Correctly restore gnutls_record_recv() in DTLS mode if interrupted during the retrasm...
[gnutls.git] / lib / pkcs11_privkey.c
blobec709307aea1a3c2d563537fa22fbb9e5f6bddf7
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;
37 gnutls_pkcs11_pin_callback_t pin_func;
38 void *pin_data;
41 /**
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.
49 **/
50 int
51 gnutls_pkcs11_privkey_init (gnutls_pkcs11_privkey_t * key)
53 *key = gnutls_calloc (1, sizeof (struct gnutls_pkcs11_privkey_st));
54 if (*key == NULL)
56 gnutls_assert ();
57 return GNUTLS_E_MEMORY_ERROR;
60 (*key)->info = p11_kit_uri_new ();
61 if ((*key)->info == NULL)
63 free (*key);
64 gnutls_assert ();
65 return GNUTLS_E_MEMORY_ERROR;
68 return 0;
71 /**
72 * gnutls_pkcs11_privkey_deinit:
73 * @key: The structure to be initialized
75 * This function will deinitialize a private key structure.
76 **/
77 void
78 gnutls_pkcs11_privkey_deinit (gnutls_pkcs11_privkey_t key)
80 p11_kit_uri_free (key->info);
81 gnutls_free (key);
84 /**
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
90 * key.
92 * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
93 * success, or a negative error code on error.
94 **/
95 int
96 gnutls_pkcs11_privkey_get_pk_algorithm (gnutls_pkcs11_privkey_t key,
97 unsigned int *bits)
99 if (bits)
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) \
128 do { \
129 int retries = 0; \
130 int rret; \
131 ret = pkcs11_find_object (&module, &pks, &obj, key->info, \
132 SESSION_LOGIN); \
133 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { \
134 if (token_func) \
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); \
143 } while (0);
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);
159 return 0;
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)
180 ck_rv_t rv;
181 int ret;
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
195 * earlier. */
196 rv = pkcs11_sign_init (module, 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 (module, 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 signature->data = gnutls_malloc (siglen);
214 signature->size = siglen;
216 rv = pkcs11_sign (module, pks, hash->data, hash->size, signature->data, &siglen);
217 if (rv != CKR_OK)
219 gnutls_free (signature->data);
220 gnutls_assert ();
221 ret = pkcs11_rv_to_err (rv);
222 goto cleanup;
225 signature->size = siglen;
227 if (key->pk_algorithm == GNUTLS_PK_EC || key->pk_algorithm == GNUTLS_PK_DSA)
229 bigint_t r,s;
231 if (siglen % 2 != 0)
233 gnutls_assert();
234 ret = GNUTLS_E_PK_SIGN_FAILED;
235 goto cleanup;
238 ret = read_rs(&r, &s, signature->data, signature->size);
239 if (ret < 0)
241 gnutls_assert();
242 goto cleanup;
245 gnutls_free(signature->data);
246 ret = _gnutls_encode_ber_rs (signature, r, s);
247 _gnutls_mpi_release(&r);
248 _gnutls_mpi_release(&s);
250 if (ret < 0)
252 gnutls_assert();
253 goto cleanup;
257 ret = 0;
259 cleanup:
260 pkcs11_close_session (module, pks);
262 return ret;
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)
283 int ret;
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);
292 if (ret < 0)
294 gnutls_assert ();
295 return ret;
298 pkey->flags = flags;
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)
304 gnutls_assert ();
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)
314 gnutls_assert ();
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;
331 goto cleanup;
335 ret = 0;
337 cleanup:
338 pkcs11_close_session (module, pks);
340 return ret;
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,
358 unsigned int flags,
359 const gnutls_datum_t * ciphertext,
360 gnutls_datum_t * plaintext)
362 ck_rv_t rv;
363 int ret;
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
380 * earlier. */
381 rv = pkcs11_decrypt_init (module, pks, &mech, obj);
382 if (rv != CKR_OK)
384 gnutls_assert ();
385 ret = pkcs11_rv_to_err (rv);
386 goto cleanup;
389 /* Work out how long the plaintext must be: */
390 rv = pkcs11_decrypt (module, pks, ciphertext->data, ciphertext->size,
391 NULL, &siglen);
392 if (rv != CKR_OK)
394 gnutls_assert ();
395 ret = pkcs11_rv_to_err (rv);
396 goto cleanup;
399 plaintext->data = gnutls_malloc (siglen);
400 plaintext->size = siglen;
402 rv = pkcs11_decrypt (module, pks, ciphertext->data, ciphertext->size,
403 plaintext->data, &siglen);
404 if (rv != CKR_OK)
406 gnutls_free (plaintext->data);
407 gnutls_assert ();
408 ret = pkcs11_rv_to_err (rv);
409 goto cleanup;
412 plaintext->size = siglen;
414 ret = 0;
416 cleanup:
417 pkcs11_close_session (module, pks);
419 return ret;
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,
436 char **url)
438 int ret;
440 ret = pkcs11_info_to_url (key->info, detailed, url);
441 if (ret < 0)
443 gnutls_assert ();
444 return ret;
447 return 0;
452 * gnutls_pkcs11_privkey_generate:
453 * @url: a token URL
454 * @pk: the public key algorithm
455 * @bits: the security bits
456 * @label: a label
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.
466 * Since: 3.0
469 gnutls_pkcs11_privkey_generate (const char* url,
470 gnutls_pk_algorithm_t pk, unsigned int bits,
471 const char* label, unsigned int flags)
473 int ret;
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;
479 ck_rv_t rv;
480 struct ck_attribute a[10], p[10];
481 ck_object_handle_t pub, priv;
482 unsigned long _bits = bits;
483 int a_val, p_val;
484 struct ck_mechanism mech;
486 ret = pkcs11_url_to_info (url, &info);
487 if (ret < 0)
489 gnutls_assert ();
490 return ret;
493 ret =
494 pkcs11_open_session (&module, &pks, info,
495 SESSION_WRITE | pkcs11_obj_flags_to_int (flags));
496 p11_kit_uri_free (info);
498 if (ret < 0)
500 gnutls_assert ();
501 goto cleanup;
504 /* a holds the public key template
505 * and p the private key */
506 a_val = p_val = 0;
507 mech.parameter = NULL;
508 mech.parameter_len = 0;
509 mech.mechanism = pk_to_genmech(pk);
511 switch(pk)
513 case GNUTLS_PK_RSA:
514 p[p_val].type = CKA_DECRYPT;
515 p[p_val].value = (void*)&tval;
516 p[p_val].value_len = sizeof (tval);
517 p_val++;
519 p[p_val].type = CKA_SIGN;
520 p[p_val].value = (void*)&tval;
521 p[p_val].value_len = sizeof (tval);
522 p_val++;
524 a[a_val].type = CKA_ENCRYPT;
525 a[a_val].value = (void*)&tval;
526 a[a_val].value_len = sizeof (tval);
527 a_val++;
529 a[a_val].type = CKA_VERIFY;
530 a[a_val].value = (void*)&tval;
531 a[a_val].value_len = sizeof (tval);
532 a_val++;
534 a[a_val].type = CKA_MODULUS_BITS;
535 a[a_val].value = &_bits;
536 a[a_val].value_len = sizeof (_bits);
537 a_val++;
538 break;
539 case GNUTLS_PK_DSA:
540 p[p_val].type = CKA_SIGN;
541 p[p_val].value = (void*)&tval;
542 p[p_val].value_len = sizeof (tval);
543 p_val++;
545 a[a_val].type = CKA_VERIFY;
546 a[a_val].value = (void*)&tval;
547 a[a_val].value_len = sizeof (tval);
548 a_val++;
550 a[a_val].type = CKA_MODULUS_BITS;
551 a[a_val].value = &_bits;
552 a[a_val].value_len = sizeof (_bits);
553 a_val++;
554 break;
555 case GNUTLS_PK_EC:
556 p[p_val].type = CKA_SIGN;
557 p[p_val].value = (void*)&tval;
558 p[p_val].value_len = sizeof (tval);
559 p_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 default:
572 ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
573 goto cleanup;
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);
584 p_val++;
586 else
588 p[p_val].type = CKA_PRIVATE;
589 p[p_val].value = (void*)&tval;
590 p[p_val].value_len = sizeof (tval);
591 p_val++;
594 p[p_val].type = CKA_TOKEN;
595 p[p_val].value = (void *)&tval;
596 p[p_val].value_len = sizeof (tval);
597 p_val++;
599 if (label)
601 p[p_val].type = CKA_LABEL;
602 p[p_val].value = (void*)label;
603 p[p_val].value_len = strlen (label);
604 p_val++;
606 a[a_val].type = CKA_LABEL;
607 a[a_val].value = (void*)label;
608 a[a_val].value_len = strlen (label);
609 a_val++;
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);
617 p_val++;
619 else
621 p[p_val].type = CKA_SENSITIVE;
622 p[p_val].value = (void*)&fval;
623 p[p_val].value_len = sizeof (fval);
624 p_val++;
627 rv = pkcs11_generate_key_pair( module, pks, &mech, a, a_val, p, p_val, &pub, &priv);
628 if (rv != CKR_OK)
630 gnutls_assert ();
631 _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv));
632 ret = pkcs11_rv_to_err (rv);
633 goto cleanup;
637 cleanup:
638 if (pks != 0)
639 pkcs11_close_session (module, pks);
641 return ret;