Revert "Imported Upstream version 3.4.11"
[platform/upstream/gnutls.git] / lib / pkcs11_privkey.c
1 /*
2  * GnuTLS PKCS#11 support
3  * Copyright (C) 2010-2012 Free Software Foundation, Inc.
4  * 
5  * Authors: Nikos Mavrogiannopoulos, Stef Walter
6  *
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 2.1 of
10  * the License, or (at your option) any later version.
11  *
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.
16  *
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/>
19  */
20
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 <fips.h>
31 #include <p11-kit/uri.h>
32
33 struct gnutls_pkcs11_privkey_st {
34         gnutls_pk_algorithm_t pk_algorithm;
35         unsigned int flags;
36         struct p11_kit_uri *info;
37
38         struct pkcs11_session_info sinfo;
39         ck_object_handle_t obj; /* the key in the session */
40
41         struct pin_info_st pin;
42 };
43
44 /**
45  * gnutls_pkcs11_privkey_init:
46  * @key: The structure to be initialized
47  *
48  * This function will initialize an private key structure.
49  *
50  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
51  *   negative error value.
52  **/
53 int gnutls_pkcs11_privkey_init(gnutls_pkcs11_privkey_t * key)
54 {
55         FAIL_IF_LIB_ERROR;
56
57         *key = gnutls_calloc(1, sizeof(struct gnutls_pkcs11_privkey_st));
58         if (*key == NULL) {
59                 gnutls_assert();
60                 return GNUTLS_E_MEMORY_ERROR;
61         }
62
63         (*key)->info = p11_kit_uri_new();
64         if ((*key)->info == NULL) {
65                 free(*key);
66                 gnutls_assert();
67                 return GNUTLS_E_MEMORY_ERROR;
68         }
69
70         return 0;
71 }
72
73 /**
74  * gnutls_pkcs11_privkey_deinit:
75  * @key: The structure to be initialized
76  *
77  * This function will deinitialize a private key structure.
78  **/
79 void gnutls_pkcs11_privkey_deinit(gnutls_pkcs11_privkey_t key)
80 {
81         p11_kit_uri_free(key->info);
82         if (key->sinfo.init != 0)
83                 pkcs11_close_session(&key->sinfo);
84         gnutls_free(key);
85 }
86
87 /**
88  * gnutls_pkcs11_privkey_get_pk_algorithm:
89  * @key: should contain a #gnutls_pkcs11_privkey_t structure
90  * @bits: if bits is non null it will hold the size of the parameters' in bits
91  *
92  * This function will return the public key algorithm of a private
93  * key.
94  *
95  * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
96  *   success, or a negative error code on error.
97  **/
98 int
99 gnutls_pkcs11_privkey_get_pk_algorithm(gnutls_pkcs11_privkey_t key,
100                                        unsigned int *bits)
101 {
102         if (bits)
103                 *bits = 0;      /* FIXME */
104         return key->pk_algorithm;
105 }
106
107 /**
108  * gnutls_pkcs11_privkey_get_info:
109  * @pkey: should contain a #gnutls_pkcs11_privkey_t structure
110  * @itype: Denotes the type of information requested
111  * @output: where output will be stored
112  * @output_size: contains the maximum size of the output and will be overwritten with actual
113  *
114  * This function will return information about the PKCS 11 private key such
115  * as the label, id as well as token information where the key is stored. When
116  * output is text it returns null terminated string although #output_size contains
117  * the size of the actual data only.
118  *
119  * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
120  **/
121 int
122 gnutls_pkcs11_privkey_get_info(gnutls_pkcs11_privkey_t pkey,
123                                gnutls_pkcs11_obj_info_t itype,
124                                void *output, size_t * output_size)
125 {
126         return pkcs11_get_info(pkey->info, itype, output, output_size);
127 }
128
129 static int
130 find_object(struct pkcs11_session_info *sinfo,
131             struct pin_info_st *pin_info,
132             ck_object_handle_t * _obj,
133             struct p11_kit_uri *info, unsigned int flags)
134 {
135         int ret;
136         ck_object_handle_t obj;
137         struct ck_attribute *attrs;
138         unsigned long attr_count;
139         unsigned long count;
140         ck_rv_t rv;
141
142         ret =
143             pkcs11_open_session(sinfo, pin_info, info,
144                                 flags & SESSION_LOGIN);
145         if (ret < 0) {
146                 gnutls_assert();
147                 return ret;
148         }
149
150         attrs = p11_kit_uri_get_attributes(info, &attr_count);
151         rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, attrs,
152                                       attr_count);
153         if (rv != CKR_OK) {
154                 gnutls_assert();
155                 _gnutls_debug_log("p11: FindObjectsInit failed.\n");
156                 ret = pkcs11_rv_to_err(rv);
157                 goto fail;
158         }
159
160         if (pkcs11_find_objects(sinfo->module, sinfo->pks, &obj, 1, &count)
161             == CKR_OK && count == 1) {
162                 *_obj = obj;
163                 pkcs11_find_objects_final(sinfo);
164                 return 0;
165         }
166
167         ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
168         pkcs11_find_objects_final(sinfo);
169       fail:
170         pkcs11_close_session(sinfo);
171
172         return ret;
173 }
174
175 #define FIND_OBJECT(sinfo, pin_info, obj, key) \
176         do { \
177                 int retries = 0; \
178                 int rret; \
179                 ret = find_object (sinfo, pin_info, &obj, key->info, \
180                                           SESSION_LOGIN); \
181                 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { \
182                         if (_gnutls_token_func) \
183                           { \
184                             rret = pkcs11_call_token_func (key->info, retries++); \
185                             if (rret == 0) continue; \
186                           } \
187                         return gnutls_assert_val(ret); \
188                 } else if (ret < 0) { \
189                         return gnutls_assert_val(ret); \
190                 } \
191         } while (0);
192
193
194 /*-
195  * _gnutls_pkcs11_privkey_sign_hash:
196  * @key: Holds the key
197  * @hash: holds the data to be signed (should be output of a hash)
198  * @signature: will contain the signature allocated with gnutls_malloc()
199  *
200  * This function will sign the given data using a signature algorithm
201  * supported by the private key. It is assumed that the given data
202  * are the output of a hash function.
203  *
204  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
205  *   negative error value.
206  -*/
207 int
208 _gnutls_pkcs11_privkey_sign_hash(gnutls_pkcs11_privkey_t key,
209                                  const gnutls_datum_t * hash,
210                                  gnutls_datum_t * signature)
211 {
212         ck_rv_t rv;
213         int ret;
214         struct ck_mechanism mech;
215         gnutls_datum_t tmp = { NULL, 0 };
216         unsigned long siglen;
217         struct pkcs11_session_info _sinfo;
218         struct pkcs11_session_info *sinfo;
219         ck_object_handle_t obj;
220
221         PKCS11_CHECK_INIT;
222
223         if (key->sinfo.init != 0) {
224                 sinfo = &key->sinfo;
225                 obj = key->obj;
226         } else {
227                 sinfo = &_sinfo;
228                 memset(sinfo, 0, sizeof(*sinfo));
229                 FIND_OBJECT(sinfo, &key->pin, obj, key);
230         }
231
232         mech.mechanism = pk_to_mech(key->pk_algorithm);
233         mech.parameter = NULL;
234         mech.parameter_len = 0;
235
236         /* Initialize signing operation; using the private key discovered
237          * earlier. */
238         rv = pkcs11_sign_init(sinfo->module, sinfo->pks, &mech, obj);
239         if (rv != CKR_OK) {
240                 gnutls_assert();
241                 ret = pkcs11_rv_to_err(rv);
242                 goto cleanup;
243         }
244
245         /* Work out how long the signature must be: */
246         rv = pkcs11_sign(sinfo->module, sinfo->pks, hash->data, hash->size,
247                          NULL, &siglen);
248         if (rv != CKR_OK) {
249                 gnutls_assert();
250                 ret = pkcs11_rv_to_err(rv);
251                 goto cleanup;
252         }
253
254         tmp.data = gnutls_malloc(siglen);
255         tmp.size = siglen;
256
257         rv = pkcs11_sign(sinfo->module, sinfo->pks, hash->data, hash->size,
258                          tmp.data, &siglen);
259         if (rv != CKR_OK) {
260                 gnutls_assert();
261                 ret = pkcs11_rv_to_err(rv);
262                 goto cleanup;
263         }
264
265
266         if (key->pk_algorithm == GNUTLS_PK_EC
267             || key->pk_algorithm == GNUTLS_PK_DSA) {
268                 unsigned int hlen = siglen / 2;
269                 gnutls_datum_t r, s;
270
271                 if (siglen % 2 != 0) {
272                         gnutls_assert();
273                         ret = GNUTLS_E_PK_SIGN_FAILED;
274                         goto cleanup;
275                 }
276
277                 r.data = tmp.data;
278                 r.size = hlen;
279
280                 s.data = &tmp.data[hlen];
281                 s.size = hlen;
282
283                 ret = _gnutls_encode_ber_rs_raw(signature, &r, &s);
284                 if (ret < 0) {
285                         gnutls_assert();
286                         goto cleanup;
287                 }
288
289                 gnutls_free(tmp.data);
290                 tmp.data = NULL;
291         } else {
292                 signature->size = siglen;
293                 signature->data = tmp.data;
294         }
295
296         ret = 0;
297
298       cleanup:
299         if (sinfo != &key->sinfo)
300                 pkcs11_close_session(sinfo);
301         if (ret < 0)
302                 gnutls_free(tmp.data);
303
304         return ret;
305 }
306
307 /**
308  * gnutls_pkcs11_privkey_status:
309  * @key: Holds the key
310  *
311  * Checks the status of the private key token.
312  *
313  * Returns: this function will return non-zero if the token 
314  * holding the private key is still available (inserted), and zero otherwise.
315  * 
316  * Since: 3.1.9
317  *
318  **/
319 int gnutls_pkcs11_privkey_status(gnutls_pkcs11_privkey_t key)
320 {
321         ck_rv_t rv;
322         int ret;
323         struct pkcs11_session_info _sinfo;
324         struct pkcs11_session_info *sinfo;
325         ck_object_handle_t obj;
326         struct ck_session_info session_info;
327         
328         PKCS11_CHECK_INIT;
329
330         if (key->sinfo.init != 0) {
331                 sinfo = &key->sinfo;
332                 obj = key->obj;
333         } else {
334                 sinfo = &_sinfo;
335                 memset(sinfo, 0, sizeof(*sinfo));
336                 FIND_OBJECT(sinfo, &key->pin, obj, key);
337         }
338
339         rv = (sinfo->module)->C_GetSessionInfo(sinfo->pks, &session_info);
340         if (rv != CKR_OK) {
341                 ret = 0;
342                 goto cleanup;
343         }
344         ret = 1;
345
346       cleanup:
347         if (sinfo != &key->sinfo)
348                 pkcs11_close_session(sinfo);
349
350         return ret;
351 }
352
353 /**
354  * gnutls_pkcs11_privkey_import_url:
355  * @pkey: The structure to store the parsed key
356  * @url: a PKCS 11 url identifying the key
357  * @flags: sequence of GNUTLS_PKCS_PRIVKEY_*
358  *
359  * This function will "import" a PKCS 11 URL identifying a private
360  * key to the #gnutls_pkcs11_privkey_t structure. In reality since
361  * in most cases keys cannot be exported, the private key structure
362  * is being associated with the available operations on the token.
363  *
364  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
365  *   negative error value.
366  **/
367 int
368 gnutls_pkcs11_privkey_import_url(gnutls_pkcs11_privkey_t pkey,
369                                  const char *url, unsigned int flags)
370 {
371         int ret;
372         struct ck_attribute *attr;
373         ck_object_handle_t obj;
374         struct ck_attribute a[4];
375         ck_key_type_t key_type;
376         struct pkcs11_session_info sinfo;
377
378         PKCS11_CHECK_INIT;
379
380         memset(&sinfo, 0, sizeof(sinfo));
381
382         ret = pkcs11_url_to_info(url, &pkey->info);
383         if (ret < 0) {
384                 gnutls_assert();
385                 return ret;
386         }
387
388         pkey->flags = flags;
389
390         attr = p11_kit_uri_get_attribute(pkey->info, CKA_CLASS);
391         if (!attr || attr->value_len != sizeof(ck_object_class_t) ||
392             *(ck_object_class_t *) attr->value != CKO_PRIVATE_KEY) {
393                 gnutls_assert();
394                 return GNUTLS_E_INVALID_REQUEST;
395         }
396
397         attr = p11_kit_uri_get_attribute(pkey->info, CKA_ID);
398         if (!attr || !attr->value_len) {
399                 attr = p11_kit_uri_get_attribute(pkey->info, CKA_LABEL);
400                 if (!attr || !attr->value_len) {
401                         gnutls_assert();
402                         return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
403                 }
404         }
405
406         FIND_OBJECT(&sinfo, &pkey->pin, obj, pkey);
407
408         a[0].type = CKA_KEY_TYPE;
409         a[0].value = &key_type;
410         a[0].value_len = sizeof(key_type);
411
412         if (pkcs11_get_attribute_value(sinfo.module, sinfo.pks, obj, a, 1)
413             == CKR_OK) {
414                 pkey->pk_algorithm = mech_to_pk(key_type);
415                 if (pkey->pk_algorithm == GNUTLS_PK_UNKNOWN) {
416                         _gnutls_debug_log
417                             ("Cannot determine PKCS #11 key algorithm\n");
418                         ret = GNUTLS_E_UNKNOWN_ALGORITHM;
419                         goto cleanup;
420                 }
421         }
422
423         ret = 0;
424
425         if (pkey->sinfo.init)
426                 pkcs11_close_session(&pkey->sinfo);
427
428         if (sinfo.tinfo.max_session_count != 1) {
429                 /* We do not keep the session open in tokens that can 
430                  * only support a single session.
431                  */
432                 memcpy(&pkey->sinfo, &sinfo, sizeof(pkey->sinfo));
433                 pkey->obj = obj;
434                 return ret;
435         }
436
437       cleanup:
438         pkcs11_close_session(&sinfo);
439
440         return ret;
441 }
442
443 /*-
444  * _gnutls_pkcs11_privkey_decrypt_data:
445  * @key: Holds the key
446  * @flags: should be 0 for now
447  * @ciphertext: holds the data to be signed
448  * @plaintext: will contain the plaintext, allocated with gnutls_malloc()
449  *
450  * This function will decrypt the given data using the public key algorithm
451  * supported by the private key. 
452  *
453  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
454  *   negative error value.
455  -*/
456 int
457 _gnutls_pkcs11_privkey_decrypt_data(gnutls_pkcs11_privkey_t key,
458                                     unsigned int flags,
459                                     const gnutls_datum_t * ciphertext,
460                                     gnutls_datum_t * plaintext)
461 {
462         ck_rv_t rv;
463         int ret;
464         struct ck_mechanism mech;
465         unsigned long siglen;
466         ck_object_handle_t obj;
467         struct pkcs11_session_info _sinfo;
468         struct pkcs11_session_info *sinfo;
469
470         PKCS11_CHECK_INIT;
471
472         if (key->sinfo.init != 0) {
473                 sinfo = &key->sinfo;
474                 obj = key->obj;
475         } else {
476                 sinfo = &_sinfo;
477                 memset(sinfo, 0, sizeof(*sinfo));
478                 FIND_OBJECT(sinfo, &key->pin, obj, key);
479         }
480
481         if (key->pk_algorithm != GNUTLS_PK_RSA)
482                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
483
484         mech.mechanism = CKM_RSA_PKCS;
485         mech.parameter = NULL;
486         mech.parameter_len = 0;
487
488         /* Initialize signing operation; using the private key discovered
489          * earlier. */
490         rv = pkcs11_decrypt_init(sinfo->module, sinfo->pks, &mech, obj);
491         if (rv != CKR_OK) {
492                 gnutls_assert();
493                 ret = pkcs11_rv_to_err(rv);
494                 goto cleanup;
495         }
496
497         /* Work out how long the plaintext must be: */
498         rv = pkcs11_decrypt(sinfo->module, sinfo->pks, ciphertext->data,
499                             ciphertext->size, NULL, &siglen);
500         if (rv != CKR_OK) {
501                 gnutls_assert();
502                 ret = pkcs11_rv_to_err(rv);
503                 goto cleanup;
504         }
505
506         plaintext->data = gnutls_malloc(siglen);
507         plaintext->size = siglen;
508
509         rv = pkcs11_decrypt(sinfo->module, sinfo->pks, ciphertext->data,
510                             ciphertext->size, plaintext->data, &siglen);
511         if (rv != CKR_OK) {
512                 gnutls_free(plaintext->data);
513                 gnutls_assert();
514                 ret = pkcs11_rv_to_err(rv);
515                 goto cleanup;
516         }
517
518         plaintext->size = siglen;
519
520         ret = 0;
521
522       cleanup:
523         if (key->sinfo.init == 0)
524                 pkcs11_close_session(sinfo);
525
526         return ret;
527 }
528
529 /**
530  * gnutls_pkcs11_privkey_export_url:
531  * @key: Holds the PKCS 11 key
532  * @detailed: non zero if a detailed URL is required
533  * @url: will contain an allocated url
534  *
535  * This function will export a URL identifying the given key.
536  *
537  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
538  *   negative error value.
539  **/
540 int
541 gnutls_pkcs11_privkey_export_url(gnutls_pkcs11_privkey_t key,
542                                  gnutls_pkcs11_url_type_t detailed,
543                                  char **url)
544 {
545         int ret;
546
547         ret = pkcs11_info_to_url(key->info, detailed, url);
548         if (ret < 0) {
549                 gnutls_assert();
550                 return ret;
551         }
552
553         return 0;
554 }
555
556
557 /**
558  * gnutls_pkcs11_privkey_generate:
559  * @url: a token URL
560  * @pk: the public key algorithm
561  * @bits: the security bits
562  * @label: a label
563  * @flags: should be zero
564  *
565  * This function will generate a private key in the specified
566  * by the @url token. The private key will be generate within
567  * the token and will not be exportable.
568  *
569  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
570  *   negative error value.
571  *
572  * Since: 3.0
573  **/
574 int
575 gnutls_pkcs11_privkey_generate(const char *url, gnutls_pk_algorithm_t pk,
576                                unsigned int bits, const char *label,
577                                unsigned int flags)
578 {
579         return gnutls_pkcs11_privkey_generate2(url, pk, bits, label, 0,
580                                                NULL, flags);
581 }
582
583 /**
584  * gnutls_pkcs11_privkey_generate2:
585  * @url: a token URL
586  * @pk: the public key algorithm
587  * @bits: the security bits
588  * @label: a label
589  * @fmt: the format of output params. PEM or DER.
590  * @pubkey: will hold the public key (may be %NULL)
591  * @flags: should be zero
592  *
593  * This function will generate a private key in the specified
594  * by the @url token. The private key will be generate within
595  * the token and will not be exportable. This function will
596  * store the DER-encoded public key in the SubjectPublicKeyInfo format 
597  * in @pubkey. The @pubkey should be deinitialized using gnutls_free().
598  *
599  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
600  *   negative error value.
601  *
602  * Since: 3.1.5
603  **/
604 int
605 gnutls_pkcs11_privkey_generate2(const char *url, gnutls_pk_algorithm_t pk,
606                                 unsigned int bits, const char *label,
607                                 gnutls_x509_crt_fmt_t fmt,
608                                 gnutls_datum_t * pubkey,
609                                 unsigned int flags)
610 {
611         int ret;
612         const ck_bool_t tval = 1;
613         const ck_bool_t fval = 0;
614         struct pkcs11_session_info sinfo;
615         struct p11_kit_uri *info = NULL;
616         ck_rv_t rv;
617         struct ck_attribute a[10], p[10];
618         ck_object_handle_t pub, priv;
619         unsigned long _bits = bits;
620         int a_val, p_val;
621         struct ck_mechanism mech;
622         gnutls_pubkey_t pkey = NULL;
623         gnutls_pkcs11_obj_t obj = NULL;
624
625         PKCS11_CHECK_INIT;
626
627         memset(&sinfo, 0, sizeof(sinfo));
628
629         ret = pkcs11_url_to_info(url, &info);
630         if (ret < 0) {
631                 gnutls_assert();
632                 return ret;
633         }
634
635         ret =
636             pkcs11_open_session(&sinfo, NULL, info,
637                                 SESSION_WRITE |
638                                 pkcs11_obj_flags_to_int(flags));
639         p11_kit_uri_free(info);
640
641         if (ret < 0) {
642                 gnutls_assert();
643                 goto cleanup;
644         }
645
646         /* a holds the public key template
647          * and p the private key */
648         a_val = p_val = 0;
649         mech.parameter = NULL;
650         mech.parameter_len = 0;
651         mech.mechanism = pk_to_genmech(pk);
652
653         switch (pk) {
654         case GNUTLS_PK_RSA:
655                 p[p_val].type = CKA_DECRYPT;
656                 p[p_val].value = (void *) &tval;
657                 p[p_val].value_len = sizeof(tval);
658                 p_val++;
659
660                 p[p_val].type = CKA_SIGN;
661                 p[p_val].value = (void *) &tval;
662                 p[p_val].value_len = sizeof(tval);
663                 p_val++;
664
665                 a[a_val].type = CKA_ENCRYPT;
666                 a[a_val].value = (void *) &tval;
667                 a[a_val].value_len = sizeof(tval);
668                 a_val++;
669
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++;
674
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         case GNUTLS_PK_DSA:
681                 p[p_val].type = CKA_SIGN;
682                 p[p_val].value = (void *) &tval;
683                 p[p_val].value_len = sizeof(tval);
684                 p_val++;
685
686                 a[a_val].type = CKA_VERIFY;
687                 a[a_val].value = (void *) &tval;
688                 a[a_val].value_len = sizeof(tval);
689                 a_val++;
690
691                 a[a_val].type = CKA_MODULUS_BITS;
692                 a[a_val].value = &_bits;
693                 a[a_val].value_len = sizeof(_bits);
694                 a_val++;
695                 break;
696         case GNUTLS_PK_EC:
697                 p[p_val].type = CKA_SIGN;
698                 p[p_val].value = (void *) &tval;
699                 p[p_val].value_len = sizeof(tval);
700                 p_val++;
701
702                 a[a_val].type = CKA_VERIFY;
703                 a[a_val].value = (void *) &tval;
704                 a[a_val].value_len = sizeof(tval);
705                 a_val++;
706
707                 a[a_val].type = CKA_MODULUS_BITS;
708                 a[a_val].value = &_bits;
709                 a[a_val].value_len = sizeof(_bits);
710                 a_val++;
711                 break;
712         default:
713                 ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
714                 goto cleanup;
715         }
716
717         /* a private key is set always as private unless
718          * requested otherwise
719          */
720         if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE) {
721                 p[p_val].type = CKA_PRIVATE;
722                 p[p_val].value = (void *) &fval;
723                 p[p_val].value_len = sizeof(fval);
724                 p_val++;
725         } else {
726                 p[p_val].type = CKA_PRIVATE;
727                 p[p_val].value = (void *) &tval;
728                 p[p_val].value_len = sizeof(tval);
729                 p_val++;
730         }
731
732         p[p_val].type = CKA_TOKEN;
733         p[p_val].value = (void *) &tval;
734         p[p_val].value_len = sizeof(tval);
735         p_val++;
736
737         if (label) {
738                 p[p_val].type = CKA_LABEL;
739                 p[p_val].value = (void *) label;
740                 p[p_val].value_len = strlen(label);
741                 p_val++;
742
743                 a[a_val].type = CKA_LABEL;
744                 a[a_val].value = (void *) label;
745                 a[a_val].value_len = strlen(label);
746                 a_val++;
747         }
748
749         if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE) {
750                 p[p_val].type = CKA_SENSITIVE;
751                 p[p_val].value = (void *) &tval;
752                 p[p_val].value_len = sizeof(tval);
753                 p_val++;
754         } else {
755                 p[p_val].type = CKA_SENSITIVE;
756                 p[p_val].value = (void *) &fval;
757                 p[p_val].value_len = sizeof(fval);
758                 p_val++;
759         }
760
761         rv = pkcs11_generate_key_pair(sinfo.module, sinfo.pks, &mech, a,
762                                       a_val, p, p_val, &pub, &priv);
763         if (rv != CKR_OK) {
764                 gnutls_assert();
765                 _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
766                 ret = pkcs11_rv_to_err(rv);
767                 goto cleanup;
768         }
769
770         /* extract the public key */
771         if (pubkey) {
772                 ret = gnutls_pubkey_init(&pkey);
773                 if (ret < 0) {
774                         gnutls_assert();
775                         goto cleanup;
776                 }
777
778                 ret = gnutls_pkcs11_obj_init(&obj);
779                 if (ret < 0) {
780                         gnutls_assert();
781                         goto cleanup;
782                 }
783
784                 obj->pk_algorithm = pk;
785                 obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
786                 ret =
787                     pkcs11_read_pubkey(sinfo.module, sinfo.pks, pub,
788                                        mech.mechanism, obj->pubkey);
789                 if (ret < 0) {
790                         gnutls_assert();
791                         goto cleanup;
792                 }
793
794                 ret = gnutls_pubkey_import_pkcs11(pkey, obj, 0);
795                 if (ret < 0) {
796                         gnutls_assert();
797                         goto cleanup;
798                 }
799
800                 ret = gnutls_pubkey_export2(pkey, fmt, pubkey);
801                 if (ret < 0) {
802                         gnutls_assert();
803                         goto cleanup;
804                 }
805         }
806
807
808       cleanup:
809         if (obj != NULL)
810                 gnutls_pkcs11_obj_deinit(obj);
811         if (pkey != NULL)
812                 gnutls_pubkey_deinit(pkey);
813         if (sinfo.pks != 0)
814                 pkcs11_close_session(&sinfo);
815
816         return ret;
817 }
818
819 /**
820  * gnutls_pkcs11_privkey_set_pin_function:
821  * @key: The private key
822  * @fn: the callback
823  * @userdata: data associated with the callback
824  *
825  * This function will set a callback function to be used when
826  * required to access the object. This function overrides the global
827  * set using gnutls_pkcs11_set_pin_function().
828  *
829  * Since: 3.1.0
830  *
831  **/
832 void
833 gnutls_pkcs11_privkey_set_pin_function(gnutls_pkcs11_privkey_t key,
834                                        gnutls_pin_callback_t fn,
835                                        void *userdata)
836 {
837         key->pin.cb = fn;
838         key->pin.data = userdata;
839 }