certtool is able to set certificate policies via a template
[gnutls.git] / lib / pkcs11_privkey.c
bloba4ace845ca2efab96a848cb6ce345443655bb109
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);
131 static int
132 find_object (struct pkcs11_session_info* sinfo,
133 struct pin_info_st * pin_info,
134 ck_object_handle_t * _obj,
135 struct p11_kit_uri *info, unsigned int flags)
137 int ret;
138 ck_object_handle_t obj;
139 struct ck_attribute *attrs;
140 unsigned long attr_count;
141 unsigned long count;
142 ck_rv_t rv;
144 ret = pkcs11_open_session (sinfo, pin_info, info, flags & SESSION_LOGIN);
145 if (ret < 0)
147 gnutls_assert ();
148 return ret;
151 attrs = p11_kit_uri_get_attributes (info, &attr_count);
152 rv = pkcs11_find_objects_init (sinfo->module, sinfo->pks, attrs, attr_count);
153 if (rv != CKR_OK)
155 gnutls_assert ();
156 _gnutls_debug_log ("pk11: FindObjectsInit failed.\n");
157 ret = pkcs11_rv_to_err (rv);
158 goto fail;
161 if (pkcs11_find_objects (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK && count == 1)
163 *_obj = obj;
164 pkcs11_find_objects_final (sinfo);
165 return 0;
168 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
169 pkcs11_find_objects_final (sinfo);
170 fail:
171 pkcs11_close_session (sinfo);
173 return ret;
176 #define FIND_OBJECT(sinfo, pin_info, obj, key) \
177 do { \
178 int retries = 0; \
179 int rret; \
180 ret = find_object (sinfo, pin_info, &obj, key->info, \
181 SESSION_LOGIN); \
182 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { \
183 if (_gnutls_token_func) \
185 rret = pkcs11_call_token_func (key->info, retries++); \
186 if (rret == 0) continue; \
188 return gnutls_assert_val(ret); \
189 } else if (ret < 0) { \
190 return gnutls_assert_val(ret); \
192 } while (0);
196 * _gnutls_pkcs11_privkey_sign_hash:
197 * @key: Holds the key
198 * @hash: holds the data to be signed (should be output of a hash)
199 * @signature: will contain the signature allocated with gnutls_malloc()
201 * This function will sign the given data using a signature algorithm
202 * supported by the private key. It is assumed that the given data
203 * are the output of a hash function.
205 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
206 * negative error value.
209 _gnutls_pkcs11_privkey_sign_hash (gnutls_pkcs11_privkey_t key,
210 const gnutls_datum_t * hash,
211 gnutls_datum_t * signature)
213 ck_rv_t rv;
214 int ret;
215 struct ck_mechanism mech;
216 gnutls_datum_t tmp = {NULL, 0};
217 unsigned long siglen;
218 struct pkcs11_session_info _sinfo;
219 struct pkcs11_session_info *sinfo;
220 ck_object_handle_t obj;
222 if (key->sinfo.init != 0)
224 sinfo = &key->sinfo;
225 obj = key->obj;
227 else
229 sinfo = &_sinfo;
230 memset(sinfo, 0, sizeof(*sinfo));
231 FIND_OBJECT (sinfo, &key->pin, obj, key);
234 mech.mechanism = pk_to_mech(key->pk_algorithm);
235 mech.parameter = NULL;
236 mech.parameter_len = 0;
238 /* Initialize signing operation; using the private key discovered
239 * earlier. */
240 rv = pkcs11_sign_init (sinfo->module, sinfo->pks, &mech, obj);
241 if (rv != CKR_OK)
243 gnutls_assert ();
244 ret = pkcs11_rv_to_err (rv);
245 goto cleanup;
248 /* Work out how long the signature must be: */
249 rv = pkcs11_sign (sinfo->module, sinfo->pks, hash->data, hash->size, NULL, &siglen);
250 if (rv != CKR_OK)
252 gnutls_assert ();
253 ret = pkcs11_rv_to_err (rv);
254 goto cleanup;
257 tmp.data = gnutls_malloc (siglen);
258 tmp.size = siglen;
260 rv = pkcs11_sign (sinfo->module, sinfo->pks, hash->data, hash->size, tmp.data, &siglen);
261 if (rv != CKR_OK)
263 gnutls_assert ();
264 ret = pkcs11_rv_to_err (rv);
265 goto cleanup;
269 if (key->pk_algorithm == GNUTLS_PK_EC || key->pk_algorithm == GNUTLS_PK_DSA)
271 unsigned int hlen = siglen / 2;
272 gnutls_datum_t r, s;
274 if (siglen % 2 != 0)
276 gnutls_assert();
277 ret = GNUTLS_E_PK_SIGN_FAILED;
278 goto cleanup;
281 r.data = tmp.data;
282 r.size = hlen;
284 s.data = &tmp.data[hlen];
285 s.size = hlen;
287 ret = _gnutls_encode_ber_rs_raw (signature, &r, &s);
288 if (ret < 0)
290 gnutls_assert();
291 goto cleanup;
294 gnutls_free(tmp.data);
295 tmp.data = NULL;
297 else
299 signature->size = siglen;
300 signature->data = tmp.data;
303 ret = 0;
305 cleanup:
306 if (sinfo != &key->sinfo)
307 pkcs11_close_session (sinfo);
308 if (ret < 0)
309 gnutls_free(tmp.data);
311 return ret;
315 * gnutls_pkcs11_privkey_import_url:
316 * @pkey: The structure to store the parsed key
317 * @url: a PKCS 11 url identifying the key
318 * @flags: sequence of GNUTLS_PKCS_PRIVKEY_*
320 * This function will "import" a PKCS 11 URL identifying a private
321 * key to the #gnutls_pkcs11_privkey_t structure. In reality since
322 * in most cases keys cannot be exported, the private key structure
323 * is being associated with the available operations on the token.
325 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
326 * negative error value.
329 gnutls_pkcs11_privkey_import_url (gnutls_pkcs11_privkey_t pkey,
330 const char *url, unsigned int flags)
332 int ret;
333 struct ck_attribute *attr;
334 ck_object_handle_t obj;
335 struct ck_attribute a[4];
336 ck_key_type_t key_type;
337 struct pkcs11_session_info sinfo;
339 memset(&sinfo, 0, sizeof(sinfo));
341 ret = pkcs11_url_to_info (url, &pkey->info);
342 if (ret < 0)
344 gnutls_assert ();
345 return ret;
348 pkey->flags = flags;
350 attr = p11_kit_uri_get_attribute (pkey->info, CKA_CLASS);
351 if (!attr || attr->value_len != sizeof (ck_object_class_t) ||
352 *(ck_object_class_t*)attr->value != CKO_PRIVATE_KEY)
354 gnutls_assert ();
355 return GNUTLS_E_INVALID_REQUEST;
358 attr = p11_kit_uri_get_attribute (pkey->info, CKA_ID);
359 if (!attr || !attr->value_len)
361 attr = p11_kit_uri_get_attribute (pkey->info, CKA_LABEL);
362 if (!attr || !attr->value_len)
364 gnutls_assert ();
365 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
369 FIND_OBJECT (&sinfo, &pkey->pin, obj, pkey);
371 a[0].type = CKA_KEY_TYPE;
372 a[0].value = &key_type;
373 a[0].value_len = sizeof (key_type);
375 if (pkcs11_get_attribute_value (sinfo.module, sinfo.pks, obj, a, 1) == CKR_OK)
377 pkey->pk_algorithm = mech_to_pk(key_type);
378 if (pkey->pk_algorithm == GNUTLS_PK_UNKNOWN)
380 _gnutls_debug_log("Cannot determine PKCS #11 key algorithm\n");
381 ret = GNUTLS_E_UNKNOWN_ALGORITHM;
382 goto cleanup;
386 ret = 0;
388 if (pkey->sinfo.init)
389 pkcs11_close_session (&pkey->sinfo);
391 if (sinfo.tinfo.max_session_count != 1)
393 /* We do not keep the session open in tokens that can
394 * only support a single session.
396 memcpy(&pkey->sinfo, &sinfo, sizeof(pkey->sinfo));
397 pkey->obj = obj;
398 return ret;
401 cleanup:
402 pkcs11_close_session (&sinfo);
404 return ret;
408 * _gnutls_pkcs11_privkey_decrypt_data:
409 * @key: Holds the key
410 * @flags: should be 0 for now
411 * @ciphertext: holds the data to be signed
412 * @plaintext: will contain the plaintext, allocated with gnutls_malloc()
414 * This function will decrypt the given data using the public key algorithm
415 * supported by the private key.
417 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
418 * negative error value.
421 _gnutls_pkcs11_privkey_decrypt_data (gnutls_pkcs11_privkey_t key,
422 unsigned int flags,
423 const gnutls_datum_t * ciphertext,
424 gnutls_datum_t * plaintext)
426 ck_rv_t rv;
427 int ret;
428 struct ck_mechanism mech;
429 unsigned long siglen;
430 ck_object_handle_t obj;
431 struct pkcs11_session_info _sinfo;
432 struct pkcs11_session_info *sinfo;
434 if (key->sinfo.init != 0)
436 sinfo = &key->sinfo;
437 obj = key->obj;
439 else
441 sinfo = &_sinfo;
442 memset(sinfo, 0, sizeof(*sinfo));
443 FIND_OBJECT (sinfo, &key->pin, obj, key);
446 if (key->pk_algorithm != GNUTLS_PK_RSA)
447 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
449 mech.mechanism = CKM_RSA_PKCS;
450 mech.parameter = NULL;
451 mech.parameter_len = 0;
453 /* Initialize signing operation; using the private key discovered
454 * earlier. */
455 rv = pkcs11_decrypt_init (sinfo->module, sinfo->pks, &mech, obj);
456 if (rv != CKR_OK)
458 gnutls_assert ();
459 ret = pkcs11_rv_to_err (rv);
460 goto cleanup;
463 /* Work out how long the plaintext must be: */
464 rv = pkcs11_decrypt (sinfo->module, sinfo->pks, ciphertext->data, ciphertext->size,
465 NULL, &siglen);
466 if (rv != CKR_OK)
468 gnutls_assert ();
469 ret = pkcs11_rv_to_err (rv);
470 goto cleanup;
473 plaintext->data = gnutls_malloc (siglen);
474 plaintext->size = siglen;
476 rv = pkcs11_decrypt (sinfo->module, sinfo->pks, ciphertext->data, ciphertext->size,
477 plaintext->data, &siglen);
478 if (rv != CKR_OK)
480 gnutls_free (plaintext->data);
481 gnutls_assert ();
482 ret = pkcs11_rv_to_err (rv);
483 goto cleanup;
486 plaintext->size = siglen;
488 ret = 0;
490 cleanup:
491 if (key->sinfo.init == 0)
492 pkcs11_close_session (sinfo);
494 return ret;
498 * gnutls_pkcs11_privkey_export_url:
499 * @key: Holds the PKCS 11 key
500 * @detailed: non zero if a detailed URL is required
501 * @url: will contain an allocated url
503 * This function will export a URL identifying the given key.
505 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
506 * negative error value.
509 gnutls_pkcs11_privkey_export_url (gnutls_pkcs11_privkey_t key,
510 gnutls_pkcs11_url_type_t detailed,
511 char **url)
513 int ret;
515 ret = pkcs11_info_to_url (key->info, detailed, url);
516 if (ret < 0)
518 gnutls_assert ();
519 return ret;
522 return 0;
527 * gnutls_pkcs11_privkey_generate:
528 * @url: a token URL
529 * @pk: the public key algorithm
530 * @bits: the security bits
531 * @label: a label
532 * @flags: should be zero
534 * This function will generate a private key in the specified
535 * by the @url token. The private key will be generate within
536 * the token and will not be exportable.
538 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
539 * negative error value.
541 * Since: 3.0
544 gnutls_pkcs11_privkey_generate (const char* url, gnutls_pk_algorithm_t pk,
545 unsigned int bits, const char* label,
546 unsigned int flags)
548 return gnutls_pkcs11_privkey_generate2( url, pk, bits, label, 0, NULL, flags);
552 * gnutls_pkcs11_privkey_generate2:
553 * @url: a token URL
554 * @pk: the public key algorithm
555 * @bits: the security bits
556 * @label: a label
557 * @fmt: the format of output params. PEM or DER.
558 * @pubkey: will hold the public key (may be %NULL)
559 * @flags: should be zero
561 * This function will generate a private key in the specified
562 * by the @url token. The private key will be generate within
563 * the token and will not be exportable. This function will
564 * store the DER-encoded public key in the SubjectPublicKeyInfo format
565 * in @pubkey. The @pubkey should be deinitialized using gnutls_free().
567 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
568 * negative error value.
570 * Since: 3.1
573 gnutls_pkcs11_privkey_generate2 (const char* url, gnutls_pk_algorithm_t pk,
574 unsigned int bits, const char* label,
575 gnutls_x509_crt_fmt_t fmt,
576 gnutls_datum_t * pubkey,
577 unsigned int flags)
579 int ret;
580 const ck_bool_t tval = 1;
581 const ck_bool_t fval = 0;
582 struct pkcs11_session_info sinfo;
583 struct p11_kit_uri *info = NULL;
584 ck_rv_t rv;
585 struct ck_attribute a[10], p[10];
586 ck_object_handle_t pub, priv;
587 unsigned long _bits = bits;
588 int a_val, p_val;
589 struct ck_mechanism mech;
590 gnutls_pubkey_t pkey = NULL;
591 gnutls_pkcs11_obj_t obj = NULL;
593 memset(&sinfo, 0, sizeof(sinfo));
595 ret = pkcs11_url_to_info (url, &info);
596 if (ret < 0)
598 gnutls_assert ();
599 return ret;
602 ret =
603 pkcs11_open_session (&sinfo, NULL, info,
604 SESSION_WRITE | pkcs11_obj_flags_to_int (flags));
605 p11_kit_uri_free (info);
607 if (ret < 0)
609 gnutls_assert ();
610 goto cleanup;
613 /* a holds the public key template
614 * and p the private key */
615 a_val = p_val = 0;
616 mech.parameter = NULL;
617 mech.parameter_len = 0;
618 mech.mechanism = pk_to_genmech(pk);
620 switch(pk)
622 case GNUTLS_PK_RSA:
623 p[p_val].type = CKA_DECRYPT;
624 p[p_val].value = (void*)&tval;
625 p[p_val].value_len = sizeof (tval);
626 p_val++;
628 p[p_val].type = CKA_SIGN;
629 p[p_val].value = (void*)&tval;
630 p[p_val].value_len = sizeof (tval);
631 p_val++;
633 a[a_val].type = CKA_ENCRYPT;
634 a[a_val].value = (void*)&tval;
635 a[a_val].value_len = sizeof (tval);
636 a_val++;
638 a[a_val].type = CKA_VERIFY;
639 a[a_val].value = (void*)&tval;
640 a[a_val].value_len = sizeof (tval);
641 a_val++;
643 a[a_val].type = CKA_MODULUS_BITS;
644 a[a_val].value = &_bits;
645 a[a_val].value_len = sizeof (_bits);
646 a_val++;
647 break;
648 case GNUTLS_PK_DSA:
649 p[p_val].type = CKA_SIGN;
650 p[p_val].value = (void*)&tval;
651 p[p_val].value_len = sizeof (tval);
652 p_val++;
654 a[a_val].type = CKA_VERIFY;
655 a[a_val].value = (void*)&tval;
656 a[a_val].value_len = sizeof (tval);
657 a_val++;
659 a[a_val].type = CKA_MODULUS_BITS;
660 a[a_val].value = &_bits;
661 a[a_val].value_len = sizeof (_bits);
662 a_val++;
663 break;
664 case GNUTLS_PK_EC:
665 p[p_val].type = CKA_SIGN;
666 p[p_val].value = (void*)&tval;
667 p[p_val].value_len = sizeof (tval);
668 p_val++;
670 a[a_val].type = CKA_VERIFY;
671 a[a_val].value = (void*)&tval;
672 a[a_val].value_len = sizeof (tval);
673 a_val++;
675 a[a_val].type = CKA_MODULUS_BITS;
676 a[a_val].value = &_bits;
677 a[a_val].value_len = sizeof (_bits);
678 a_val++;
679 break;
680 default:
681 ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
682 goto cleanup;
685 /* a private key is set always as private unless
686 * requested otherwise
688 if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE)
690 p[p_val].type = CKA_PRIVATE;
691 p[p_val].value = (void*)&fval;
692 p[p_val].value_len = sizeof(fval);
693 p_val++;
695 else
697 p[p_val].type = CKA_PRIVATE;
698 p[p_val].value = (void*)&tval;
699 p[p_val].value_len = sizeof (tval);
700 p_val++;
703 p[p_val].type = CKA_TOKEN;
704 p[p_val].value = (void *)&tval;
705 p[p_val].value_len = sizeof (tval);
706 p_val++;
708 if (label)
710 p[p_val].type = CKA_LABEL;
711 p[p_val].value = (void*)label;
712 p[p_val].value_len = strlen (label);
713 p_val++;
715 a[a_val].type = CKA_LABEL;
716 a[a_val].value = (void*)label;
717 a[a_val].value_len = strlen (label);
718 a_val++;
721 if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE)
723 p[p_val].type = CKA_SENSITIVE;
724 p[p_val].value = (void*)&tval;
725 p[p_val].value_len = sizeof (tval);
726 p_val++;
728 else
730 p[p_val].type = CKA_SENSITIVE;
731 p[p_val].value = (void*)&fval;
732 p[p_val].value_len = sizeof (fval);
733 p_val++;
736 rv = pkcs11_generate_key_pair( sinfo.module, sinfo.pks, &mech, a, a_val, p, p_val, &pub, &priv);
737 if (rv != CKR_OK)
739 gnutls_assert ();
740 _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv));
741 ret = pkcs11_rv_to_err (rv);
742 goto cleanup;
745 /* extract the public key */
746 if (pubkey)
748 ret = gnutls_pubkey_init(&pkey);
749 if (ret < 0)
751 gnutls_assert ();
752 goto cleanup;
755 ret = gnutls_pkcs11_obj_init(&obj);
756 if (ret < 0)
758 gnutls_assert ();
759 goto cleanup;
762 obj->pk_algorithm = pk;
763 obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
764 ret = pkcs11_read_pubkey(sinfo.module, sinfo.pks, pub, mech.mechanism, obj->pubkey);
765 if (ret < 0)
767 gnutls_assert ();
768 goto cleanup;
771 ret = gnutls_pubkey_import_pkcs11 (pkey, obj, 0);
772 if (ret < 0)
774 gnutls_assert ();
775 goto cleanup;
778 ret = gnutls_pubkey_export2 (pkey, fmt, pubkey);
779 if (ret < 0)
781 gnutls_assert ();
782 goto cleanup;
787 cleanup:
788 if (obj != NULL)
789 gnutls_pkcs11_obj_deinit(obj);
790 if (pkey != NULL)
791 gnutls_pubkey_deinit(pkey);
792 if (sinfo.pks != 0)
793 pkcs11_close_session (&sinfo);
795 return ret;
799 * gnutls_pkcs11_privkey_set_pin_function:
800 * @key: The private key
801 * @fn: the callback
802 * @userdata: data associated with the callback
804 * This function will set a callback function to be used when
805 * required to access the object. This function overrides the global
806 * set using gnutls_pkcs11_set_pin_function().
808 * Since: 3.1.0
811 void
812 gnutls_pkcs11_privkey_set_pin_function (gnutls_pkcs11_privkey_t key,
813 gnutls_pin_callback_t fn,
814 void *userdata)
816 key->pin.cb = fn;
817 key->pin.data = userdata;