Made error code consistent with the other text parsing functions.
[gnutls.git] / lib / pkcs11_privkey.c
blob4e90657722af72841382a956ec1cf256e896363a
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 <gnutls_pk.h>
30 #include <p11-kit/uri.h>
32 struct gnutls_pkcs11_privkey_st
34 gnutls_pk_algorithm_t pk_algorithm;
35 unsigned int flags;
36 struct p11_kit_uri *info;
38 struct pkcs11_session_info sinfo;
39 ck_object_handle_t obj; /* the key in the session */
41 struct pin_info_st pin;
44 /**
45 * gnutls_pkcs11_privkey_init:
46 * @key: The structure to be initialized
48 * This function will initialize an private key structure.
50 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
51 * negative error value.
52 **/
53 int
54 gnutls_pkcs11_privkey_init (gnutls_pkcs11_privkey_t * key)
56 *key = gnutls_calloc (1, sizeof (struct gnutls_pkcs11_privkey_st));
57 if (*key == NULL)
59 gnutls_assert ();
60 return GNUTLS_E_MEMORY_ERROR;
63 (*key)->info = p11_kit_uri_new ();
64 if ((*key)->info == NULL)
66 free (*key);
67 gnutls_assert ();
68 return GNUTLS_E_MEMORY_ERROR;
71 return 0;
74 /**
75 * gnutls_pkcs11_privkey_deinit:
76 * @key: The structure to be initialized
78 * This function will deinitialize a private key structure.
79 **/
80 void
81 gnutls_pkcs11_privkey_deinit (gnutls_pkcs11_privkey_t key)
83 p11_kit_uri_free (key->info);
84 if (key->sinfo.init != 0)
85 pkcs11_close_session (&key->sinfo);
86 gnutls_free (key);
89 /**
90 * gnutls_pkcs11_privkey_get_pk_algorithm:
91 * @key: should contain a #gnutls_pkcs11_privkey_t structure
92 * @bits: if bits is non null it will hold the size of the parameters' in bits
94 * This function will return the public key algorithm of a private
95 * key.
97 * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
98 * success, or a negative error code on error.
99 **/
101 gnutls_pkcs11_privkey_get_pk_algorithm (gnutls_pkcs11_privkey_t key,
102 unsigned int *bits)
104 if (bits)
105 *bits = 0; /* FIXME */
106 return key->pk_algorithm;
110 * gnutls_pkcs11_privkey_get_info:
111 * @pkey: should contain a #gnutls_pkcs11_privkey_t structure
112 * @itype: Denotes the type of information requested
113 * @output: where output will be stored
114 * @output_size: contains the maximum size of the output and will be overwritten with actual
116 * This function will return information about the PKCS 11 private key such
117 * as the label, id as well as token information where the key is stored. When
118 * output is text it returns null terminated string although #output_size contains
119 * the size of the actual data only.
121 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
124 gnutls_pkcs11_privkey_get_info (gnutls_pkcs11_privkey_t pkey,
125 gnutls_pkcs11_obj_info_t itype,
126 void *output, size_t * output_size)
128 return pkcs11_get_info (pkey->info, itype, output, output_size);
132 #define FIND_OBJECT(sinfo, pin_info, obj, key) \
133 do { \
134 int retries = 0; \
135 int rret; \
136 ret = pkcs11_find_object (sinfo, pin_info, &obj, key->info, \
137 SESSION_LOGIN); \
138 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { \
139 if (_gnutls_token_func) \
141 rret = pkcs11_call_token_func (key->info, retries++); \
142 if (rret == 0) continue; \
144 return gnutls_assert_val(ret); \
145 } else if (ret < 0) { \
146 return gnutls_assert_val(ret); \
148 } while (0);
152 * _gnutls_pkcs11_privkey_sign_hash:
153 * @key: Holds the key
154 * @hash: holds the data to be signed (should be output of a hash)
155 * @signature: will contain the signature allocated with gnutls_malloc()
157 * This function will sign the given data using a signature algorithm
158 * supported by the private key. It is assumed that the given data
159 * are the output of a hash function.
161 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
162 * negative error value.
165 _gnutls_pkcs11_privkey_sign_hash (gnutls_pkcs11_privkey_t key,
166 const gnutls_datum_t * hash,
167 gnutls_datum_t * signature)
169 ck_rv_t rv;
170 int ret;
171 struct ck_mechanism mech;
172 gnutls_datum_t tmp = {NULL, 0};
173 unsigned long siglen;
174 struct pkcs11_session_info _sinfo;
175 struct pkcs11_session_info *sinfo;
176 ck_object_handle_t obj;
178 if (key->sinfo.init != 0)
180 sinfo = &key->sinfo;
181 obj = key->obj;
183 else
185 sinfo = &_sinfo;
186 memset(sinfo, 0, sizeof(*sinfo));
187 FIND_OBJECT (sinfo, &key->pin, 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
195 * earlier. */
196 rv = pkcs11_sign_init (sinfo->module, sinfo->pks, &mech, obj);
197 if (rv != CKR_OK)
199 gnutls_assert ();
200 ret = pkcs11_rv_to_err (rv);
201 goto cleanup;
204 /* Work out how long the signature must be: */
205 rv = pkcs11_sign (sinfo->module, sinfo->pks, hash->data, hash->size, NULL, &siglen);
206 if (rv != CKR_OK)
208 gnutls_assert ();
209 ret = pkcs11_rv_to_err (rv);
210 goto cleanup;
213 tmp.data = gnutls_malloc (siglen);
214 tmp.size = siglen;
216 rv = pkcs11_sign (sinfo->module, sinfo->pks, hash->data, hash->size, tmp.data, &siglen);
217 if (rv != CKR_OK)
219 gnutls_assert ();
220 ret = pkcs11_rv_to_err (rv);
221 goto cleanup;
225 if (key->pk_algorithm == GNUTLS_PK_EC || key->pk_algorithm == GNUTLS_PK_DSA)
227 unsigned int hlen = siglen / 2;
228 gnutls_datum_t r, s;
230 if (siglen % 2 != 0)
232 gnutls_assert();
233 ret = GNUTLS_E_PK_SIGN_FAILED;
234 goto cleanup;
237 r.data = tmp.data;
238 r.size = hlen;
240 s.data = &tmp.data[hlen];
241 s.size = hlen;
243 ret = _gnutls_encode_ber_rs_raw (signature, &r, &s);
244 if (ret < 0)
246 gnutls_assert();
247 goto cleanup;
250 gnutls_free(tmp.data);
251 tmp.data = NULL;
253 else
255 signature->size = siglen;
256 signature->data = tmp.data;
259 ret = 0;
261 cleanup:
262 if (sinfo != &key->sinfo)
263 pkcs11_close_session (sinfo);
264 if (ret < 0)
265 gnutls_free(tmp.data);
267 return ret;
271 * gnutls_pkcs11_privkey_import_url:
272 * @pkey: The structure to store the parsed key
273 * @url: a PKCS 11 url identifying the key
274 * @flags: sequence of GNUTLS_PKCS_PRIVKEY_*
276 * This function will "import" a PKCS 11 URL identifying a private
277 * key to the #gnutls_pkcs11_privkey_t structure. In reality since
278 * in most cases keys cannot be exported, the private key structure
279 * is being associated with the available operations on the token.
281 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
282 * negative error value.
285 gnutls_pkcs11_privkey_import_url (gnutls_pkcs11_privkey_t pkey,
286 const char *url, unsigned int flags)
288 int ret;
289 struct ck_attribute *attr;
290 ck_object_handle_t obj;
291 struct ck_attribute a[4];
292 ck_key_type_t key_type;
293 struct pkcs11_session_info sinfo;
295 memset(&sinfo, 0, sizeof(sinfo));
297 ret = pkcs11_url_to_info (url, &pkey->info);
298 if (ret < 0)
300 gnutls_assert ();
301 return ret;
304 pkey->flags = flags;
306 attr = p11_kit_uri_get_attribute (pkey->info, CKA_CLASS);
307 if (!attr || attr->value_len != sizeof (ck_object_class_t) ||
308 *(ck_object_class_t*)attr->value != CKO_PRIVATE_KEY)
310 gnutls_assert ();
311 return GNUTLS_E_INVALID_REQUEST;
314 attr = p11_kit_uri_get_attribute (pkey->info, CKA_ID);
315 if (!attr || !attr->value_len)
317 attr = p11_kit_uri_get_attribute (pkey->info, CKA_LABEL);
318 if (!attr || !attr->value_len)
320 gnutls_assert ();
321 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
325 FIND_OBJECT (&sinfo, &pkey->pin, obj, pkey);
327 a[0].type = CKA_KEY_TYPE;
328 a[0].value = &key_type;
329 a[0].value_len = sizeof (key_type);
331 if (pkcs11_get_attribute_value (sinfo.module, sinfo.pks, obj, a, 1) == CKR_OK)
333 pkey->pk_algorithm = mech_to_pk(key_type);
334 if (pkey->pk_algorithm == GNUTLS_PK_UNKNOWN)
336 _gnutls_debug_log("Cannot determine PKCS #11 key algorithm\n");
337 ret = GNUTLS_E_UNKNOWN_ALGORITHM;
338 goto cleanup;
342 ret = 0;
344 if (pkey->sinfo.init)
345 pkcs11_close_session (&pkey->sinfo);
347 if (sinfo.tinfo.max_session_count != 1)
349 /* We do not keep the session open in tokens that can
350 * only support a single session.
352 memcpy(&pkey->sinfo, &sinfo, sizeof(pkey->sinfo));
353 pkey->obj = obj;
354 return ret;
357 cleanup:
358 pkcs11_close_session (&sinfo);
360 return ret;
364 * _gnutls_pkcs11_privkey_decrypt_data:
365 * @key: Holds the key
366 * @flags: should be 0 for now
367 * @ciphertext: holds the data to be signed
368 * @plaintext: will contain the plaintext, allocated with gnutls_malloc()
370 * This function will decrypt the given data using the public key algorithm
371 * supported by the private key.
373 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
374 * negative error value.
377 _gnutls_pkcs11_privkey_decrypt_data (gnutls_pkcs11_privkey_t key,
378 unsigned int flags,
379 const gnutls_datum_t * ciphertext,
380 gnutls_datum_t * plaintext)
382 ck_rv_t rv;
383 int ret;
384 struct ck_mechanism mech;
385 unsigned long siglen;
386 ck_object_handle_t obj;
387 struct pkcs11_session_info _sinfo;
388 struct pkcs11_session_info *sinfo;
390 if (key->sinfo.init != 0)
392 sinfo = &key->sinfo;
393 obj = key->obj;
395 else
397 sinfo = &_sinfo;
398 memset(sinfo, 0, sizeof(*sinfo));
399 FIND_OBJECT (sinfo, &key->pin, obj, key);
402 if (key->pk_algorithm != GNUTLS_PK_RSA)
403 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
405 mech.mechanism = CKM_RSA_PKCS;
406 mech.parameter = NULL;
407 mech.parameter_len = 0;
409 /* Initialize signing operation; using the private key discovered
410 * earlier. */
411 rv = pkcs11_decrypt_init (sinfo->module, sinfo->pks, &mech, obj);
412 if (rv != CKR_OK)
414 gnutls_assert ();
415 ret = pkcs11_rv_to_err (rv);
416 goto cleanup;
419 /* Work out how long the plaintext must be: */
420 rv = pkcs11_decrypt (sinfo->module, sinfo->pks, ciphertext->data, ciphertext->size,
421 NULL, &siglen);
422 if (rv != CKR_OK)
424 gnutls_assert ();
425 ret = pkcs11_rv_to_err (rv);
426 goto cleanup;
429 plaintext->data = gnutls_malloc (siglen);
430 plaintext->size = siglen;
432 rv = pkcs11_decrypt (sinfo->module, sinfo->pks, ciphertext->data, ciphertext->size,
433 plaintext->data, &siglen);
434 if (rv != CKR_OK)
436 gnutls_free (plaintext->data);
437 gnutls_assert ();
438 ret = pkcs11_rv_to_err (rv);
439 goto cleanup;
442 plaintext->size = siglen;
444 ret = 0;
446 cleanup:
447 if (key->sinfo.init == 0)
448 pkcs11_close_session (sinfo);
450 return ret;
454 * gnutls_pkcs11_privkey_export_url:
455 * @key: Holds the PKCS 11 key
456 * @detailed: non zero if a detailed URL is required
457 * @url: will contain an allocated url
459 * This function will export a URL identifying the given key.
461 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
462 * negative error value.
465 gnutls_pkcs11_privkey_export_url (gnutls_pkcs11_privkey_t key,
466 gnutls_pkcs11_url_type_t detailed,
467 char **url)
469 int ret;
471 ret = pkcs11_info_to_url (key->info, detailed, url);
472 if (ret < 0)
474 gnutls_assert ();
475 return ret;
478 return 0;
483 * gnutls_pkcs11_privkey_generate:
484 * @url: a token URL
485 * @pk: the public key algorithm
486 * @bits: the security bits
487 * @label: a label
488 * @flags: should be zero
490 * This function will generate a private key in the specified
491 * by the @url token. The private key will be generate within
492 * the token and will not be exportable.
494 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
495 * negative error value.
497 * Since: 3.0
500 gnutls_pkcs11_privkey_generate (const char* url, gnutls_pk_algorithm_t pk,
501 unsigned int bits, const char* label,
502 unsigned int flags)
504 int ret;
505 const ck_bool_t tval = 1;
506 const ck_bool_t fval = 0;
507 struct pkcs11_session_info sinfo;
508 struct p11_kit_uri *info = NULL;
509 ck_rv_t rv;
510 struct ck_attribute a[10], p[10];
511 ck_object_handle_t pub, priv;
512 unsigned long _bits = bits;
513 int a_val, p_val;
514 struct ck_mechanism mech;
516 memset(&sinfo, 0, sizeof(sinfo));
518 ret = pkcs11_url_to_info (url, &info);
519 if (ret < 0)
521 gnutls_assert ();
522 return ret;
525 ret =
526 pkcs11_open_session (&sinfo, NULL, info,
527 SESSION_WRITE | pkcs11_obj_flags_to_int (flags));
528 p11_kit_uri_free (info);
530 if (ret < 0)
532 gnutls_assert ();
533 goto cleanup;
536 /* a holds the public key template
537 * and p the private key */
538 a_val = p_val = 0;
539 mech.parameter = NULL;
540 mech.parameter_len = 0;
541 mech.mechanism = pk_to_genmech(pk);
543 switch(pk)
545 case GNUTLS_PK_RSA:
546 p[p_val].type = CKA_DECRYPT;
547 p[p_val].value = (void*)&tval;
548 p[p_val].value_len = sizeof (tval);
549 p_val++;
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_ENCRYPT;
557 a[a_val].value = (void*)&tval;
558 a[a_val].value_len = sizeof (tval);
559 a_val++;
561 a[a_val].type = CKA_VERIFY;
562 a[a_val].value = (void*)&tval;
563 a[a_val].value_len = sizeof (tval);
564 a_val++;
566 a[a_val].type = CKA_MODULUS_BITS;
567 a[a_val].value = &_bits;
568 a[a_val].value_len = sizeof (_bits);
569 a_val++;
570 break;
571 case GNUTLS_PK_DSA:
572 p[p_val].type = CKA_SIGN;
573 p[p_val].value = (void*)&tval;
574 p[p_val].value_len = sizeof (tval);
575 p_val++;
577 a[a_val].type = CKA_VERIFY;
578 a[a_val].value = (void*)&tval;
579 a[a_val].value_len = sizeof (tval);
580 a_val++;
582 a[a_val].type = CKA_MODULUS_BITS;
583 a[a_val].value = &_bits;
584 a[a_val].value_len = sizeof (_bits);
585 a_val++;
586 break;
587 case GNUTLS_PK_EC:
588 p[p_val].type = CKA_SIGN;
589 p[p_val].value = (void*)&tval;
590 p[p_val].value_len = sizeof (tval);
591 p_val++;
593 a[a_val].type = CKA_VERIFY;
594 a[a_val].value = (void*)&tval;
595 a[a_val].value_len = sizeof (tval);
596 a_val++;
598 a[a_val].type = CKA_MODULUS_BITS;
599 a[a_val].value = &_bits;
600 a[a_val].value_len = sizeof (_bits);
601 a_val++;
602 break;
603 default:
604 ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
605 goto cleanup;
608 /* a private key is set always as private unless
609 * requested otherwise
611 if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE)
613 p[p_val].type = CKA_PRIVATE;
614 p[p_val].value = (void*)&fval;
615 p[p_val].value_len = sizeof(fval);
616 p_val++;
618 else
620 p[p_val].type = CKA_PRIVATE;
621 p[p_val].value = (void*)&tval;
622 p[p_val].value_len = sizeof (tval);
623 p_val++;
626 p[p_val].type = CKA_TOKEN;
627 p[p_val].value = (void *)&tval;
628 p[p_val].value_len = sizeof (tval);
629 p_val++;
631 if (label)
633 p[p_val].type = CKA_LABEL;
634 p[p_val].value = (void*)label;
635 p[p_val].value_len = strlen (label);
636 p_val++;
638 a[a_val].type = CKA_LABEL;
639 a[a_val].value = (void*)label;
640 a[a_val].value_len = strlen (label);
641 a_val++;
644 if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE)
646 p[p_val].type = CKA_SENSITIVE;
647 p[p_val].value = (void*)&tval;
648 p[p_val].value_len = sizeof (tval);
649 p_val++;
651 else
653 p[p_val].type = CKA_SENSITIVE;
654 p[p_val].value = (void*)&fval;
655 p[p_val].value_len = sizeof (fval);
656 p_val++;
659 rv = pkcs11_generate_key_pair( sinfo.module, sinfo.pks, &mech, a, a_val, p, p_val, &pub, &priv);
660 if (rv != CKR_OK)
662 gnutls_assert ();
663 _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv));
664 ret = pkcs11_rv_to_err (rv);
665 goto cleanup;
669 cleanup:
670 if (sinfo.pks != 0)
671 pkcs11_close_session (&sinfo);
673 return ret;
677 * gnutls_pkcs11_privkey_set_pin_function:
678 * @key: The private key
679 * @fn: the callback
680 * @userdata: data associated with the callback
682 * This function will set a callback function to be used when
683 * required to access the object. This function overrides the global
684 * set using gnutls_pkcs11_set_pin_function().
686 * Since: 3.1.0
689 void
690 gnutls_pkcs11_privkey_set_pin_function (gnutls_pkcs11_privkey_t key,
691 gnutls_pin_callback_t fn,
692 void *userdata)
694 key->pin.cb = fn;
695 key->pin.data = userdata;