no need to check for DTLS
[gnutls.git] / lib / pkcs11_privkey.c
blobf377a9d289bc37250f5aa6de4d688f96cea2ab2d
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;
39 struct pkcs11_session_info sinfo;
40 ck_object_handle_t obj; /* the key in the session */
43 /**
44 * gnutls_pkcs11_privkey_init:
45 * @key: The structure to be initialized
47 * This function will initialize an private key structure.
49 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
50 * negative error value.
51 **/
52 int
53 gnutls_pkcs11_privkey_init (gnutls_pkcs11_privkey_t * key)
55 *key = gnutls_calloc (1, sizeof (struct gnutls_pkcs11_privkey_st));
56 if (*key == NULL)
58 gnutls_assert ();
59 return GNUTLS_E_MEMORY_ERROR;
62 (*key)->info = p11_kit_uri_new ();
63 if ((*key)->info == NULL)
65 free (*key);
66 gnutls_assert ();
67 return GNUTLS_E_MEMORY_ERROR;
70 return 0;
73 /**
74 * gnutls_pkcs11_privkey_deinit:
75 * @key: The structure to be initialized
77 * This function will deinitialize a private key structure.
78 **/
79 void
80 gnutls_pkcs11_privkey_deinit (gnutls_pkcs11_privkey_t key)
82 p11_kit_uri_free (key->info);
83 if (key->sinfo.init != 0)
84 pkcs11_close_session (&key->sinfo);
85 gnutls_free (key);
88 /**
89 * gnutls_pkcs11_privkey_get_pk_algorithm:
90 * @key: should contain a #gnutls_pkcs11_privkey_t structure
91 * @bits: if bits is non null it will hold the size of the parameters' in bits
93 * This function will return the public key algorithm of a private
94 * key.
96 * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
97 * success, or a negative error code on error.
98 **/
99 int
100 gnutls_pkcs11_privkey_get_pk_algorithm (gnutls_pkcs11_privkey_t key,
101 unsigned int *bits)
103 if (bits)
104 *bits = 0; /* FIXME */
105 return key->pk_algorithm;
109 * gnutls_pkcs11_privkey_get_info:
110 * @pkey: should contain a #gnutls_pkcs11_privkey_t structure
111 * @itype: Denotes the type of information requested
112 * @output: where output will be stored
113 * @output_size: contains the maximum size of the output and will be overwritten with actual
115 * This function will return information about the PKCS 11 private key such
116 * as the label, id as well as token information where the key is stored. When
117 * output is text it returns null terminated string although #output_size contains
118 * the size of the actual data only.
120 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
123 gnutls_pkcs11_privkey_get_info (gnutls_pkcs11_privkey_t pkey,
124 gnutls_pkcs11_obj_info_t itype,
125 void *output, size_t * output_size)
127 return pkcs11_get_info (pkey->info, itype, output, output_size);
131 #define FIND_OBJECT(sinfo, obj, key) \
132 do { \
133 int retries = 0; \
134 int rret; \
135 ret = pkcs11_find_object (sinfo, &obj, key->info, \
136 SESSION_LOGIN); \
137 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { \
138 if (token_func) \
140 rret = pkcs11_call_token_func (key->info, retries++); \
141 if (rret == 0) continue; \
143 return gnutls_assert_val(ret); \
144 } else if (ret < 0) { \
145 return gnutls_assert_val(ret); \
147 } while (0);
150 * _gnutls_pkcs11_privkey_sign_hash:
151 * @key: Holds the key
152 * @hash: holds the data to be signed (should be output of a hash)
153 * @signature: will contain the signature allocated with gnutls_malloc()
155 * This function will sign the given data using a signature algorithm
156 * supported by the private key. It is assumed that the given data
157 * are the output of a hash function.
159 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
160 * negative error value.
163 _gnutls_pkcs11_privkey_sign_hash (gnutls_pkcs11_privkey_t key,
164 const gnutls_datum_t * hash,
165 gnutls_datum_t * signature)
167 ck_rv_t rv;
168 int ret;
169 struct ck_mechanism mech;
170 unsigned long siglen;
171 struct pkcs11_session_info _sinfo;
172 struct pkcs11_session_info *sinfo;
173 ck_object_handle_t obj;
175 if (key->sinfo.init != 0)
177 sinfo = &key->sinfo;
178 obj = key->obj;
180 else
182 sinfo = &_sinfo;
183 memset(sinfo, 0, sizeof(*sinfo));
184 FIND_OBJECT (sinfo, obj, key);
187 mech.mechanism = pk_to_mech(key->pk_algorithm);
188 mech.parameter = NULL;
189 mech.parameter_len = 0;
191 /* Initialize signing operation; using the private key discovered
192 * earlier. */
193 rv = pkcs11_sign_init (sinfo->module, sinfo->pks, &mech, obj);
194 if (rv != CKR_OK)
196 gnutls_assert ();
197 ret = pkcs11_rv_to_err (rv);
198 goto cleanup;
201 /* Work out how long the signature must be: */
202 rv = pkcs11_sign (sinfo->module, sinfo->pks, hash->data, hash->size, NULL, &siglen);
203 if (rv != CKR_OK)
205 gnutls_assert ();
206 ret = pkcs11_rv_to_err (rv);
207 goto cleanup;
210 signature->data = gnutls_malloc (siglen);
211 signature->size = siglen;
213 rv = pkcs11_sign (sinfo->module, sinfo->pks, hash->data, hash->size, signature->data, &siglen);
214 if (rv != CKR_OK)
216 gnutls_free (signature->data);
217 gnutls_assert ();
218 ret = pkcs11_rv_to_err (rv);
219 goto cleanup;
222 signature->size = siglen;
224 ret = 0;
226 cleanup:
227 if (sinfo != &key->sinfo)
228 pkcs11_close_session (sinfo);
230 return ret;
234 * gnutls_pkcs11_privkey_import_url:
235 * @pkey: The structure to store the parsed key
236 * @url: a PKCS 11 url identifying the key
237 * @flags: sequence of GNUTLS_PKCS_PRIVKEY_*
239 * This function will "import" a PKCS 11 URL identifying a private
240 * key to the #gnutls_pkcs11_privkey_t structure. In reality since
241 * in most cases keys cannot be exported, the private key structure
242 * is being associated with the available operations on the token.
244 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
245 * negative error value.
248 gnutls_pkcs11_privkey_import_url (gnutls_pkcs11_privkey_t pkey,
249 const char *url, unsigned int flags)
251 int ret;
252 struct ck_attribute *attr;
253 ck_object_handle_t obj;
254 struct ck_attribute a[4];
255 ck_key_type_t key_type;
256 struct pkcs11_session_info sinfo;
258 memset(&sinfo, 0, sizeof(sinfo));
260 ret = pkcs11_url_to_info (url, &pkey->info);
261 if (ret < 0)
263 gnutls_assert ();
264 return ret;
267 pkey->flags = flags;
269 attr = p11_kit_uri_get_attribute (pkey->info, CKA_CLASS);
270 if (!attr || attr->value_len != sizeof (ck_object_class_t) ||
271 *(ck_object_class_t*)attr->value != CKO_PRIVATE_KEY)
273 gnutls_assert ();
274 return GNUTLS_E_INVALID_REQUEST;
277 attr = p11_kit_uri_get_attribute (pkey->info, CKA_ID);
278 if (!attr || !attr->value_len)
280 attr = p11_kit_uri_get_attribute (pkey->info, CKA_LABEL);
281 if (!attr || !attr->value_len)
283 gnutls_assert ();
284 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
288 FIND_OBJECT (&sinfo, obj, pkey);
290 a[0].type = CKA_KEY_TYPE;
291 a[0].value = &key_type;
292 a[0].value_len = sizeof (key_type);
294 if (pkcs11_get_attribute_value (sinfo.module, sinfo.pks, obj, a, 1) == CKR_OK)
296 pkey->pk_algorithm = mech_to_pk(key_type);
297 if (pkey->pk_algorithm == GNUTLS_PK_UNKNOWN)
299 _gnutls_debug_log("Cannot determine PKCS #11 key algorithm\n");
300 ret = GNUTLS_E_UNKNOWN_ALGORITHM;
301 goto cleanup;
305 ret = 0;
307 if (pkey->sinfo.init)
308 pkcs11_close_session (&pkey->sinfo);
310 if (sinfo.tinfo.max_session_count != 1)
312 /* We do not keep the session open in tokens that can
313 * only support a single session.
315 memcpy(&pkey->sinfo, &sinfo, sizeof(pkey->sinfo));
316 pkey->obj = obj;
317 return ret;
320 cleanup:
321 pkcs11_close_session (&sinfo);
323 return ret;
327 * _gnutls_pkcs11_privkey_decrypt_data:
328 * @key: Holds the key
329 * @flags: should be 0 for now
330 * @ciphertext: holds the data to be signed
331 * @plaintext: will contain the plaintext, allocated with gnutls_malloc()
333 * This function will decrypt the given data using the public key algorithm
334 * supported by the private key.
336 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
337 * negative error value.
340 _gnutls_pkcs11_privkey_decrypt_data (gnutls_pkcs11_privkey_t key,
341 unsigned int flags,
342 const gnutls_datum_t * ciphertext,
343 gnutls_datum_t * plaintext)
345 ck_rv_t rv;
346 int ret;
347 struct ck_mechanism mech;
348 unsigned long siglen;
349 ck_object_handle_t obj;
350 struct pkcs11_session_info _sinfo;
351 struct pkcs11_session_info *sinfo;
353 if (key->sinfo.init != 0)
355 sinfo = &key->sinfo;
356 obj = key->obj;
358 else
360 sinfo = &_sinfo;
361 memset(sinfo, 0, sizeof(*sinfo));
362 FIND_OBJECT (sinfo, obj, key);
365 if (key->pk_algorithm != GNUTLS_PK_RSA)
366 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
368 mech.mechanism = CKM_RSA_PKCS;
369 mech.parameter = NULL;
370 mech.parameter_len = 0;
372 /* Initialize signing operation; using the private key discovered
373 * earlier. */
374 rv = pkcs11_decrypt_init (sinfo->module, sinfo->pks, &mech, obj);
375 if (rv != CKR_OK)
377 gnutls_assert ();
378 ret = pkcs11_rv_to_err (rv);
379 goto cleanup;
382 /* Work out how long the plaintext must be: */
383 rv = pkcs11_decrypt (sinfo->module, sinfo->pks, ciphertext->data, ciphertext->size,
384 NULL, &siglen);
385 if (rv != CKR_OK)
387 gnutls_assert ();
388 ret = pkcs11_rv_to_err (rv);
389 goto cleanup;
392 plaintext->data = gnutls_malloc (siglen);
393 plaintext->size = siglen;
395 rv = pkcs11_decrypt (sinfo->module, sinfo->pks, ciphertext->data, ciphertext->size,
396 plaintext->data, &siglen);
397 if (rv != CKR_OK)
399 gnutls_free (plaintext->data);
400 gnutls_assert ();
401 ret = pkcs11_rv_to_err (rv);
402 goto cleanup;
405 plaintext->size = siglen;
407 ret = 0;
409 cleanup:
410 if (key->sinfo.init == 0)
411 pkcs11_close_session (sinfo);
413 return ret;
417 * gnutls_pkcs11_privkey_export_url:
418 * @key: Holds the PKCS 11 key
419 * @detailed: non zero if a detailed URL is required
420 * @url: will contain an allocated url
422 * This function will export a URL identifying the given key.
424 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
425 * negative error value.
428 gnutls_pkcs11_privkey_export_url (gnutls_pkcs11_privkey_t key,
429 gnutls_pkcs11_url_type_t detailed,
430 char **url)
432 int ret;
434 ret = pkcs11_info_to_url (key->info, detailed, url);
435 if (ret < 0)
437 gnutls_assert ();
438 return ret;
441 return 0;
446 * gnutls_pkcs11_privkey_generate:
447 * @url: a token URL
448 * @pk: the public key algorithm
449 * @bits: the security bits
450 * @label: a label
451 * @flags: should be zero
453 * This function will generate a private key in the specified
454 * by the @url token. The pivate key will be generate within
455 * the token and will not be exportable.
457 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
458 * negative error value.
460 * Since: 3.0
463 gnutls_pkcs11_privkey_generate (const char* url,
464 gnutls_pk_algorithm_t pk, unsigned int bits,
465 const char* label, unsigned int flags)
467 int ret;
468 const ck_bool_t tval = 1;
469 const ck_bool_t fval = 0;
470 struct pkcs11_session_info sinfo;
471 struct p11_kit_uri *info = NULL;
472 ck_rv_t rv;
473 struct ck_attribute a[10], p[10];
474 ck_object_handle_t pub, priv;
475 unsigned long _bits = bits;
476 int a_val, p_val;
477 struct ck_mechanism mech;
479 memset(&sinfo, 0, sizeof(sinfo));
481 ret = pkcs11_url_to_info (url, &info);
482 if (ret < 0)
484 gnutls_assert ();
485 return ret;
488 ret =
489 pkcs11_open_session (&sinfo, info,
490 SESSION_WRITE | pkcs11_obj_flags_to_int (flags));
491 p11_kit_uri_free (info);
493 if (ret < 0)
495 gnutls_assert ();
496 goto cleanup;
499 /* a holds the public key template
500 * and p the private key */
501 a_val = p_val = 0;
502 mech.parameter = NULL;
503 mech.parameter_len = 0;
504 mech.mechanism = pk_to_genmech(pk);
506 switch(pk)
508 case GNUTLS_PK_RSA:
509 p[p_val].type = CKA_DECRYPT;
510 p[p_val].value = (void*)&tval;
511 p[p_val].value_len = sizeof (tval);
512 p_val++;
514 p[p_val].type = CKA_SIGN;
515 p[p_val].value = (void*)&tval;
516 p[p_val].value_len = sizeof (tval);
517 p_val++;
519 a[a_val].type = CKA_ENCRYPT;
520 a[a_val].value = (void*)&tval;
521 a[a_val].value_len = sizeof (tval);
522 a_val++;
524 a[a_val].type = CKA_VERIFY;
525 a[a_val].value = (void*)&tval;
526 a[a_val].value_len = sizeof (tval);
527 a_val++;
529 a[a_val].type = CKA_MODULUS_BITS;
530 a[a_val].value = &_bits;
531 a[a_val].value_len = sizeof (_bits);
532 a_val++;
533 break;
534 case GNUTLS_PK_DSA:
535 p[p_val].type = CKA_SIGN;
536 p[p_val].value = (void*)&tval;
537 p[p_val].value_len = sizeof (tval);
538 p_val++;
540 a[a_val].type = CKA_VERIFY;
541 a[a_val].value = (void*)&tval;
542 a[a_val].value_len = sizeof (tval);
543 a_val++;
545 a[a_val].type = CKA_MODULUS_BITS;
546 a[a_val].value = &_bits;
547 a[a_val].value_len = sizeof (_bits);
548 a_val++;
549 break;
550 case GNUTLS_PK_EC:
551 p[p_val].type = CKA_SIGN;
552 p[p_val].value = (void*)&tval;
553 p[p_val].value_len = sizeof (tval);
554 p_val++;
556 a[a_val].type = CKA_VERIFY;
557 a[a_val].value = (void*)&tval;
558 a[a_val].value_len = sizeof (tval);
559 a_val++;
561 a[a_val].type = CKA_MODULUS_BITS;
562 a[a_val].value = &_bits;
563 a[a_val].value_len = sizeof (_bits);
564 a_val++;
565 break;
566 default:
567 ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
568 goto cleanup;
571 /* a private key is set always as private unless
572 * requested otherwise
574 if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE)
576 p[p_val].type = CKA_PRIVATE;
577 p[p_val].value = (void*)&fval;
578 p[p_val].value_len = sizeof(fval);
579 p_val++;
581 else
583 p[p_val].type = CKA_PRIVATE;
584 p[p_val].value = (void*)&tval;
585 p[p_val].value_len = sizeof (tval);
586 p_val++;
589 p[p_val].type = CKA_TOKEN;
590 p[p_val].value = (void *)&tval;
591 p[p_val].value_len = sizeof (tval);
592 p_val++;
594 if (label)
596 p[p_val].type = CKA_LABEL;
597 p[p_val].value = (void*)label;
598 p[p_val].value_len = strlen (label);
599 p_val++;
601 a[a_val].type = CKA_LABEL;
602 a[a_val].value = (void*)label;
603 a[a_val].value_len = strlen (label);
604 a_val++;
607 if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE)
609 p[p_val].type = CKA_SENSITIVE;
610 p[p_val].value = (void*)&tval;
611 p[p_val].value_len = sizeof (tval);
612 p_val++;
614 else
616 p[p_val].type = CKA_SENSITIVE;
617 p[p_val].value = (void*)&fval;
618 p[p_val].value_len = sizeof (fval);
619 p_val++;
622 rv = pkcs11_generate_key_pair( sinfo.module, sinfo.pks, &mech, a, a_val, p, p_val, &pub, &priv);
623 if (rv != CKR_OK)
625 gnutls_assert ();
626 _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv));
627 ret = pkcs11_rv_to_err (rv);
628 goto cleanup;
632 cleanup:
633 if (sinfo.pks != 0)
634 pkcs11_close_session (&sinfo);
636 return ret;