2 * GnuTLS PKCS#11 support
3 * Copyright (C) 2010-2012 Free Software Foundation, Inc.
5 * Authors: Nikos Mavrogiannopoulos, Stef Walter
7 * The GnuTLS is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation; either version 3 of
10 * the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>
21 #include <gnutls_int.h>
22 #include <gnutls/pkcs11.h>
25 #include <gnutls_errors.h>
26 #include <gnutls_datum.h>
27 #include <pkcs11_int.h>
28 #include <gnutls_sig.h>
29 #include <gnutls_pk.h>
30 #include <p11-kit/uri.h>
32 struct gnutls_pkcs11_privkey_st
34 gnutls_pk_algorithm_t pk_algorithm
;
36 struct p11_kit_uri
*info
;
37 gnutls_pkcs11_pin_callback_t pin_func
;
42 * gnutls_pkcs11_privkey_init:
43 * @key: The structure to be initialized
45 * This function will initialize an private key structure.
47 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
48 * negative error value.
51 gnutls_pkcs11_privkey_init (gnutls_pkcs11_privkey_t
* key
)
53 *key
= gnutls_calloc (1, sizeof (struct gnutls_pkcs11_privkey_st
));
57 return GNUTLS_E_MEMORY_ERROR
;
60 (*key
)->info
= p11_kit_uri_new ();
61 if ((*key
)->info
== NULL
)
65 return GNUTLS_E_MEMORY_ERROR
;
72 * gnutls_pkcs11_privkey_deinit:
73 * @key: The structure to be initialized
75 * This function will deinitialize a private key structure.
78 gnutls_pkcs11_privkey_deinit (gnutls_pkcs11_privkey_t key
)
80 p11_kit_uri_free (key
->info
);
85 * gnutls_pkcs11_privkey_get_pk_algorithm:
86 * @key: should contain a #gnutls_pkcs11_privkey_t structure
87 * @bits: if bits is non null it will hold the size of the parameters' in bits
89 * This function will return the public key algorithm of a private
92 * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
93 * success, or a negative error code on error.
96 gnutls_pkcs11_privkey_get_pk_algorithm (gnutls_pkcs11_privkey_t key
,
100 *bits
= 0; /* FIXME */
101 return key
->pk_algorithm
;
105 * gnutls_pkcs11_privkey_get_info:
106 * @pkey: should contain a #gnutls_pkcs11_privkey_t structure
107 * @itype: Denotes the type of information requested
108 * @output: where output will be stored
109 * @output_size: contains the maximum size of the output and will be overwritten with actual
111 * This function will return information about the PKCS 11 private key such
112 * as the label, id as well as token information where the key is stored. When
113 * output is text it returns null terminated string although #output_size contains
114 * the size of the actual data only.
116 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
119 gnutls_pkcs11_privkey_get_info (gnutls_pkcs11_privkey_t pkey
,
120 gnutls_pkcs11_obj_info_t itype
,
121 void *output
, size_t * output_size
)
123 return pkcs11_get_info (pkey
->info
, itype
, output
, output_size
);
127 #define FIND_OBJECT(module, pks, obj, key) \
131 ret = pkcs11_find_object (&module, &pks, &obj, key->info, \
133 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { \
136 rret = pkcs11_call_token_func (key->info, retries++); \
137 if (rret == 0) continue; \
139 return gnutls_assert_val(ret); \
140 } else if (ret < 0) { \
141 return gnutls_assert_val(ret); \
146 static int read_rs(bigint_t
*r
, bigint_t
*s
, uint8_t *data
, size_t data_size
)
148 unsigned int dhalf
= data_size
/2;
150 if (_gnutls_mpi_scan_nz (r
, data
, dhalf
) != 0)
151 return gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED
);
153 if (_gnutls_mpi_scan_nz (s
, &data
[dhalf
], dhalf
) != 0)
155 _gnutls_mpi_release(r
);
156 return gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED
);
163 * _gnutls_pkcs11_privkey_sign_hash:
164 * @key: Holds the key
165 * @hash: holds the data to be signed (should be output of a hash)
166 * @signature: will contain the signature allocated with gnutls_malloc()
168 * This function will sign the given data using a signature algorithm
169 * supported by the private key. It is assumed that the given data
170 * are the output of a hash function.
172 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
173 * negative error value.
176 _gnutls_pkcs11_privkey_sign_hash (gnutls_pkcs11_privkey_t key
,
177 const gnutls_datum_t
* hash
,
178 gnutls_datum_t
* signature
)
182 struct ck_mechanism mech
;
183 unsigned long siglen
;
184 struct ck_function_list
*module
;
185 ck_session_handle_t pks
;
186 ck_object_handle_t obj
;
188 FIND_OBJECT (module
, pks
, obj
, key
);
190 mech
.mechanism
= pk_to_mech(key
->pk_algorithm
);
191 mech
.parameter
= NULL
;
192 mech
.parameter_len
= 0;
194 /* Initialize signing operation; using the private key discovered
196 rv
= pkcs11_sign_init (module
, pks
, &mech
, obj
);
200 ret
= pkcs11_rv_to_err (rv
);
204 /* Work out how long the signature must be: */
205 rv
= pkcs11_sign (module
, pks
, hash
->data
, hash
->size
, NULL
, &siglen
);
209 ret
= pkcs11_rv_to_err (rv
);
213 signature
->data
= gnutls_malloc (siglen
);
214 signature
->size
= siglen
;
216 rv
= pkcs11_sign (module
, pks
, hash
->data
, hash
->size
, signature
->data
, &siglen
);
219 gnutls_free (signature
->data
);
221 ret
= pkcs11_rv_to_err (rv
);
225 signature
->size
= siglen
;
227 if (key
->pk_algorithm
== GNUTLS_PK_EC
|| key
->pk_algorithm
== GNUTLS_PK_DSA
)
234 ret
= GNUTLS_E_PK_SIGN_FAILED
;
238 ret
= read_rs(&r
, &s
, signature
->data
, signature
->size
);
245 gnutls_free(signature
->data
);
246 ret
= _gnutls_encode_ber_rs (signature
, r
, s
);
247 _gnutls_mpi_release(&r
);
248 _gnutls_mpi_release(&s
);
260 pkcs11_close_session (module
, pks
);
266 * gnutls_pkcs11_privkey_import_url:
267 * @pkey: The structure to store the parsed key
268 * @url: a PKCS 11 url identifying the key
269 * @flags: sequence of GNUTLS_PKCS_PRIVKEY_*
271 * This function will "import" a PKCS 11 URL identifying a private
272 * key to the #gnutls_pkcs11_privkey_t structure. In reality since
273 * in most cases keys cannot be exported, the private key structure
274 * is being associated with the available operations on the token.
276 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
277 * negative error value.
280 gnutls_pkcs11_privkey_import_url (gnutls_pkcs11_privkey_t pkey
,
281 const char *url
, unsigned int flags
)
284 struct ck_function_list
*module
;
285 struct ck_attribute
*attr
;
286 ck_session_handle_t pks
;
287 ck_object_handle_t obj
;
288 struct ck_attribute a
[4];
289 ck_key_type_t key_type
;
291 ret
= pkcs11_url_to_info (url
, &pkey
->info
);
300 attr
= p11_kit_uri_get_attribute (pkey
->info
, CKA_CLASS
);
301 if (!attr
|| attr
->value_len
!= sizeof (ck_object_class_t
) ||
302 *(ck_object_class_t
*)attr
->value
!= CKO_PRIVATE_KEY
)
305 return GNUTLS_E_INVALID_REQUEST
;
308 attr
= p11_kit_uri_get_attribute (pkey
->info
, CKA_ID
);
309 if (!attr
|| !attr
->value_len
)
311 attr
= p11_kit_uri_get_attribute (pkey
->info
, CKA_LABEL
);
312 if (!attr
|| !attr
->value_len
)
315 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
;
319 FIND_OBJECT (module
, pks
, obj
, pkey
);
320 a
[0].type
= CKA_KEY_TYPE
;
321 a
[0].value
= &key_type
;
322 a
[0].value_len
= sizeof (key_type
);
324 if (pkcs11_get_attribute_value (module
, pks
, obj
, a
, 1) == CKR_OK
)
326 pkey
->pk_algorithm
= mech_to_pk(key_type
);
327 if (pkey
->pk_algorithm
== GNUTLS_PK_UNKNOWN
)
329 _gnutls_debug_log("Cannot determine PKCS #11 key algorithm\n");
330 ret
= GNUTLS_E_UNKNOWN_ALGORITHM
;
338 pkcs11_close_session (module
, pks
);
344 * _gnutls_pkcs11_privkey_decrypt_data:
345 * @key: Holds the key
346 * @flags: should be 0 for now
347 * @ciphertext: holds the data to be signed
348 * @plaintext: will contain the plaintext, allocated with gnutls_malloc()
350 * This function will decrypt the given data using the public key algorithm
351 * supported by the private key.
353 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
354 * negative error value.
357 _gnutls_pkcs11_privkey_decrypt_data (gnutls_pkcs11_privkey_t key
,
359 const gnutls_datum_t
* ciphertext
,
360 gnutls_datum_t
* plaintext
)
364 struct ck_mechanism mech
;
365 unsigned long siglen
;
366 struct ck_function_list
*module
;
367 ck_session_handle_t pks
;
368 ck_object_handle_t obj
;
370 FIND_OBJECT (module
, pks
, obj
, key
);
372 if (key
->pk_algorithm
!= GNUTLS_PK_RSA
)
373 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST
);
375 mech
.mechanism
= CKM_RSA_PKCS
;
376 mech
.parameter
= NULL
;
377 mech
.parameter_len
= 0;
379 /* Initialize signing operation; using the private key discovered
381 rv
= pkcs11_decrypt_init (module
, pks
, &mech
, obj
);
385 ret
= pkcs11_rv_to_err (rv
);
389 /* Work out how long the plaintext must be: */
390 rv
= pkcs11_decrypt (module
, pks
, ciphertext
->data
, ciphertext
->size
,
395 ret
= pkcs11_rv_to_err (rv
);
399 plaintext
->data
= gnutls_malloc (siglen
);
400 plaintext
->size
= siglen
;
402 rv
= pkcs11_decrypt (module
, pks
, ciphertext
->data
, ciphertext
->size
,
403 plaintext
->data
, &siglen
);
406 gnutls_free (plaintext
->data
);
408 ret
= pkcs11_rv_to_err (rv
);
412 plaintext
->size
= siglen
;
417 pkcs11_close_session (module
, pks
);
423 * gnutls_pkcs11_privkey_export_url:
424 * @key: Holds the PKCS 11 key
425 * @detailed: non zero if a detailed URL is required
426 * @url: will contain an allocated url
428 * This function will export a URL identifying the given key.
430 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
431 * negative error value.
434 gnutls_pkcs11_privkey_export_url (gnutls_pkcs11_privkey_t key
,
435 gnutls_pkcs11_url_type_t detailed
,
440 ret
= pkcs11_info_to_url (key
->info
, detailed
, url
);
452 * gnutls_pkcs11_privkey_generate:
454 * @pk: the public key algorithm
455 * @bits: the security bits
457 * @flags: should be zero
459 * This function will generate a private key in the specified
460 * by the @url token. The pivate key will be generate within
461 * the token and will not be exportable.
463 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
464 * negative error value.
469 gnutls_pkcs11_privkey_generate (const char* url
,
470 gnutls_pk_algorithm_t pk
, unsigned int bits
,
471 const char* label
, unsigned int flags
)
474 const ck_bool_t tval
= 1;
475 const ck_bool_t fval
= 0;
476 struct ck_function_list
*module
;
477 ck_session_handle_t pks
= 0;
478 struct p11_kit_uri
*info
= NULL
;
480 struct ck_attribute a
[10], p
[10];
481 ck_object_handle_t pub
, priv
;
482 unsigned long _bits
= bits
;
484 struct ck_mechanism mech
;
486 ret
= pkcs11_url_to_info (url
, &info
);
494 pkcs11_open_session (&module
, &pks
, info
,
495 SESSION_WRITE
| pkcs11_obj_flags_to_int (flags
));
496 p11_kit_uri_free (info
);
504 /* a holds the public key template
505 * and p the private key */
507 mech
.parameter
= NULL
;
508 mech
.parameter_len
= 0;
509 mech
.mechanism
= pk_to_genmech(pk
);
514 p
[p_val
].type
= CKA_DECRYPT
;
515 p
[p_val
].value
= (void*)&tval
;
516 p
[p_val
].value_len
= sizeof (tval
);
519 p
[p_val
].type
= CKA_SIGN
;
520 p
[p_val
].value
= (void*)&tval
;
521 p
[p_val
].value_len
= sizeof (tval
);
524 a
[a_val
].type
= CKA_ENCRYPT
;
525 a
[a_val
].value
= (void*)&tval
;
526 a
[a_val
].value_len
= sizeof (tval
);
529 a
[a_val
].type
= CKA_VERIFY
;
530 a
[a_val
].value
= (void*)&tval
;
531 a
[a_val
].value_len
= sizeof (tval
);
534 a
[a_val
].type
= CKA_MODULUS_BITS
;
535 a
[a_val
].value
= &_bits
;
536 a
[a_val
].value_len
= sizeof (_bits
);
540 p
[p_val
].type
= CKA_SIGN
;
541 p
[p_val
].value
= (void*)&tval
;
542 p
[p_val
].value_len
= sizeof (tval
);
545 a
[a_val
].type
= CKA_VERIFY
;
546 a
[a_val
].value
= (void*)&tval
;
547 a
[a_val
].value_len
= sizeof (tval
);
550 a
[a_val
].type
= CKA_MODULUS_BITS
;
551 a
[a_val
].value
= &_bits
;
552 a
[a_val
].value_len
= sizeof (_bits
);
556 p
[p_val
].type
= CKA_SIGN
;
557 p
[p_val
].value
= (void*)&tval
;
558 p
[p_val
].value_len
= sizeof (tval
);
561 a
[a_val
].type
= CKA_VERIFY
;
562 a
[a_val
].value
= (void*)&tval
;
563 a
[a_val
].value_len
= sizeof (tval
);
566 a
[a_val
].type
= CKA_MODULUS_BITS
;
567 a
[a_val
].value
= &_bits
;
568 a
[a_val
].value_len
= sizeof (_bits
);
572 ret
= gnutls_assert_val(GNUTLS_E_INVALID_REQUEST
);
576 /* a private key is set always as private unless
577 * requested otherwise
579 if (flags
& GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE
)
581 p
[p_val
].type
= CKA_PRIVATE
;
582 p
[p_val
].value
= (void*)&fval
;
583 p
[p_val
].value_len
= sizeof(fval
);
588 p
[p_val
].type
= CKA_PRIVATE
;
589 p
[p_val
].value
= (void*)&tval
;
590 p
[p_val
].value_len
= sizeof (tval
);
594 p
[p_val
].type
= CKA_TOKEN
;
595 p
[p_val
].value
= (void *)&tval
;
596 p
[p_val
].value_len
= sizeof (tval
);
601 p
[p_val
].type
= CKA_LABEL
;
602 p
[p_val
].value
= (void*)label
;
603 p
[p_val
].value_len
= strlen (label
);
606 a
[a_val
].type
= CKA_LABEL
;
607 a
[a_val
].value
= (void*)label
;
608 a
[a_val
].value_len
= strlen (label
);
612 if (flags
& GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE
)
614 p
[p_val
].type
= CKA_SENSITIVE
;
615 p
[p_val
].value
= (void*)&tval
;
616 p
[p_val
].value_len
= sizeof (tval
);
621 p
[p_val
].type
= CKA_SENSITIVE
;
622 p
[p_val
].value
= (void*)&fval
;
623 p
[p_val
].value_len
= sizeof (fval
);
627 rv
= pkcs11_generate_key_pair( module
, pks
, &mech
, a
, a_val
, p
, p_val
, &pub
, &priv
);
631 _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv
));
632 ret
= pkcs11_rv_to_err (rv
);
639 pkcs11_close_session (module
, pks
);