corrected typo
[gnutls.git] / lib / pkcs11_privkey.c
blobafbd8e402a645fc8aeec6969547e4f3afba4712c
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 gnutls_assert ();
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;
279 goto cleanup;
283 ret = 0;
285 cleanup:
286 pkcs11_close_session (module, pks);
288 return ret;
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,
306 unsigned int flags,
307 const gnutls_datum_t * ciphertext,
308 gnutls_datum_t * plaintext)
310 ck_rv_t rv;
311 int ret;
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
328 * earlier. */
329 rv = pkcs11_decrypt_init (module, pks, &mech, obj);
330 if (rv != CKR_OK)
332 gnutls_assert ();
333 ret = pkcs11_rv_to_err (rv);
334 goto cleanup;
337 /* Work out how long the plaintext must be: */
338 rv = pkcs11_decrypt (module, pks, ciphertext->data, ciphertext->size,
339 NULL, &siglen);
340 if (rv != CKR_OK)
342 gnutls_assert ();
343 ret = pkcs11_rv_to_err (rv);
344 goto cleanup;
347 plaintext->data = gnutls_malloc (siglen);
348 plaintext->size = siglen;
350 rv = pkcs11_decrypt (module, pks, ciphertext->data, ciphertext->size,
351 plaintext->data, &siglen);
352 if (rv != CKR_OK)
354 gnutls_free (plaintext->data);
355 gnutls_assert ();
356 ret = pkcs11_rv_to_err (rv);
357 goto cleanup;
360 plaintext->size = siglen;
362 ret = 0;
364 cleanup:
365 pkcs11_close_session (module, pks);
367 return ret;
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,
384 char **url)
386 int ret;
388 ret = pkcs11_info_to_url (key->info, detailed, url);
389 if (ret < 0)
391 gnutls_assert ();
392 return ret;
395 return 0;
400 * gnutls_pkcs11_privkey_generate:
401 * @url: a token URL
402 * @pk: the public key algorithm
403 * @bits: the security bits
404 * @label: a label
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.
414 * Since: 3.0
417 gnutls_pkcs11_privkey_generate (const char* url,
418 gnutls_pk_algorithm_t pk, unsigned int bits,
419 const char* label, unsigned int flags)
421 int ret;
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;
427 ck_rv_t rv;
428 struct ck_attribute a[10], p[10];
429 ck_object_handle_t pub, priv;
430 unsigned long _bits = bits;
431 int a_val, p_val;
432 struct ck_mechanism mech;
434 ret = pkcs11_url_to_info (url, &info);
435 if (ret < 0)
437 gnutls_assert ();
438 return ret;
441 ret =
442 pkcs11_open_session (&module, &pks, info,
443 SESSION_WRITE | pkcs11_obj_flags_to_int (flags));
444 p11_kit_uri_free (info);
446 if (ret < 0)
448 gnutls_assert ();
449 goto cleanup;
452 /* a holds the public key template
453 * and p the private key */
454 a_val = p_val = 0;
455 mech.parameter = NULL;
456 mech.parameter_len = 0;
457 mech.mechanism = pk_to_genmech(pk);
459 switch(pk)
461 case GNUTLS_PK_RSA:
462 p[p_val].type = CKA_DECRYPT;
463 p[p_val].value = (void*)&tval;
464 p[p_val].value_len = sizeof (tval);
465 p_val++;
467 p[p_val].type = CKA_SIGN;
468 p[p_val].value = (void*)&tval;
469 p[p_val].value_len = sizeof (tval);
470 p_val++;
472 a[a_val].type = CKA_ENCRYPT;
473 a[a_val].value = (void*)&tval;
474 a[a_val].value_len = sizeof (tval);
475 a_val++;
477 a[a_val].type = CKA_VERIFY;
478 a[a_val].value = (void*)&tval;
479 a[a_val].value_len = sizeof (tval);
480 a_val++;
482 a[a_val].type = CKA_MODULUS_BITS;
483 a[a_val].value = &_bits;
484 a[a_val].value_len = sizeof (_bits);
485 a_val++;
486 break;
487 case GNUTLS_PK_DSA:
488 p[p_val].type = CKA_SIGN;
489 p[p_val].value = (void*)&tval;
490 p[p_val].value_len = sizeof (tval);
491 p_val++;
493 a[a_val].type = CKA_VERIFY;
494 a[a_val].value = (void*)&tval;
495 a[a_val].value_len = sizeof (tval);
496 a_val++;
498 a[a_val].type = CKA_MODULUS_BITS;
499 a[a_val].value = &_bits;
500 a[a_val].value_len = sizeof (_bits);
501 a_val++;
502 break;
503 case GNUTLS_PK_EC:
504 p[p_val].type = CKA_SIGN;
505 p[p_val].value = (void*)&tval;
506 p[p_val].value_len = sizeof (tval);
507 p_val++;
509 a[a_val].type = CKA_VERIFY;
510 a[a_val].value = (void*)&tval;
511 a[a_val].value_len = sizeof (tval);
512 a_val++;
514 a[a_val].type = CKA_MODULUS_BITS;
515 a[a_val].value = &_bits;
516 a[a_val].value_len = sizeof (_bits);
517 a_val++;
518 break;
519 default:
520 ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
521 goto cleanup;
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);
532 p_val++;
534 else
536 p[p_val].type = CKA_PRIVATE;
537 p[p_val].value = (void*)&tval;
538 p[p_val].value_len = sizeof (tval);
539 p_val++;
542 p[p_val].type = CKA_TOKEN;
543 p[p_val].value = (void *)&tval;
544 p[p_val].value_len = sizeof (tval);
545 p_val++;
547 if (label)
549 p[p_val].type = CKA_LABEL;
550 p[p_val].value = (void*)label;
551 p[p_val].value_len = strlen (label);
552 p_val++;
554 a[a_val].type = CKA_LABEL;
555 a[a_val].value = (void*)label;
556 a[a_val].value_len = strlen (label);
557 a_val++;
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);
565 p_val++;
567 else
569 p[p_val].type = CKA_SENSITIVE;
570 p[p_val].value = (void*)&fval;
571 p[p_val].value_len = sizeof (fval);
572 p_val++;
575 rv = pkcs11_generate_key_pair( module, pks, &mech, a, a_val, p, p_val, &pub, &priv);
576 if (rv != CKR_OK)
578 gnutls_assert ();
579 _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv));
580 ret = pkcs11_rv_to_err (rv);
581 goto cleanup;
585 cleanup:
586 if (pks != 0)
587 pkcs11_close_session (module, pks);
589 return ret;