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 <p11-kit/uri.h>
31 struct gnutls_pkcs11_privkey_st
33 gnutls_pk_algorithm_t pk_algorithm
;
35 struct p11_kit_uri
*info
;
36 gnutls_pkcs11_pin_callback_t pin_func
;
41 * gnutls_pkcs11_privkey_init:
42 * @key: The structure to be initialized
44 * This function will initialize an private key structure.
46 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
47 * negative error value.
50 gnutls_pkcs11_privkey_init (gnutls_pkcs11_privkey_t
* key
)
52 *key
= gnutls_calloc (1, sizeof (struct gnutls_pkcs11_privkey_st
));
56 return GNUTLS_E_MEMORY_ERROR
;
59 (*key
)->info
= p11_kit_uri_new ();
60 if ((*key
)->info
== NULL
)
64 return GNUTLS_E_MEMORY_ERROR
;
71 * gnutls_pkcs11_privkey_deinit:
72 * @key: The structure to be initialized
74 * This function will deinitialize a private key structure.
77 gnutls_pkcs11_privkey_deinit (gnutls_pkcs11_privkey_t key
)
79 p11_kit_uri_free (key
->info
);
84 * gnutls_pkcs11_privkey_get_pk_algorithm:
85 * @key: should contain a #gnutls_pkcs11_privkey_t structure
86 * @bits: if bits is non null it will hold the size of the parameters' in bits
88 * This function will return the public key algorithm of a private
91 * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
92 * success, or a negative error code on error.
95 gnutls_pkcs11_privkey_get_pk_algorithm (gnutls_pkcs11_privkey_t key
,
99 *bits
= 0; /* FIXME */
100 return key
->pk_algorithm
;
104 * gnutls_pkcs11_privkey_get_info:
105 * @pkey: should contain a #gnutls_pkcs11_privkey_t structure
106 * @itype: Denotes the type of information requested
107 * @output: where output will be stored
108 * @output_size: contains the maximum size of the output and will be overwritten with actual
110 * This function will return information about the PKCS 11 private key such
111 * as the label, id as well as token information where the key is stored. When
112 * output is text it returns null terminated string although #output_size contains
113 * the size of the actual data only.
115 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
118 gnutls_pkcs11_privkey_get_info (gnutls_pkcs11_privkey_t pkey
,
119 gnutls_pkcs11_obj_info_t itype
,
120 void *output
, size_t * output_size
)
122 return pkcs11_get_info (pkey
->info
, itype
, output
, output_size
);
126 #define FIND_OBJECT(module, pks, obj, key) \
130 ret = pkcs11_find_object (&module, &pks, &obj, key->info, \
132 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { \
135 rret = pkcs11_call_token_func (key->info, retries++); \
136 if (rret == 0) continue; \
138 return gnutls_assert_val(ret); \
139 } else if (ret < 0) { \
140 return gnutls_assert_val(ret); \
145 * _gnutls_pkcs11_privkey_sign_hash:
146 * @key: Holds the key
147 * @hash: holds the data to be signed (should be output of a hash)
148 * @signature: will contain the signature allocated with gnutls_malloc()
150 * This function will sign the given data using a signature algorithm
151 * supported by the private key. It is assumed that the given data
152 * are the output of a hash function.
154 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
155 * negative error value.
158 _gnutls_pkcs11_privkey_sign_hash (gnutls_pkcs11_privkey_t key
,
159 const gnutls_datum_t
* hash
,
160 gnutls_datum_t
* signature
)
164 struct ck_mechanism mech
;
165 unsigned long siglen
;
166 struct ck_function_list
*module
;
167 ck_session_handle_t pks
;
168 ck_object_handle_t obj
;
170 FIND_OBJECT (module
, pks
, obj
, key
);
172 mech
.mechanism
= pk_to_mech(key
->pk_algorithm
);
173 mech
.parameter
= NULL
;
174 mech
.parameter_len
= 0;
176 /* Initialize signing operation; using the private key discovered
178 rv
= pkcs11_sign_init (module
, pks
, &mech
, obj
);
182 ret
= pkcs11_rv_to_err (rv
);
186 /* Work out how long the signature must be: */
187 rv
= pkcs11_sign (module
, pks
, hash
->data
, hash
->size
, NULL
, &siglen
);
191 ret
= pkcs11_rv_to_err (rv
);
195 signature
->data
= gnutls_malloc (siglen
);
196 signature
->size
= siglen
;
198 rv
= pkcs11_sign (module
, pks
, hash
->data
, hash
->size
, signature
->data
, &siglen
);
201 gnutls_free (signature
->data
);
203 ret
= pkcs11_rv_to_err (rv
);
207 signature
->size
= siglen
;
212 pkcs11_close_session (module
, pks
);
218 * gnutls_pkcs11_privkey_import_url:
219 * @pkey: The structure to store the parsed key
220 * @url: a PKCS 11 url identifying the key
221 * @flags: sequence of GNUTLS_PKCS_PRIVKEY_*
223 * This function will "import" a PKCS 11 URL identifying a private
224 * key to the #gnutls_pkcs11_privkey_t structure. In reality since
225 * in most cases keys cannot be exported, the private key structure
226 * is being associated with the available operations on the token.
228 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
229 * negative error value.
232 gnutls_pkcs11_privkey_import_url (gnutls_pkcs11_privkey_t pkey
,
233 const char *url
, unsigned int flags
)
236 struct ck_function_list
*module
;
237 struct ck_attribute
*attr
;
238 ck_session_handle_t pks
;
239 ck_object_handle_t obj
;
240 struct ck_attribute a
[4];
241 ck_key_type_t key_type
;
243 ret
= pkcs11_url_to_info (url
, &pkey
->info
);
252 attr
= p11_kit_uri_get_attribute (pkey
->info
, CKA_CLASS
);
253 if (!attr
|| attr
->value_len
!= sizeof (ck_object_class_t
) ||
254 *(ck_object_class_t
*)attr
->value
!= CKO_PRIVATE_KEY
)
257 return GNUTLS_E_INVALID_REQUEST
;
260 attr
= p11_kit_uri_get_attribute (pkey
->info
, CKA_ID
);
261 if (!attr
|| !attr
->value_len
)
264 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
;
267 FIND_OBJECT (module
, pks
, obj
, pkey
);
268 a
[0].type
= CKA_KEY_TYPE
;
269 a
[0].value
= &key_type
;
270 a
[0].value_len
= sizeof (key_type
);
272 if (pkcs11_get_attribute_value (module
, pks
, obj
, a
, 1) == CKR_OK
)
274 pkey
->pk_algorithm
= mech_to_pk(key_type
);
275 if (pkey
->pk_algorithm
== GNUTLS_PK_UNKNOWN
)
277 _gnutls_debug_log("Cannot determine PKCS #11 key algorithm\n");
278 ret
= GNUTLS_E_UNKNOWN_ALGORITHM
;
286 pkcs11_close_session (module
, pks
);
292 * _gnutls_pkcs11_privkey_decrypt_data:
293 * @key: Holds the key
294 * @flags: should be 0 for now
295 * @ciphertext: holds the data to be signed
296 * @plaintext: will contain the plaintext, allocated with gnutls_malloc()
298 * This function will decrypt the given data using the public key algorithm
299 * supported by the private key.
301 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
302 * negative error value.
305 _gnutls_pkcs11_privkey_decrypt_data (gnutls_pkcs11_privkey_t key
,
307 const gnutls_datum_t
* ciphertext
,
308 gnutls_datum_t
* plaintext
)
312 struct ck_mechanism mech
;
313 unsigned long siglen
;
314 struct ck_function_list
*module
;
315 ck_session_handle_t pks
;
316 ck_object_handle_t obj
;
318 FIND_OBJECT (module
, pks
, obj
, key
);
320 if (key
->pk_algorithm
!= GNUTLS_PK_RSA
)
321 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST
);
323 mech
.mechanism
= CKM_RSA_PKCS
;
324 mech
.parameter
= NULL
;
325 mech
.parameter_len
= 0;
327 /* Initialize signing operation; using the private key discovered
329 rv
= pkcs11_decrypt_init (module
, pks
, &mech
, obj
);
333 ret
= pkcs11_rv_to_err (rv
);
337 /* Work out how long the plaintext must be: */
338 rv
= pkcs11_decrypt (module
, pks
, ciphertext
->data
, ciphertext
->size
,
343 ret
= pkcs11_rv_to_err (rv
);
347 plaintext
->data
= gnutls_malloc (siglen
);
348 plaintext
->size
= siglen
;
350 rv
= pkcs11_decrypt (module
, pks
, ciphertext
->data
, ciphertext
->size
,
351 plaintext
->data
, &siglen
);
354 gnutls_free (plaintext
->data
);
356 ret
= pkcs11_rv_to_err (rv
);
360 plaintext
->size
= siglen
;
365 pkcs11_close_session (module
, pks
);
371 * gnutls_pkcs11_privkey_export_url:
372 * @key: Holds the PKCS 11 key
373 * @detailed: non zero if a detailed URL is required
374 * @url: will contain an allocated url
376 * This function will export a URL identifying the given key.
378 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
379 * negative error value.
382 gnutls_pkcs11_privkey_export_url (gnutls_pkcs11_privkey_t key
,
383 gnutls_pkcs11_url_type_t detailed
,
388 ret
= pkcs11_info_to_url (key
->info
, detailed
, url
);
400 * gnutls_pkcs11_privkey_generate:
402 * @pk: the public key algorithm
403 * @bits: the security bits
405 * @flags: should be zero
407 * This function will generate a private key in the specified
408 * by the @url token. The pivate key will be generate within
409 * the token and will not be exportable.
411 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
412 * negative error value.
417 gnutls_pkcs11_privkey_generate (const char* url
,
418 gnutls_pk_algorithm_t pk
, unsigned int bits
,
419 const char* label
, unsigned int flags
)
422 const ck_bool_t tval
= 1;
423 const ck_bool_t fval
= 0;
424 struct ck_function_list
*module
;
425 ck_session_handle_t pks
= 0;
426 struct p11_kit_uri
*info
= NULL
;
428 struct ck_attribute a
[10], p
[10];
429 ck_object_handle_t pub
, priv
;
430 unsigned long _bits
= bits
;
432 struct ck_mechanism mech
;
434 ret
= pkcs11_url_to_info (url
, &info
);
442 pkcs11_open_session (&module
, &pks
, info
,
443 SESSION_WRITE
| pkcs11_obj_flags_to_int (flags
));
444 p11_kit_uri_free (info
);
452 /* a holds the public key template
453 * and p the private key */
455 mech
.parameter
= NULL
;
456 mech
.parameter_len
= 0;
457 mech
.mechanism
= pk_to_genmech(pk
);
462 p
[p_val
].type
= CKA_DECRYPT
;
463 p
[p_val
].value
= (void*)&tval
;
464 p
[p_val
].value_len
= sizeof (tval
);
467 p
[p_val
].type
= CKA_SIGN
;
468 p
[p_val
].value
= (void*)&tval
;
469 p
[p_val
].value_len
= sizeof (tval
);
472 a
[a_val
].type
= CKA_ENCRYPT
;
473 a
[a_val
].value
= (void*)&tval
;
474 a
[a_val
].value_len
= sizeof (tval
);
477 a
[a_val
].type
= CKA_VERIFY
;
478 a
[a_val
].value
= (void*)&tval
;
479 a
[a_val
].value_len
= sizeof (tval
);
482 a
[a_val
].type
= CKA_MODULUS_BITS
;
483 a
[a_val
].value
= &_bits
;
484 a
[a_val
].value_len
= sizeof (_bits
);
488 p
[p_val
].type
= CKA_SIGN
;
489 p
[p_val
].value
= (void*)&tval
;
490 p
[p_val
].value_len
= sizeof (tval
);
493 a
[a_val
].type
= CKA_VERIFY
;
494 a
[a_val
].value
= (void*)&tval
;
495 a
[a_val
].value_len
= sizeof (tval
);
498 a
[a_val
].type
= CKA_MODULUS_BITS
;
499 a
[a_val
].value
= &_bits
;
500 a
[a_val
].value_len
= sizeof (_bits
);
504 p
[p_val
].type
= CKA_SIGN
;
505 p
[p_val
].value
= (void*)&tval
;
506 p
[p_val
].value_len
= sizeof (tval
);
509 a
[a_val
].type
= CKA_VERIFY
;
510 a
[a_val
].value
= (void*)&tval
;
511 a
[a_val
].value_len
= sizeof (tval
);
514 a
[a_val
].type
= CKA_MODULUS_BITS
;
515 a
[a_val
].value
= &_bits
;
516 a
[a_val
].value_len
= sizeof (_bits
);
520 ret
= gnutls_assert_val(GNUTLS_E_INVALID_REQUEST
);
524 /* a private key is set always as private unless
525 * requested otherwise
527 if (flags
& GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE
)
529 p
[p_val
].type
= CKA_PRIVATE
;
530 p
[p_val
].value
= (void*)&fval
;
531 p
[p_val
].value_len
= sizeof(fval
);
536 p
[p_val
].type
= CKA_PRIVATE
;
537 p
[p_val
].value
= (void*)&tval
;
538 p
[p_val
].value_len
= sizeof (tval
);
542 p
[p_val
].type
= CKA_TOKEN
;
543 p
[p_val
].value
= (void *)&tval
;
544 p
[p_val
].value_len
= sizeof (tval
);
549 p
[p_val
].type
= CKA_LABEL
;
550 p
[p_val
].value
= (void*)label
;
551 p
[p_val
].value_len
= strlen (label
);
554 a
[a_val
].type
= CKA_LABEL
;
555 a
[a_val
].value
= (void*)label
;
556 a
[a_val
].value_len
= strlen (label
);
560 if (flags
& GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE
)
562 p
[p_val
].type
= CKA_SENSITIVE
;
563 p
[p_val
].value
= (void*)&tval
;
564 p
[p_val
].value_len
= sizeof (tval
);
569 p
[p_val
].type
= CKA_SENSITIVE
;
570 p
[p_val
].value
= (void*)&fval
;
571 p
[p_val
].value_len
= sizeof (fval
);
575 rv
= pkcs11_generate_key_pair( module
, pks
, &mech
, a
, a_val
, p
, p_val
, &pub
, &priv
);
579 _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv
));
580 ret
= pkcs11_rv_to_err (rv
);
587 pkcs11_close_session (module
, pks
);