documented update
[gnutls.git] / lib / pkcs11_privkey.c
blobccec17ed9b9887ce3736e600c93fb0fcf4444d06
1 /*
2 * GnuTLS PKCS#11 support
3 * Copyright (C) 2010-2012 Free Software Foundation, Inc.
4 *
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>
23 #include <stdio.h>
24 #include <string.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;
34 unsigned int flags;
35 struct p11_kit_uri *info;
36 gnutls_pkcs11_pin_callback_t pin_func;
37 void *pin_data;
40 /**
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.
48 **/
49 int
50 gnutls_pkcs11_privkey_init (gnutls_pkcs11_privkey_t * key)
52 *key = gnutls_calloc (1, sizeof (struct gnutls_pkcs11_privkey_st));
53 if (*key == NULL)
55 gnutls_assert ();
56 return GNUTLS_E_MEMORY_ERROR;
59 (*key)->info = p11_kit_uri_new ();
60 if ((*key)->info == NULL)
62 free (*key);
63 gnutls_assert ();
64 return GNUTLS_E_MEMORY_ERROR;
67 return 0;
70 /**
71 * gnutls_pkcs11_privkey_deinit:
72 * @key: The structure to be initialized
74 * This function will deinitialize a private key structure.
75 **/
76 void
77 gnutls_pkcs11_privkey_deinit (gnutls_pkcs11_privkey_t key)
79 p11_kit_uri_free (key->info);
80 gnutls_free (key);
83 /**
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
89 * key.
91 * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
92 * success, or a negative error code on error.
93 **/
94 int
95 gnutls_pkcs11_privkey_get_pk_algorithm (gnutls_pkcs11_privkey_t key,
96 unsigned int *bits)
98 if (bits)
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) \
127 do { \
128 int retries = 0; \
129 int rret; \
130 ret = pkcs11_find_object (&module, &pks, &obj, key->info, \
131 SESSION_LOGIN); \
132 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { \
133 if (token_func) \
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); \
142 } while (0);
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)
162 ck_rv_t rv;
163 int ret;
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
177 * earlier. */
178 rv = pkcs11_sign_init (module, pks, &mech, obj);
179 if (rv != CKR_OK)
181 gnutls_assert ();
182 ret = pkcs11_rv_to_err (rv);
183 goto cleanup;
186 /* Work out how long the signature must be: */
187 rv = pkcs11_sign (module, pks, hash->data, hash->size, NULL, &siglen);
188 if (rv != CKR_OK)
190 gnutls_assert ();
191 ret = pkcs11_rv_to_err (rv);
192 goto cleanup;
195 signature->data = gnutls_malloc (siglen);
196 signature->size = siglen;
198 rv = pkcs11_sign (module, pks, hash->data, hash->size, signature->data, &siglen);
199 if (rv != CKR_OK)
201 gnutls_free (signature->data);
202 gnutls_assert ();
203 ret = pkcs11_rv_to_err (rv);
204 goto cleanup;
207 signature->size = siglen;
209 ret = 0;
211 cleanup:
212 pkcs11_close_session (module, pks);
214 return ret;
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)
235 int ret;
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);
244 if (ret < 0)
246 gnutls_assert ();
247 return ret;
250 pkey->flags = flags;
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)
256 gnutls_assert ();
257 return GNUTLS_E_INVALID_REQUEST;
260 attr = p11_kit_uri_get_attribute (pkey->info, CKA_ID);
261 if (!attr || !attr->value_len)
263 attr = p11_kit_uri_get_attribute (pkey->info, CKA_LABEL);
264 if (!attr || !attr->value_len)
266 gnutls_assert ();
267 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
271 FIND_OBJECT (module, pks, obj, pkey);
272 a[0].type = CKA_KEY_TYPE;
273 a[0].value = &key_type;
274 a[0].value_len = sizeof (key_type);
276 if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
278 pkey->pk_algorithm = mech_to_pk(key_type);
279 if (pkey->pk_algorithm == GNUTLS_PK_UNKNOWN)
281 _gnutls_debug_log("Cannot determine PKCS #11 key algorithm\n");
282 ret = GNUTLS_E_UNKNOWN_ALGORITHM;
283 goto cleanup;
287 ret = 0;
289 cleanup:
290 pkcs11_close_session (module, pks);
292 return ret;
296 * _gnutls_pkcs11_privkey_decrypt_data:
297 * @key: Holds the key
298 * @flags: should be 0 for now
299 * @ciphertext: holds the data to be signed
300 * @plaintext: will contain the plaintext, allocated with gnutls_malloc()
302 * This function will decrypt the given data using the public key algorithm
303 * supported by the private key.
305 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
306 * negative error value.
309 _gnutls_pkcs11_privkey_decrypt_data (gnutls_pkcs11_privkey_t key,
310 unsigned int flags,
311 const gnutls_datum_t * ciphertext,
312 gnutls_datum_t * plaintext)
314 ck_rv_t rv;
315 int ret;
316 struct ck_mechanism mech;
317 unsigned long siglen;
318 struct ck_function_list *module;
319 ck_session_handle_t pks;
320 ck_object_handle_t obj;
322 FIND_OBJECT (module, pks, obj, key);
324 if (key->pk_algorithm != GNUTLS_PK_RSA)
325 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
327 mech.mechanism = CKM_RSA_PKCS;
328 mech.parameter = NULL;
329 mech.parameter_len = 0;
331 /* Initialize signing operation; using the private key discovered
332 * earlier. */
333 rv = pkcs11_decrypt_init (module, pks, &mech, obj);
334 if (rv != CKR_OK)
336 gnutls_assert ();
337 ret = pkcs11_rv_to_err (rv);
338 goto cleanup;
341 /* Work out how long the plaintext must be: */
342 rv = pkcs11_decrypt (module, pks, ciphertext->data, ciphertext->size,
343 NULL, &siglen);
344 if (rv != CKR_OK)
346 gnutls_assert ();
347 ret = pkcs11_rv_to_err (rv);
348 goto cleanup;
351 plaintext->data = gnutls_malloc (siglen);
352 plaintext->size = siglen;
354 rv = pkcs11_decrypt (module, pks, ciphertext->data, ciphertext->size,
355 plaintext->data, &siglen);
356 if (rv != CKR_OK)
358 gnutls_free (plaintext->data);
359 gnutls_assert ();
360 ret = pkcs11_rv_to_err (rv);
361 goto cleanup;
364 plaintext->size = siglen;
366 ret = 0;
368 cleanup:
369 pkcs11_close_session (module, pks);
371 return ret;
375 * gnutls_pkcs11_privkey_export_url:
376 * @key: Holds the PKCS 11 key
377 * @detailed: non zero if a detailed URL is required
378 * @url: will contain an allocated url
380 * This function will export a URL identifying the given key.
382 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
383 * negative error value.
386 gnutls_pkcs11_privkey_export_url (gnutls_pkcs11_privkey_t key,
387 gnutls_pkcs11_url_type_t detailed,
388 char **url)
390 int ret;
392 ret = pkcs11_info_to_url (key->info, detailed, url);
393 if (ret < 0)
395 gnutls_assert ();
396 return ret;
399 return 0;
404 * gnutls_pkcs11_privkey_generate:
405 * @url: a token URL
406 * @pk: the public key algorithm
407 * @bits: the security bits
408 * @label: a label
409 * @flags: should be zero
411 * This function will generate a private key in the specified
412 * by the @url token. The pivate key will be generate within
413 * the token and will not be exportable.
415 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
416 * negative error value.
418 * Since: 3.0
421 gnutls_pkcs11_privkey_generate (const char* url,
422 gnutls_pk_algorithm_t pk, unsigned int bits,
423 const char* label, unsigned int flags)
425 int ret;
426 const ck_bool_t tval = 1;
427 const ck_bool_t fval = 0;
428 struct ck_function_list *module;
429 ck_session_handle_t pks = 0;
430 struct p11_kit_uri *info = NULL;
431 ck_rv_t rv;
432 struct ck_attribute a[10], p[10];
433 ck_object_handle_t pub, priv;
434 unsigned long _bits = bits;
435 int a_val, p_val;
436 struct ck_mechanism mech;
438 ret = pkcs11_url_to_info (url, &info);
439 if (ret < 0)
441 gnutls_assert ();
442 return ret;
445 ret =
446 pkcs11_open_session (&module, &pks, info,
447 SESSION_WRITE | pkcs11_obj_flags_to_int (flags));
448 p11_kit_uri_free (info);
450 if (ret < 0)
452 gnutls_assert ();
453 goto cleanup;
456 /* a holds the public key template
457 * and p the private key */
458 a_val = p_val = 0;
459 mech.parameter = NULL;
460 mech.parameter_len = 0;
461 mech.mechanism = pk_to_genmech(pk);
463 switch(pk)
465 case GNUTLS_PK_RSA:
466 p[p_val].type = CKA_DECRYPT;
467 p[p_val].value = (void*)&tval;
468 p[p_val].value_len = sizeof (tval);
469 p_val++;
471 p[p_val].type = CKA_SIGN;
472 p[p_val].value = (void*)&tval;
473 p[p_val].value_len = sizeof (tval);
474 p_val++;
476 a[a_val].type = CKA_ENCRYPT;
477 a[a_val].value = (void*)&tval;
478 a[a_val].value_len = sizeof (tval);
479 a_val++;
481 a[a_val].type = CKA_VERIFY;
482 a[a_val].value = (void*)&tval;
483 a[a_val].value_len = sizeof (tval);
484 a_val++;
486 a[a_val].type = CKA_MODULUS_BITS;
487 a[a_val].value = &_bits;
488 a[a_val].value_len = sizeof (_bits);
489 a_val++;
490 break;
491 case GNUTLS_PK_DSA:
492 p[p_val].type = CKA_SIGN;
493 p[p_val].value = (void*)&tval;
494 p[p_val].value_len = sizeof (tval);
495 p_val++;
497 a[a_val].type = CKA_VERIFY;
498 a[a_val].value = (void*)&tval;
499 a[a_val].value_len = sizeof (tval);
500 a_val++;
502 a[a_val].type = CKA_MODULUS_BITS;
503 a[a_val].value = &_bits;
504 a[a_val].value_len = sizeof (_bits);
505 a_val++;
506 break;
507 case GNUTLS_PK_EC:
508 p[p_val].type = CKA_SIGN;
509 p[p_val].value = (void*)&tval;
510 p[p_val].value_len = sizeof (tval);
511 p_val++;
513 a[a_val].type = CKA_VERIFY;
514 a[a_val].value = (void*)&tval;
515 a[a_val].value_len = sizeof (tval);
516 a_val++;
518 a[a_val].type = CKA_MODULUS_BITS;
519 a[a_val].value = &_bits;
520 a[a_val].value_len = sizeof (_bits);
521 a_val++;
522 break;
523 default:
524 ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
525 goto cleanup;
528 /* a private key is set always as private unless
529 * requested otherwise
531 if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE)
533 p[p_val].type = CKA_PRIVATE;
534 p[p_val].value = (void*)&fval;
535 p[p_val].value_len = sizeof(fval);
536 p_val++;
538 else
540 p[p_val].type = CKA_PRIVATE;
541 p[p_val].value = (void*)&tval;
542 p[p_val].value_len = sizeof (tval);
543 p_val++;
546 p[p_val].type = CKA_TOKEN;
547 p[p_val].value = (void *)&tval;
548 p[p_val].value_len = sizeof (tval);
549 p_val++;
551 if (label)
553 p[p_val].type = CKA_LABEL;
554 p[p_val].value = (void*)label;
555 p[p_val].value_len = strlen (label);
556 p_val++;
558 a[a_val].type = CKA_LABEL;
559 a[a_val].value = (void*)label;
560 a[a_val].value_len = strlen (label);
561 a_val++;
564 if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE)
566 p[p_val].type = CKA_SENSITIVE;
567 p[p_val].value = (void*)&tval;
568 p[p_val].value_len = sizeof (tval);
569 p_val++;
571 else
573 p[p_val].type = CKA_SENSITIVE;
574 p[p_val].value = (void*)&fval;
575 p[p_val].value_len = sizeof (fval);
576 p_val++;
579 rv = pkcs11_generate_key_pair( module, pks, &mech, a, a_val, p, p_val, &pub, &priv);
580 if (rv != CKR_OK)
582 gnutls_assert ();
583 _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv));
584 ret = pkcs11_rv_to_err (rv);
585 goto cleanup;
589 cleanup:
590 if (pks != 0)
591 pkcs11_close_session (module, pks);
593 return ret;