blob: 92120c6ce630636a213da12965dc35ae0649475f [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>
32#include <pkcs11.h>
33
34#include "mbedtls/pkcs11_client.h"
35
36#if defined(MBEDTLS_PLATFORM_C)
37#include "mbedtls/platform.h"
38#else
39#include <stdlib.h>
40#define mbedtls_calloc calloc
41#define mbedtls_free free
42#endif
43
44
45
46#if defined(MBEDTLS_PK_C)
47#include "mbedtls/pk.h"
48#include "mbedtls/pk_info.h"
49
50#if defined(MBEDTLS_ECDSA_C)
51#include "mbedtls/asn1.h"
52#include "mbedtls/asn1write.h"
53#include "mbedtls/bignum.h"
54#include "mbedtls/ecdsa.h"
55#include "mbedtls/ecp.h"
56#include "mbedtls/oid.h"
57#endif
58
59#define ARRAY_LENGTH( a ) ( sizeof( a ) / sizeof( *( a ) ) )
60
61typedef struct {
62 mbedtls_pk_type_t key_type; /**< key type */
63 CK_SESSION_HANDLE hSession; /**< session handle */
64 CK_OBJECT_HANDLE hPublicKey; /**< public key handle (must not be null) */
65 CK_OBJECT_HANDLE hPrivateKey; /**< private key handle (may be null) */
66 uint16_t bit_length; /**< key length in bits */
67} mbedtls_pk_pkcs11_context_t;
68
69static int pkcs11_err_to_mbedtls_pk_err( CK_RV rv )
70{
71 switch( rv )
72 {
73 case CKR_OK:
74 return( 0 );
75 case CKR_HOST_MEMORY:
76 return( MBEDTLS_ERR_PK_ALLOC_FAILED );
77 case CKR_ARGUMENTS_BAD:
78 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
79 case CKR_KEY_FUNCTION_NOT_PERMITTED:
80 return( MBEDTLS_ERR_PK_NOT_PERMITTED );
81 case CKR_MECHANISM_INVALID:
82 return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
83 case CKR_MECHANISM_PARAM_INVALID:
84 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
85 case CKR_OBJECT_HANDLE_INVALID:
86 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
87 case CKR_SIGNATURE_INVALID:
88 return( MBEDTLS_ERR_PK_INVALID_SIGNATURE );
89 case CKR_SIGNATURE_LEN_RANGE:
90 return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH );
91 case CKR_TEMPLATE_INCOMPLETE:
92 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
93 case CKR_BUFFER_TOO_SMALL:
94 return( MBEDTLS_ERR_PK_BUFFER_TOO_SMALL );
95 default:
96 return( MBEDTLS_ERR_PK_FILE_IO_ERROR );
97 }
98}
99
100static size_t pkcs11_pk_get_bitlen( const void *ctx_arg )
101{
102 const mbedtls_pk_pkcs11_context_t *ctx = ctx_arg;
103 return( ctx->bit_length );
104}
105
106static int pkcs11_pk_can_do( const void *ctx_arg, mbedtls_pk_type_t type )
107{
108 const mbedtls_pk_pkcs11_context_t *ctx = ctx_arg;
109 return ctx->key_type == mbedtls_pk_representation_type( type );
110}
111
112static void *pkcs11_pk_alloc( )
113{
114 return( mbedtls_calloc( 1, sizeof( mbedtls_pk_pkcs11_context_t ) ) );
115}
116
117static void pkcs11_pk_free( void *ctx )
118{
119 mbedtls_free( ctx );
120}
121
122static size_t pkcs11_pk_signature_size( const void *ctx_arg )
123{
124 const mbedtls_pk_pkcs11_context_t *ctx = ctx_arg;
125 switch( ctx->key_type )
126 {
127 case MBEDTLS_PK_RSA:
128 return( ( ctx->bit_length + 7 ) / 8 );
129 case MBEDTLS_PK_ECKEY:
130 return( MBEDTLS_ECDSA_MAX_SIG_LEN( ctx->bit_length ) );
131 default:
132 return( 0 );
133 }
134}
135
136static int pkcs11_sign( void *ctx_arg,
137 mbedtls_md_type_t md_alg,
138 const unsigned char *hash, size_t hash_len,
139 unsigned char *sig, size_t *sig_len,
140 int (*f_rng)(void *, unsigned char *, size_t),
141 void *p_rng )
142{
143 mbedtls_pk_pkcs11_context_t *ctx = ctx_arg;
144 CK_RV rv;
145 CK_MECHANISM mechanism = {0, NULL_PTR, 0};
146 CK_ULONG ck_sig_len;
147
148 /* This function takes size_t arguments but the underlying layer
149 takes unsigned long. Either type may be smaller than the other.
150 Legitimate values won't overflow either type but we still need
151 to check for overflow for robustness. */
152 if( hash_len > (CK_ULONG)( -1 ) )
153 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
154 (void) f_rng;
155 (void) p_rng;
156
157 switch( ctx->key_type )
158 {
159#if defined(MBEDTLS_ECDSA_C)
160 case MBEDTLS_PK_ECKEY:
161 ck_sig_len = MBEDTLS_ECDSA_MAX_SIG_LEN( ctx->bit_length );
162 mechanism.mechanism = CKM_ECDSA;
163 break;
164#endif /* MBEDTLS_ECDSA_C */
165 default:
166 return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
167 }
168
169 rv = C_SignInit( ctx->hSession, &mechanism, ctx->hPrivateKey );
170 if( rv != CKR_OK )
171 goto exit;
172 rv = C_Sign( ctx->hSession, (CK_BYTE_PTR) hash, hash_len,
173 sig, &ck_sig_len );
174 if( rv != CKR_OK )
175 goto exit;
176
177 if( mechanism.mechanism == CKM_ECDSA )
178 {
179 /* The signature from the token contains r and s concatenated,
180 * each in the form of a big-endian byte sequence, with r and s
181 * having the same length as the base point.
182 *
183 * A standard ECDSA signature is encoded in ASN.1:
184 * 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. */
212 if( ecdsa_signature_to_asn1( &r, &s, sig, sig_len, sig_size ) != 0 )
213 {
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
234static const mbedtls_pk_info_t mbedtls_pk_pkcs11_info =
235 MBEDTLS_PK_OPAQUE_INFO_1( "pkcs11"
236 , pkcs11_pk_get_bitlen
237 , pkcs11_pk_can_do //can_do
238 , pkcs11_pk_signature_size
239 , NULL //pkcs11_verify
240 , pkcs11_sign
241 , NULL //pkcs11_decrypt
242 , NULL //pkcs11_encrypt
243 , NULL //check_pair_func
244 , pkcs11_pk_alloc
245 , pkcs11_pk_free
246 , NULL //debug_func
247 );
248
249int mbedtls_pk_setup_pkcs11( mbedtls_pk_context *ctx,
250 CK_SESSION_HANDLE hSession,
251 CK_OBJECT_HANDLE hPublicKey,
252 CK_OBJECT_HANDLE hPrivateKey )
253{
254 CK_OBJECT_CLASS public_key_class = -1, private_key_class = -1;
255 CK_KEY_TYPE public_key_type = -1, private_key_type = -1;
256 mbedtls_pk_type_t can_do;
257 CK_ATTRIBUTE attributes[] = {
258 {CKA_CLASS, &public_key_class, sizeof( public_key_class )},
259 {CKA_KEY_TYPE, &public_key_type, sizeof( public_key_type )},
260 };
261 CK_RV rv;
262 uint16_t key_size = 0;
263
264 rv = C_GetAttributeValue( hSession, hPublicKey,
265 attributes, ARRAY_LENGTH( attributes ) );
266 if( rv != CKR_OK )
267 return( pkcs11_err_to_mbedtls_pk_err( rv ) );
268 if( public_key_class != CKO_PUBLIC_KEY )
269 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
270
271 if( hPrivateKey != CK_INVALID_HANDLE )
272 {
273 attributes[0].pValue = &private_key_class;
274 attributes[1].pValue = &private_key_type;
275 rv = C_GetAttributeValue( hSession, hPrivateKey,
276 attributes, ARRAY_LENGTH( attributes ) );
277 if( rv != CKR_OK )
278 return( pkcs11_err_to_mbedtls_pk_err( rv ) );
279 if( private_key_class != CKO_PRIVATE_KEY )
280 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
281 if( public_key_type != private_key_type )
282 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
283 }
284
285 switch( public_key_type ) {
286#if defined(MBEDTLS_ECDSA_C)
287 case CKK_ECDSA:
288 can_do = MBEDTLS_PK_ECKEY;
289 {
290 unsigned char ecParams[16];
291 mbedtls_asn1_buf params_asn1;
292 mbedtls_ecp_group_id grp_id;
293 const mbedtls_ecp_curve_info *curve_info;
294 attributes[0].type = CKA_EC_PARAMS;
295 attributes[0].pValue = ecParams;
296 attributes[0].ulValueLen = sizeof( ecParams );
297 rv = C_GetAttributeValue( hSession, hPrivateKey, attributes, 1 );
298 if( rv != CKR_OK )
299 return( pkcs11_err_to_mbedtls_pk_err( rv ) );
300 params_asn1.tag = ecParams[0];
301 params_asn1.len = ecParams[1];
302 params_asn1.p = ecParams + 2;
303 if( mbedtls_oid_get_ec_grp( &params_asn1, &grp_id ) != 0 )
304 return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE );
305 curve_info = mbedtls_ecp_curve_info_from_grp_id( grp_id );
306 if( curve_info == NULL )
307 return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE );
308 key_size = curve_info->bit_size;
309 }
310 break;
311#endif /* MBEDTLS_ECDSA_C */
312 default:
313 can_do = MBEDTLS_PK_OPAQUE;
314 break;
315 }
316
317 {
318 int ret = mbedtls_pk_setup( ctx, &mbedtls_pk_pkcs11_info );
319 if( ret != 0 )
320 return( MBEDTLS_ERR_PK_ALLOC_FAILED );
321 }
322 {
323 mbedtls_pk_pkcs11_context_t *pkcs11_ctx = ctx->pk_ctx;
324 pkcs11_ctx->key_type = can_do;
325 pkcs11_ctx->bit_length = key_size;
326 pkcs11_ctx->hSession = hSession;
327 pkcs11_ctx->hPublicKey = hPublicKey;
328 pkcs11_ctx->hPrivateKey = hPrivateKey;
329 }
330 return( 0 );
331}
332
333#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C)
334static int mpi_to_ck( const mbedtls_mpi *mpi,
335 CK_ATTRIBUTE *attr, CK_ATTRIBUTE_TYPE at,
336 unsigned char **p, size_t len )
337{
338 if( mbedtls_mpi_write_binary( mpi, *p, len ) != 0 )
339 return( 0 );
340 attr->type = at;
341 attr->pValue = *p;
342 attr->ulValueLen = len;
343 *p += len;
344 return( 1 );
345}
346#define MPI_TO_CK( mpi, attr, at, p, len ) \
347 do \
348 { \
349 if( !mpi_to_ck( ( mpi ), ( attr ), ( at ), ( p ), ( len ) ) ) \
350 { \
351 rv = CKR_ARGUMENTS_BAD; \
352 goto exit; \
353 } \
354 } \
355 while( 0 )
356#endif /* defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) */
357
358#define CK_BOOL( x ) ( ( x ) ? CK_TRUE : CK_FALSE )
359
360int mbedtls_pk_import_to_pkcs11( const mbedtls_pk_context *ctx,
361 uint32_t flags,
362 CK_SESSION_HANDLE hSession,
363 CK_OBJECT_HANDLE *hPublicKey,
364 CK_OBJECT_HANDLE *hPrivateKey )
365{
366 CK_OBJECT_CLASS cko_private_key = CKO_PRIVATE_KEY;
367 CK_OBJECT_CLASS cko_public_key = CKO_PUBLIC_KEY;
368 CK_KEY_TYPE ck_key_type;
369 CK_BBOOL ck_sensitive = CK_BOOL( flags & MBEDTLS_PK_FLAG_SENSITIVE );
370 CK_BBOOL ck_extractable = CK_BOOL( flags & MBEDTLS_PK_FLAG_EXTRACTABLE );
371 CK_BBOOL ck_sign = CK_BOOL( flags & MBEDTLS_PK_FLAG_SIGN );
372 CK_BBOOL ck_verify = CK_BOOL( flags & MBEDTLS_PK_FLAG_VERIFY );
373 CK_BBOOL ck_decrypt = CK_BOOL( flags & MBEDTLS_PK_FLAG_DECRYPT );
374 CK_BBOOL ck_encrypt = CK_BOOL( flags & MBEDTLS_PK_FLAG_ENCRYPT );
375 CK_BBOOL ck_token = CK_BOOL( flags & MBEDTLS_PKCS11_FLAG_TOKEN );
376 CK_ATTRIBUTE public_attributes[] = {
377 {CKA_CLASS, &cko_public_key, sizeof( cko_public_key )},
378 {CKA_KEY_TYPE, &ck_key_type, sizeof( ck_key_type )},
379 {CKA_TOKEN, &ck_token, sizeof( ck_token )},
380 {CKA_ENCRYPT, &ck_encrypt, sizeof( ck_encrypt )},
381 {CKA_VERIFY, &ck_verify, sizeof( ck_verify )},
382#define COMMON_PUBLIC_ATTRIBUTES 5 // number of attributes above
383 {-1, NULL, 0},
384 {-1, NULL, 0},
385 };
386 CK_ATTRIBUTE private_attributes[] = {
387 {CKA_CLASS, &cko_private_key, sizeof( cko_private_key )},
388 {CKA_KEY_TYPE, &ck_key_type, sizeof( ck_key_type )},
389 {CKA_TOKEN, &ck_token, sizeof( ck_token )},
390 {CKA_DECRYPT, &ck_decrypt, sizeof( ck_decrypt )},
391 {CKA_SIGN, &ck_sign, sizeof( ck_sign )},
392 {CKA_SENSITIVE, &ck_sensitive, sizeof( ck_sensitive )},
393 {CKA_EXTRACTABLE, &ck_extractable, sizeof( ck_extractable )},
394#define COMMON_PRIVATE_ATTRIBUTES 7 // number of attributes above
395 {-1, NULL, 0},
396 {-1, NULL, 0},
397 {-1, NULL, 0},
398 {-1, NULL, 0},
399 {-1, NULL, 0},
400 {-1, NULL, 0},
401 {-1, NULL, 0},
402 {-1, NULL, 0},
403 };
404 CK_ATTRIBUTE *public_end = public_attributes + COMMON_PUBLIC_ATTRIBUTES;
405 CK_ATTRIBUTE *private_end = private_attributes + COMMON_PRIVATE_ATTRIBUTES;
406#undef COMMON_PUBLIC_ATTRIBUTES
407#undef COMMON_PRIVATE_ATTRIBUTES
408 unsigned char *data = NULL;
409 CK_RV rv;
410
411 if( hPublicKey != NULL )
412 *hPublicKey = CK_INVALID_HANDLE;
413 if( hPrivateKey != NULL )
414 *hPrivateKey = CK_INVALID_HANDLE;
415
416 /* Prepare the data-dependent key attributes */
417 switch( mbedtls_pk_representation_type( mbedtls_pk_get_type( ctx ) ) )
418 {
419#if defined(MBEDTLS_ECDSA_C)
420 case MBEDTLS_PK_ECKEY:
421 {
422 const mbedtls_ecp_keypair *ec = mbedtls_pk_ec( *ctx );
423 unsigned char *p;
424 size_t curve_bytes = ( ec->grp.pbits + 7 ) / 8;
425 size_t point_bytes = 4 + 2 * curve_bytes; // overapproximation
426 int format = MBEDTLS_ECP_PF_UNCOMPRESSED;
427 int ret;
428 data = mbedtls_calloc( 1,
429 MBEDTLS_OID_EC_GRP_MAX_SIZE +
430 ( hPublicKey == NULL ? 0 : point_bytes ) +
431 ( hPrivateKey == NULL ? 0 : curve_bytes ) );
432 if( data == NULL )
433 {
434 rv = CKR_HOST_MEMORY;
435 goto exit;
436 }
437 p = data;
438 ck_key_type = CKK_ECDSA;
439 /* Convert the group identifier */
440 ret = mbedtls_ecp_ansi_write_group( &ec->grp, p,
441 MBEDTLS_OID_EC_GRP_MAX_SIZE );
442 if( ret < 0 )
443 {
444 rv = CKR_GENERAL_ERROR;
445 goto exit;
446 }
447 public_end->type = CKA_EC_PARAMS;
448 public_end->pValue = p;
449 public_end->ulValueLen = ret;
450 p += ret;
451 *private_end++ = *public_end++;
452 if( hPublicKey != NULL )
453 {
454 /* Convert the public point */
455 ret = mbedtls_ecp_ansi_write_point( ec, format, p, point_bytes );
456 if( ret < 0 )
457 {
458 rv = CKR_GENERAL_ERROR;
459 goto exit;
460 }
461 public_end->type = CKA_EC_POINT;
462 public_end->pValue = p;
463 public_end->ulValueLen = ret;
464 p += ret;
465 public_end++;
466 }
467 if( hPrivateKey != NULL )
468 {
469 /* Convert the private value */
470 MPI_TO_CK( &ec->d, private_end++, CKA_VALUE, &p, curve_bytes );
471 }
472 }
473 break;
474#endif /* MBEDTLS_ECDSA_C */
475 default:
476 return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
477 }
478
479 if( hPublicKey != NULL )
480 {
481 *hPublicKey = CK_INVALID_HANDLE;
482 rv = C_CreateObject( hSession,
483 public_attributes,
484 public_end - public_attributes,
485 hPublicKey );
486 if( rv != CKR_OK )
487 goto exit;
488 }
489
490 if( hPrivateKey != NULL )
491 {
492 rv = C_CreateObject( hSession,
493 private_attributes,
494 private_end - private_attributes,
495 hPrivateKey );
496 if( rv != CKR_OK )
497 goto exit;
498 }
499
500exit:
501 if( rv != CKR_OK )
502 {
503 /* In case an error happened, destroy any object that we
504 created. In case C_DestroyObject failed, we report the original
505 error, but *hPublicKey may contain a valid handle if
506 creating the private key failed and then destroying the public key
507 also failed (e.g. because the token disconnected). */
508 if( hPublicKey != NULL && *hPublicKey != CK_INVALID_HANDLE )
509 {
510 if( C_DestroyObject( hSession, *hPublicKey ) == CKR_OK )
511 *hPublicKey = CK_INVALID_HANDLE;
512 }
513 if( hPrivateKey != NULL && *hPrivateKey != CK_INVALID_HANDLE )
514 {
515 if( C_DestroyObject( hSession, *hPrivateKey ) == CKR_OK )
516 *hPrivateKey = CK_INVALID_HANDLE;
517 }
518 }
519 mbedtls_free( data );
520 return( pkcs11_err_to_mbedtls_pk_err( rv ) );
521}
522
523#endif /* MBEDTLS_PK_C */
524
525
526
527#endif /* MBEDTLS_PKCS11_CLIENT_C */