blob: cb803cd3c9911e1b3261e7323e1f8409c61bace8 [file] [log] [blame]
Andrzej Kurekc53dee32018-01-23 05:44:20 -05001/*
2 * Generic wrapper for Cryptoki (PKCS#11) support
3 *
4 * Copyright (C) 2017, ARM Limited, All Rights Reserved
5 * 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 );
194 mbedtls_mpi r, s;
195 mbedtls_mpi_init( &r );
196 mbedtls_mpi_init( &s );
197 rv = CKR_OK;
198 if( ck_sig_len != 2 * byte_len )
199 {
200 /* Bad data from the token */
201 rv = CKR_GENERAL_ERROR;
202 goto ecdsa_exit;
203 }
204 if( mbedtls_mpi_read_binary( &r, sig, byte_len ) != 0 ||
205 mbedtls_mpi_read_binary( &s, sig + byte_len, byte_len ) != 0 )
206 {
207 rv = CKR_HOST_MEMORY;
208 goto ecdsa_exit;
209 }
210 /* The signature buffer is guaranteed to have enough room for
211 the encoded signature by the pk_sign interface. */
Andrzej Kurekc289bf12018-01-23 06:10:53 -0500212 if( mbedtls_ecdsa_signature_to_asn1( &r, &s, sig, sig_len, sig_size ) != 0 )
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500213 {
214 rv = CKR_GENERAL_ERROR;
215 goto ecdsa_exit;
216 }
217 ecdsa_exit:
218 mbedtls_mpi_free( &r );
219 mbedtls_mpi_free( &s );
220 if( rv != CKR_OK )
221 goto exit;
222 }
223 else
224 {
225 *sig_len = ck_sig_len;
226 }
227
228exit:
229 if( rv != CKR_OK )
230 memset( sig, 0, ck_sig_len );
231 return( pkcs11_err_to_mbedtls_pk_err( rv ) );
232}
233
Andrzej Kurekc289bf12018-01-23 06:10:53 -0500234static int pkcs11_verify( void *ctx_arg,
235 mbedtls_md_type_t md_alg,
236 const unsigned char *hash, size_t hash_len,
237 const unsigned char *sig, size_t sig_len)
238{
239 mbedtls_pk_pkcs11_context_t *ctx = ctx_arg;
240 CK_RV rv;
241 CK_MECHANISM mechanism = {0, NULL_PTR, 0};
Andrzej Kurekb03bc432018-01-23 06:25:32 -0500242 unsigned char *decoded_sig = NULL;
Andrzej Kurekc289bf12018-01-23 06:10:53 -0500243 size_t decoded_sig_len;
244
245 /* This function takes size_t arguments but the underlying layer
246 takes unsigned long. Either type may be smaller than the other.
247 Legitimate values won't overflow either type but we still need
248 to check for overflow for robustness. */
249 if( hash_len > (CK_ULONG)( -1 ) )
250 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
251
252 switch( ctx->key_type )
253 {
254#if defined(MBEDTLS_RSA_C)
255 case MBEDTLS_PK_RSA:
256 switch( md_alg )
257 {
258 case MBEDTLS_MD_MD5:
259 mechanism.mechanism = CKM_MD5_RSA_PKCS;
260 break;
261 case MBEDTLS_MD_SHA1:
262 mechanism.mechanism = CKM_SHA1_RSA_PKCS;
263 break;
264 case MBEDTLS_MD_SHA256:
265 mechanism.mechanism = CKM_SHA256_RSA_PKCS;
266 break;
267 case MBEDTLS_MD_SHA384:
268 mechanism.mechanism = CKM_SHA384_RSA_PKCS;
269 break;
270 case MBEDTLS_MD_SHA512:
271 mechanism.mechanism = CKM_SHA512_RSA_PKCS;
272 break;
273 default:
274 return( MBEDTLS_ERR_PK_INVALID_ALG );
275 }
276 break;
277#endif /* MBEDTLS_RSA_C */
278#if defined(MBEDTLS_ECDSA_C)
279 case MBEDTLS_PK_ECKEY:
280 mechanism.mechanism = CKM_ECDSA;
281 break;
282#endif /* MBEDTLS_ECDSA_C */
283 default:
284 return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
285 }
286 if( mechanism.mechanism == CKM_ECDSA )
287 {
288 uint16_t byte_len = ( ( ctx->bit_length + 7 ) / 8 );
Andrzej Kurekb03bc432018-01-23 06:25:32 -0500289 decoded_sig = mbedtls_calloc( 1, 2 * byte_len );
290 if( decoded_sig == NULL )
291 {
292 return( MBEDTLS_ERR_PK_ALLOC_FAILED );
293 }
Andrzej Kurekc289bf12018-01-23 06:10:53 -0500294 if( mbedtls_ecdsa_signature_to_raw( sig, sig_len, byte_len,
Andrzej Kurekb03bc432018-01-23 06:25:32 -0500295 decoded_sig, 2 * byte_len,
296 &decoded_sig_len ) != 0 )
Andrzej Kurekc289bf12018-01-23 06:10:53 -0500297 {
298 rv = CKR_GENERAL_ERROR;
299 goto exit;
300 }
301 }
302 rv = C_VerifyInit( ctx->hSession, &mechanism, ctx->hPublicKey );
303 if( rv != CKR_OK )
304 goto exit;
305 rv = C_Verify( ctx->hSession, (CK_BYTE_PTR) hash, hash_len,
306 decoded_sig, decoded_sig_len );
307 if( rv != CKR_OK )
308 goto exit;
309
310exit:
Andrzej Kurekb03bc432018-01-23 06:25:32 -0500311 mbedtls_free(decoded_sig);
Andrzej Kurekc289bf12018-01-23 06:10:53 -0500312 return( pkcs11_err_to_mbedtls_pk_err( rv ) );
313}
314
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500315static const mbedtls_pk_info_t mbedtls_pk_pkcs11_info =
316 MBEDTLS_PK_OPAQUE_INFO_1( "pkcs11"
317 , pkcs11_pk_get_bitlen
Andrzej Kureke1f26b82018-02-19 03:57:07 -0500318 , pkcs11_pk_can_do
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500319 , pkcs11_pk_signature_size
Andrzej Kurekc289bf12018-01-23 06:10:53 -0500320 , pkcs11_verify
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500321 , pkcs11_sign
322 , NULL //pkcs11_decrypt
323 , NULL //pkcs11_encrypt
324 , NULL //check_pair_func
325 , pkcs11_pk_alloc
326 , pkcs11_pk_free
327 , NULL //debug_func
328 );
329
Andrzej Kurek12603542018-02-19 04:06:05 -0500330int mbedtls_pkcs11_setup_pk( mbedtls_pk_context *ctx,
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500331 CK_SESSION_HANDLE hSession,
332 CK_OBJECT_HANDLE hPublicKey,
333 CK_OBJECT_HANDLE hPrivateKey )
334{
335 CK_OBJECT_CLASS public_key_class = -1, private_key_class = -1;
336 CK_KEY_TYPE public_key_type = -1, private_key_type = -1;
337 mbedtls_pk_type_t can_do;
338 CK_ATTRIBUTE attributes[] = {
339 {CKA_CLASS, &public_key_class, sizeof( public_key_class )},
340 {CKA_KEY_TYPE, &public_key_type, sizeof( public_key_type )},
341 };
342 CK_RV rv;
343 uint16_t key_size = 0;
344
345 rv = C_GetAttributeValue( hSession, hPublicKey,
346 attributes, ARRAY_LENGTH( attributes ) );
347 if( rv != CKR_OK )
348 return( pkcs11_err_to_mbedtls_pk_err( rv ) );
349 if( public_key_class != CKO_PUBLIC_KEY )
350 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
351
352 if( hPrivateKey != CK_INVALID_HANDLE )
353 {
354 attributes[0].pValue = &private_key_class;
355 attributes[1].pValue = &private_key_type;
356 rv = C_GetAttributeValue( hSession, hPrivateKey,
357 attributes, ARRAY_LENGTH( attributes ) );
358 if( rv != CKR_OK )
359 return( pkcs11_err_to_mbedtls_pk_err( rv ) );
360 if( private_key_class != CKO_PRIVATE_KEY )
361 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
362 if( public_key_type != private_key_type )
363 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
364 }
365
366 switch( public_key_type ) {
367#if defined(MBEDTLS_ECDSA_C)
368 case CKK_ECDSA:
369 can_do = MBEDTLS_PK_ECKEY;
370 {
Andrzej Kurek33f56652018-02-19 04:03:11 -0500371 unsigned char ecParams[MBEDTLS_OID_EC_GRP_MAX_SIZE];
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500372 mbedtls_asn1_buf params_asn1;
373 mbedtls_ecp_group_id grp_id;
374 const mbedtls_ecp_curve_info *curve_info;
375 attributes[0].type = CKA_EC_PARAMS;
376 attributes[0].pValue = ecParams;
377 attributes[0].ulValueLen = sizeof( ecParams );
Andrzej Kurek18f53892018-01-23 06:30:09 -0500378 rv = C_GetAttributeValue( hSession, hPublicKey, attributes, 1 );
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500379 if( rv != CKR_OK )
380 return( pkcs11_err_to_mbedtls_pk_err( rv ) );
381 params_asn1.tag = ecParams[0];
382 params_asn1.len = ecParams[1];
383 params_asn1.p = ecParams + 2;
384 if( mbedtls_oid_get_ec_grp( &params_asn1, &grp_id ) != 0 )
385 return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE );
386 curve_info = mbedtls_ecp_curve_info_from_grp_id( grp_id );
387 if( curve_info == NULL )
388 return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE );
389 key_size = curve_info->bit_size;
390 }
391 break;
392#endif /* MBEDTLS_ECDSA_C */
393 default:
394 can_do = MBEDTLS_PK_OPAQUE;
395 break;
396 }
397
398 {
399 int ret = mbedtls_pk_setup( ctx, &mbedtls_pk_pkcs11_info );
400 if( ret != 0 )
401 return( MBEDTLS_ERR_PK_ALLOC_FAILED );
402 }
403 {
404 mbedtls_pk_pkcs11_context_t *pkcs11_ctx = ctx->pk_ctx;
405 pkcs11_ctx->key_type = can_do;
406 pkcs11_ctx->bit_length = key_size;
407 pkcs11_ctx->hSession = hSession;
408 pkcs11_ctx->hPublicKey = hPublicKey;
409 pkcs11_ctx->hPrivateKey = hPrivateKey;
410 }
411 return( 0 );
412}
413
414#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C)
415static int mpi_to_ck( const mbedtls_mpi *mpi,
416 CK_ATTRIBUTE *attr, CK_ATTRIBUTE_TYPE at,
417 unsigned char **p, size_t len )
418{
Andrzej Kurek9982e072018-02-19 04:07:31 -0500419 int ret = mbedtls_mpi_write_binary( mpi, *p, len );
420 if( ret != 0 )
421 return( ret );
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500422 attr->type = at;
423 attr->pValue = *p;
424 attr->ulValueLen = len;
425 *p += len;
Andrzej Kurek9982e072018-02-19 04:07:31 -0500426 return( 0 );
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500427}
Andrzej Kurek9982e072018-02-19 04:07:31 -0500428#define MPI_TO_CK( mpi, attr, at, p, len ) \
429 do \
430 { \
431 if( mpi_to_ck( ( mpi ), ( attr ), ( at ), ( p ), ( len ) ) != 0) \
432 { \
433 rv = CKR_ARGUMENTS_BAD; \
434 goto exit; \
435 } \
436 } \
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500437 while( 0 )
438#endif /* defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) */
439
Andrzej Kurek7e19f772018-02-19 04:00:27 -0500440#define MBEDTLS_PKCS11_BOOL( x ) ( ( x ) ? CK_TRUE : CK_FALSE )
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500441
Andrzej Kurek12603542018-02-19 04:06:05 -0500442int mbedtls_pkcs11_import_pk( const mbedtls_pk_context *ctx,
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500443 uint32_t flags,
444 CK_SESSION_HANDLE hSession,
445 CK_OBJECT_HANDLE *hPublicKey,
446 CK_OBJECT_HANDLE *hPrivateKey )
447{
448 CK_OBJECT_CLASS cko_private_key = CKO_PRIVATE_KEY;
449 CK_OBJECT_CLASS cko_public_key = CKO_PUBLIC_KEY;
450 CK_KEY_TYPE ck_key_type;
Andrzej Kurek7e19f772018-02-19 04:00:27 -0500451 CK_BBOOL ck_sensitive = MBEDTLS_PKCS11_BOOL( flags & MBEDTLS_PKCS11_FLAG_SENSITIVE );
452 CK_BBOOL ck_extractable = MBEDTLS_PKCS11_BOOL( flags & MBEDTLS_PKCS11_FLAG_EXTRACTABLE );
453 CK_BBOOL ck_sign = MBEDTLS_PKCS11_BOOL( flags & MBEDTLS_PKCS11_FLAG_SIGN );
454 CK_BBOOL ck_verify = MBEDTLS_PKCS11_BOOL( flags & MBEDTLS_PKCS11_FLAG_VERIFY );
455 CK_BBOOL ck_decrypt = MBEDTLS_PKCS11_BOOL( flags & MBEDTLS_PKCS11_FLAG_DECRYPT );
456 CK_BBOOL ck_encrypt = MBEDTLS_PKCS11_BOOL( flags & MBEDTLS_PKCS11_FLAG_ENCRYPT );
457 CK_BBOOL ck_token = MBEDTLS_PKCS11_BOOL( flags & MBEDTLS_PKCS11_FLAG_TOKEN );
Andrzej Kurekc53dee32018-01-23 05:44:20 -0500458 CK_ATTRIBUTE public_attributes[] = {
459 {CKA_CLASS, &cko_public_key, sizeof( cko_public_key )},
460 {CKA_KEY_TYPE, &ck_key_type, sizeof( ck_key_type )},
461 {CKA_TOKEN, &ck_token, sizeof( ck_token )},
462 {CKA_ENCRYPT, &ck_encrypt, sizeof( ck_encrypt )},
463 {CKA_VERIFY, &ck_verify, sizeof( ck_verify )},
464#define COMMON_PUBLIC_ATTRIBUTES 5 // number of attributes above
465 {-1, NULL, 0},
466 {-1, NULL, 0},
467 };
468 CK_ATTRIBUTE private_attributes[] = {
469 {CKA_CLASS, &cko_private_key, sizeof( cko_private_key )},
470 {CKA_KEY_TYPE, &ck_key_type, sizeof( ck_key_type )},
471 {CKA_TOKEN, &ck_token, sizeof( ck_token )},
472 {CKA_DECRYPT, &ck_decrypt, sizeof( ck_decrypt )},
473 {CKA_SIGN, &ck_sign, sizeof( ck_sign )},
474 {CKA_SENSITIVE, &ck_sensitive, sizeof( ck_sensitive )},
475 {CKA_EXTRACTABLE, &ck_extractable, sizeof( ck_extractable )},
476#define COMMON_PRIVATE_ATTRIBUTES 7 // number of attributes above
477 {-1, NULL, 0},
478 {-1, NULL, 0},
479 {-1, NULL, 0},
480 {-1, NULL, 0},
481 {-1, NULL, 0},
482 {-1, NULL, 0},
483 {-1, NULL, 0},
484 {-1, NULL, 0},
485 };
486 CK_ATTRIBUTE *public_end = public_attributes + COMMON_PUBLIC_ATTRIBUTES;
487 CK_ATTRIBUTE *private_end = private_attributes + COMMON_PRIVATE_ATTRIBUTES;
488#undef COMMON_PUBLIC_ATTRIBUTES
489#undef COMMON_PRIVATE_ATTRIBUTES
490 unsigned char *data = NULL;
491 CK_RV rv;
492
493 if( hPublicKey != NULL )
494 *hPublicKey = CK_INVALID_HANDLE;
495 if( hPrivateKey != NULL )
496 *hPrivateKey = CK_INVALID_HANDLE;
497
498 /* Prepare the data-dependent key attributes */
499 switch( mbedtls_pk_representation_type( mbedtls_pk_get_type( ctx ) ) )
500 {
501#if defined(MBEDTLS_ECDSA_C)
502 case MBEDTLS_PK_ECKEY:
503 {
504 const mbedtls_ecp_keypair *ec = mbedtls_pk_ec( *ctx );
505 unsigned char *p;
506 size_t curve_bytes = ( ec->grp.pbits + 7 ) / 8;
507 size_t point_bytes = 4 + 2 * curve_bytes; // overapproximation
508 int format = MBEDTLS_ECP_PF_UNCOMPRESSED;
509 int ret;
510 data = mbedtls_calloc( 1,
511 MBEDTLS_OID_EC_GRP_MAX_SIZE +
512 ( hPublicKey == NULL ? 0 : point_bytes ) +
513 ( hPrivateKey == NULL ? 0 : curve_bytes ) );
514 if( data == NULL )
515 {
516 rv = CKR_HOST_MEMORY;
517 goto exit;
518 }
519 p = data;
520 ck_key_type = CKK_ECDSA;
521 /* Convert the group identifier */
522 ret = mbedtls_ecp_ansi_write_group( &ec->grp, p,
523 MBEDTLS_OID_EC_GRP_MAX_SIZE );
524 if( ret < 0 )
525 {
526 rv = CKR_GENERAL_ERROR;
527 goto exit;
528 }
529 public_end->type = CKA_EC_PARAMS;
530 public_end->pValue = p;
531 public_end->ulValueLen = ret;
532 p += ret;
533 *private_end++ = *public_end++;
534 if( hPublicKey != NULL )
535 {
536 /* Convert the public point */
537 ret = mbedtls_ecp_ansi_write_point( ec, format, p, point_bytes );
538 if( ret < 0 )
539 {
540 rv = CKR_GENERAL_ERROR;
541 goto exit;
542 }
543 public_end->type = CKA_EC_POINT;
544 public_end->pValue = p;
545 public_end->ulValueLen = ret;
546 p += ret;
547 public_end++;
548 }
549 if( hPrivateKey != NULL )
550 {
551 /* Convert the private value */
552 MPI_TO_CK( &ec->d, private_end++, CKA_VALUE, &p, curve_bytes );
553 }
554 }
555 break;
556#endif /* MBEDTLS_ECDSA_C */
557 default:
558 return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
559 }
560
561 if( hPublicKey != NULL )
562 {
563 *hPublicKey = CK_INVALID_HANDLE;
564 rv = C_CreateObject( hSession,
565 public_attributes,
566 public_end - public_attributes,
567 hPublicKey );
568 if( rv != CKR_OK )
569 goto exit;
570 }
571
572 if( hPrivateKey != NULL )
573 {
574 rv = C_CreateObject( hSession,
575 private_attributes,
576 private_end - private_attributes,
577 hPrivateKey );
578 if( rv != CKR_OK )
579 goto exit;
580 }
581
582exit:
583 if( rv != CKR_OK )
584 {
585 /* In case an error happened, destroy any object that we
586 created. In case C_DestroyObject failed, we report the original
587 error, but *hPublicKey may contain a valid handle if
588 creating the private key failed and then destroying the public key
589 also failed (e.g. because the token disconnected). */
590 if( hPublicKey != NULL && *hPublicKey != CK_INVALID_HANDLE )
591 {
592 if( C_DestroyObject( hSession, *hPublicKey ) == CKR_OK )
593 *hPublicKey = CK_INVALID_HANDLE;
594 }
595 if( hPrivateKey != NULL && *hPrivateKey != CK_INVALID_HANDLE )
596 {
597 if( C_DestroyObject( hSession, *hPrivateKey ) == CKR_OK )
598 *hPrivateKey = CK_INVALID_HANDLE;
599 }
600 }
601 mbedtls_free( data );
602 return( pkcs11_err_to_mbedtls_pk_err( rv ) );
603}
604
605#endif /* MBEDTLS_PK_C */
606
607
608
609#endif /* MBEDTLS_PKCS11_CLIENT_C */