Merge branch 'upstream' into tizen
[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 "urls.h"
32 #include <p11-kit/uri.h>
33
34 /* In case of a fork, it will invalidate the open session
35  * in the privkey and start another */
36 #define PKCS11_CHECK_INIT_PRIVKEY(k) \
37         ret = _gnutls_pkcs11_check_init(); \
38         if (ret < 0) \
39                 return gnutls_assert_val(ret); \
40         if (ret == 1) { \
41                 memset(&k->sinfo, 0, sizeof(k->sinfo)); \
42                 FIND_OBJECT(k); \
43         }
44
45 #define FIND_OBJECT(key) \
46         do { \
47                 int retries = 0; \
48                 int rret; \
49                 ret = find_object (&key->sinfo, &key->pin, &key->ref, key->uinfo, \
50                                           SESSION_LOGIN); \
51                 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { \
52                         if (_gnutls_token_func) \
53                           { \
54                             rret = pkcs11_call_token_func (key->uinfo, retries++); \
55                             if (rret == 0) continue; \
56                           } \
57                         return gnutls_assert_val(ret); \
58                 } else if (ret < 0) { \
59                         return gnutls_assert_val(ret); \
60                 } \
61                 break; \
62         } while (1);
63
64 struct gnutls_pkcs11_privkey_st {
65         gnutls_pk_algorithm_t pk_algorithm;
66         unsigned int flags;
67         struct p11_kit_uri *uinfo;
68         char *url;
69
70         struct pkcs11_session_info sinfo;
71         ck_object_handle_t ref; /* the key in the session */
72         unsigned reauth; /* whether we need to login on each operation */
73
74         struct pin_info_st pin;
75 };
76
77 /**
78  * gnutls_pkcs11_privkey_init:
79  * @key: A pointer to the type to be initialized
80  *
81  * This function will initialize an private key structure.
82  *
83  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
84  *   negative error value.
85  **/
86 int gnutls_pkcs11_privkey_init(gnutls_pkcs11_privkey_t * key)
87 {
88         FAIL_IF_LIB_ERROR;
89
90         *key = gnutls_calloc(1, sizeof(struct gnutls_pkcs11_privkey_st));
91         if (*key == NULL) {
92                 gnutls_assert();
93                 return GNUTLS_E_MEMORY_ERROR;
94         }
95
96         (*key)->uinfo = p11_kit_uri_new();
97         if ((*key)->uinfo == NULL) {
98                 free(*key);
99                 gnutls_assert();
100                 return GNUTLS_E_MEMORY_ERROR;
101         }
102
103         return 0;
104 }
105
106 /**
107  * gnutls_pkcs11_privkey_cpy:
108  * @dst: The destination key, which should be initialized.
109  * @src: The source key
110  *
111  * This function will copy a private key from source to destination
112  * key. Destination has to be initialized.
113  *
114  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
115  *   negative error value.
116  *
117  * Since: 3.4.0
118  **/
119 int
120 gnutls_pkcs11_privkey_cpy(gnutls_pkcs11_privkey_t dst,
121                           gnutls_pkcs11_privkey_t src)
122 {
123         return gnutls_pkcs11_privkey_import_url(dst, src->url, src->flags);
124 }
125
126 /**
127  * gnutls_pkcs11_privkey_deinit:
128  * @key: the key to be deinitialized
129  *
130  * This function will deinitialize a private key structure.
131  **/
132 void gnutls_pkcs11_privkey_deinit(gnutls_pkcs11_privkey_t key)
133 {
134         p11_kit_uri_free(key->uinfo);
135         gnutls_free(key->url);
136         if (key->sinfo.init != 0)
137                 pkcs11_close_session(&key->sinfo);
138         gnutls_free(key);
139 }
140
141 /**
142  * gnutls_pkcs11_privkey_get_pk_algorithm:
143  * @key: should contain a #gnutls_pkcs11_privkey_t type
144  * @bits: if bits is non null it will hold the size of the parameters' in bits
145  *
146  * This function will return the public key algorithm of a private
147  * key.
148  *
149  * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
150  *   success, or a negative error code on error.
151  **/
152 int
153 gnutls_pkcs11_privkey_get_pk_algorithm(gnutls_pkcs11_privkey_t key,
154                                        unsigned int *bits)
155 {
156         if (bits)
157                 *bits = 0;      /* FIXME */
158         return key->pk_algorithm;
159 }
160
161 /**
162  * gnutls_pkcs11_privkey_get_info:
163  * @pkey: should contain a #gnutls_pkcs11_privkey_t type
164  * @itype: Denotes the type of information requested
165  * @output: where output will be stored
166  * @output_size: contains the maximum size of the output and will be overwritten with actual
167  *
168  * This function will return information about the PKCS 11 private key such
169  * as the label, id as well as token information where the key is stored. When
170  * output is text it returns null terminated string although #output_size contains
171  * the size of the actual data only.
172  *
173  * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
174  **/
175 int
176 gnutls_pkcs11_privkey_get_info(gnutls_pkcs11_privkey_t pkey,
177                                gnutls_pkcs11_obj_info_t itype,
178                                void *output, size_t * output_size)
179 {
180         return pkcs11_get_info(pkey->uinfo, itype, output, output_size);
181 }
182
183 static int
184 find_object(struct pkcs11_session_info *sinfo,
185             struct pin_info_st *pin_info,
186             ck_object_handle_t * _obj,
187             struct p11_kit_uri *info, unsigned int flags)
188 {
189         int ret;
190         ck_object_handle_t obj;
191         struct ck_attribute *attrs;
192         unsigned long attr_count;
193         unsigned long count;
194         ck_rv_t rv;
195
196         ret =
197             pkcs11_open_session(sinfo, pin_info, info,
198                                 flags & SESSION_LOGIN);
199         if (ret < 0) {
200                 gnutls_assert();
201                 return ret;
202         }
203
204         attrs = p11_kit_uri_get_attributes(info, &attr_count);
205         rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, attrs,
206                                       attr_count);
207         if (rv != CKR_OK) {
208                 gnutls_assert();
209                 _gnutls_debug_log("p11: FindObjectsInit failed.\n");
210                 ret = pkcs11_rv_to_err(rv);
211                 goto fail;
212         }
213
214         if (pkcs11_find_objects(sinfo->module, sinfo->pks, &obj, 1, &count)
215             == CKR_OK && count == 1) {
216                 *_obj = obj;
217                 pkcs11_find_objects_final(sinfo);
218                 return 0;
219         }
220
221         ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
222         pkcs11_find_objects_final(sinfo);
223       fail:
224         pkcs11_close_session(sinfo);
225
226         return ret;
227 }
228
229
230
231 /*-
232  * _gnutls_pkcs11_privkey_sign_hash:
233  * @key: Holds the key
234  * @hash: holds the data to be signed (should be output of a hash)
235  * @signature: will contain the signature allocated with gnutls_malloc()
236  *
237  * This function will sign the given data using a signature algorithm
238  * supported by the private key. It is assumed that the given data
239  * are the output of a hash function.
240  *
241  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
242  *   negative error value.
243  -*/
244 int
245 _gnutls_pkcs11_privkey_sign_hash(gnutls_pkcs11_privkey_t key,
246                                  const gnutls_datum_t * hash,
247                                  gnutls_datum_t * signature)
248 {
249         ck_rv_t rv;
250         int ret;
251         struct ck_mechanism mech;
252         gnutls_datum_t tmp = { NULL, 0 };
253         unsigned long siglen;
254         struct pkcs11_session_info *sinfo;
255
256         PKCS11_CHECK_INIT_PRIVKEY(key);
257
258         sinfo = &key->sinfo;
259
260         mech.mechanism = pk_to_mech(key->pk_algorithm);
261         mech.parameter = NULL;
262         mech.parameter_len = 0;
263
264         /* Initialize signing operation; using the private key discovered
265          * earlier. */
266         rv = pkcs11_sign_init(sinfo->module, sinfo->pks, &mech, key->ref);
267         if (rv != CKR_OK) {
268                 gnutls_assert();
269                 ret = pkcs11_rv_to_err(rv);
270                 goto cleanup;
271         }
272
273         if (key->reauth) {
274                 ret =
275                     pkcs11_login(&key->sinfo, &key->pin,
276                                  key->uinfo, 0, 1);
277                 if (ret < 0) {
278                         gnutls_assert();
279                         _gnutls_debug_log("PKCS #11 login failed, trying operation anyway\n");
280                         /* let's try the operation anyway */
281                 }
282         }
283
284         /* Work out how long the signature must be: */
285         rv = pkcs11_sign(sinfo->module, sinfo->pks, hash->data, hash->size,
286                          NULL, &siglen);
287         if (rv != CKR_OK) {
288                 gnutls_assert();
289                 ret = pkcs11_rv_to_err(rv);
290                 goto cleanup;
291         }
292
293         tmp.data = gnutls_malloc(siglen);
294         tmp.size = siglen;
295
296         rv = pkcs11_sign(sinfo->module, sinfo->pks, hash->data, hash->size,
297                          tmp.data, &siglen);
298         if (rv != CKR_OK) {
299                 gnutls_assert();
300                 ret = pkcs11_rv_to_err(rv);
301                 goto cleanup;
302         }
303
304
305         if (key->pk_algorithm == GNUTLS_PK_EC
306             || key->pk_algorithm == GNUTLS_PK_DSA) {
307                 unsigned int hlen = siglen / 2;
308                 gnutls_datum_t r, s;
309
310                 if (siglen % 2 != 0) {
311                         gnutls_assert();
312                         ret = GNUTLS_E_PK_SIGN_FAILED;
313                         goto cleanup;
314                 }
315
316                 r.data = tmp.data;
317                 r.size = hlen;
318
319                 s.data = &tmp.data[hlen];
320                 s.size = hlen;
321
322                 ret = _gnutls_encode_ber_rs_raw(signature, &r, &s);
323                 if (ret < 0) {
324                         gnutls_assert();
325                         goto cleanup;
326                 }
327
328                 gnutls_free(tmp.data);
329                 tmp.data = NULL;
330         } else {
331                 signature->size = siglen;
332                 signature->data = tmp.data;
333         }
334
335         ret = 0;
336
337       cleanup:
338         if (sinfo != &key->sinfo)
339                 pkcs11_close_session(sinfo);
340         if (ret < 0)
341                 gnutls_free(tmp.data);
342
343         return ret;
344 }
345
346 /**
347  * gnutls_pkcs11_privkey_status:
348  * @key: Holds the key
349  *
350  * Checks the status of the private key token.
351  *
352  * Returns: this function will return non-zero if the token 
353  * holding the private key is still available (inserted), and zero otherwise.
354  * 
355  * Since: 3.1.9
356  *
357  **/
358 int gnutls_pkcs11_privkey_status(gnutls_pkcs11_privkey_t key)
359 {
360         ck_rv_t rv;
361         int ret;
362         struct ck_session_info session_info;
363         
364         PKCS11_CHECK_INIT_PRIVKEY(key);
365
366         rv = (key->sinfo.module)->C_GetSessionInfo(key->sinfo.pks, &session_info);
367         if (rv != CKR_OK) {
368                 ret = 0;
369                 goto cleanup;
370         }
371         ret = 1;
372
373       cleanup:
374
375         return ret;
376 }
377
378 /**
379  * gnutls_pkcs11_privkey_import_url:
380  * @pkey: The private key
381  * @url: a PKCS 11 url identifying the key
382  * @flags: Or sequence of GNUTLS_PKCS11_OBJ_* flags
383  *
384  * This function will "import" a PKCS 11 URL identifying a private
385  * key to the #gnutls_pkcs11_privkey_t type. In reality since
386  * in most cases keys cannot be exported, the private key structure
387  * is being associated with the available operations on the token.
388  *
389  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
390  *   negative error value.
391  **/
392 int
393 gnutls_pkcs11_privkey_import_url(gnutls_pkcs11_privkey_t pkey,
394                                  const char *url, unsigned int flags)
395 {
396         int ret;
397         struct ck_attribute *attr;
398         struct ck_attribute a[4];
399         ck_key_type_t key_type;
400         ck_bool_t reauth = 0;
401
402         PKCS11_CHECK_INIT;
403
404         memset(&pkey->sinfo, 0, sizeof(pkey->sinfo));
405
406         if (pkey->url) {
407                 gnutls_free(pkey->url);
408                 pkey->url = NULL;
409         }
410
411         if (pkey->uinfo) {
412                 p11_kit_uri_free(pkey->uinfo);
413                 pkey->uinfo = NULL;
414         }
415
416         pkey->url = gnutls_strdup(url);
417         if (pkey->url == NULL)
418                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
419
420         ret = pkcs11_url_to_info(pkey->url, &pkey->uinfo, flags|GNUTLS_PKCS11_OBJ_FLAG_EXPECT_PRIVKEY);
421         if (ret < 0) {
422                 gnutls_assert();
423                 goto cleanup;
424         }
425
426         pkey->flags = flags;
427
428         attr = p11_kit_uri_get_attribute(pkey->uinfo, CKA_CLASS);
429         if (!attr || attr->value_len != sizeof(ck_object_class_t) ||
430             *(ck_object_class_t *) attr->value != CKO_PRIVATE_KEY) {
431                 gnutls_assert();
432                 ret = GNUTLS_E_INVALID_REQUEST;
433                 goto cleanup;
434         }
435
436         attr = p11_kit_uri_get_attribute(pkey->uinfo, CKA_ID);
437         if (!attr) {
438                 attr = p11_kit_uri_get_attribute(pkey->uinfo, CKA_LABEL);
439                 if (!attr) {
440                         gnutls_assert();
441                         ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
442                         goto cleanup;
443                 }
444         }
445
446         FIND_OBJECT(pkey);
447
448         a[0].type = CKA_KEY_TYPE;
449         a[0].value = &key_type;
450         a[0].value_len = sizeof(key_type);
451
452         if (pkcs11_get_attribute_value(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, a, 1)
453             == CKR_OK) {
454                 pkey->pk_algorithm = key_type_to_pk(key_type);
455                 if (pkey->pk_algorithm == GNUTLS_PK_UNKNOWN) {
456                         _gnutls_debug_log
457                             ("Cannot determine PKCS #11 key algorithm\n");
458                         ret = GNUTLS_E_UNKNOWN_ALGORITHM;
459                         goto cleanup;
460                 }
461         }
462
463         a[0].type = CKA_ALWAYS_AUTHENTICATE;
464         a[0].value = &reauth;
465         a[0].value_len = sizeof(reauth);
466
467         if (pkcs11_get_attribute_value(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, a, 1)
468             == CKR_OK) {
469                 pkey->reauth = reauth;
470         }
471
472         ret = 0;
473
474         return ret;
475
476       cleanup:
477         if (pkey->uinfo != NULL) {
478                 p11_kit_uri_free(pkey->uinfo);
479                 pkey->uinfo = NULL;
480         }
481         gnutls_free(pkey->url);
482         pkey->url = NULL;
483
484         return ret;
485 }
486
487 /*-
488  * _gnutls_pkcs11_privkey_decrypt_data:
489  * @key: Holds the key
490  * @flags: should be 0 for now
491  * @ciphertext: holds the data to be signed
492  * @plaintext: will contain the plaintext, allocated with gnutls_malloc()
493  *
494  * This function will decrypt the given data using the public key algorithm
495  * supported by the private key. 
496  *
497  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
498  *   negative error value.
499  -*/
500 int
501 _gnutls_pkcs11_privkey_decrypt_data(gnutls_pkcs11_privkey_t key,
502                                     unsigned int flags,
503                                     const gnutls_datum_t * ciphertext,
504                                     gnutls_datum_t * plaintext)
505 {
506         ck_rv_t rv;
507         int ret;
508         struct ck_mechanism mech;
509         unsigned long siglen;
510
511         PKCS11_CHECK_INIT_PRIVKEY(key);
512
513         if (key->pk_algorithm != GNUTLS_PK_RSA)
514                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
515
516         mech.mechanism = CKM_RSA_PKCS;
517         mech.parameter = NULL;
518         mech.parameter_len = 0;
519
520         /* Initialize signing operation; using the private key discovered
521          * earlier. */
522         rv = pkcs11_decrypt_init(key->sinfo.module, key->sinfo.pks, &mech, key->ref);
523         if (rv != CKR_OK) {
524                 gnutls_assert();
525                 ret = pkcs11_rv_to_err(rv);
526                 goto cleanup;
527         }
528
529         if (key->reauth) {
530                 ret =
531                     pkcs11_login(&key->sinfo, &key->pin,
532                                  key->uinfo, 0, 1);
533                 if (ret < 0) {
534                         gnutls_assert();
535                         _gnutls_debug_log("PKCS #11 login failed, trying operation anyway\n");
536                         /* let's try the operation anyway */
537                 }
538         }
539
540         /* Work out how long the plaintext must be: */
541         rv = pkcs11_decrypt(key->sinfo.module, key->sinfo.pks, ciphertext->data,
542                             ciphertext->size, NULL, &siglen);
543         if (rv != CKR_OK) {
544                 gnutls_assert();
545                 ret = pkcs11_rv_to_err(rv);
546                 goto cleanup;
547         }
548
549         plaintext->data = gnutls_malloc(siglen);
550         plaintext->size = siglen;
551
552         rv = pkcs11_decrypt(key->sinfo.module, key->sinfo.pks, ciphertext->data,
553                             ciphertext->size, plaintext->data, &siglen);
554         if (rv != CKR_OK) {
555                 gnutls_free(plaintext->data);
556                 gnutls_assert();
557                 ret = pkcs11_rv_to_err(rv);
558                 goto cleanup;
559         }
560
561         plaintext->size = siglen;
562
563         ret = 0;
564
565       cleanup:
566         return ret;
567 }
568
569 /**
570  * gnutls_pkcs11_privkey_export_url:
571  * @key: Holds the PKCS 11 key
572  * @detailed: non zero if a detailed URL is required
573  * @url: will contain an allocated url
574  *
575  * This function will export a URL identifying the given key.
576  *
577  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
578  *   negative error value.
579  **/
580 int
581 gnutls_pkcs11_privkey_export_url(gnutls_pkcs11_privkey_t key,
582                                  gnutls_pkcs11_url_type_t detailed,
583                                  char **url)
584 {
585         int ret;
586
587         ret = pkcs11_info_to_url(key->uinfo, detailed, url);
588         if (ret < 0) {
589                 gnutls_assert();
590                 return ret;
591         }
592
593         return 0;
594 }
595
596 #if 0
597 /**
598  * gnutls_pkcs11_privkey_generate:
599  * @url: a token URL
600  * @pk: the public key algorithm
601  * @bits: the security bits
602  * @label: a label
603  * @flags: should be zero
604  *
605  * This function will generate a private key in the specified
606  * by the @url token. The private key will be generate within
607  * the token and will not be exportable.
608  *
609  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
610  *   negative error value.
611  *
612  * Since: 3.0
613  **/
614 int
615 gnutls_pkcs11_privkey_generate(const char *url, gnutls_pk_algorithm_t pk,
616                                unsigned int bits, const char *label,
617                                unsigned int flags)
618 {
619         int x;
620 }
621
622 /**
623  * gnutls_pkcs11_privkey_generate2:
624  * @url: a token URL
625  * @pk: the public key algorithm
626  * @bits: the security bits
627  * @label: a label
628  * @fmt: the format of output params. PEM or DER
629  * @pubkey: will hold the public key (may be %NULL)
630  * @flags: zero or an OR'ed sequence of %GNUTLS_PKCS11_OBJ_FLAGs
631  *
632  * This function will generate a private key in the specified
633  * by the @url token. The private key will be generate within
634  * the token and will not be exportable. This function will
635  * store the DER-encoded public key in the SubjectPublicKeyInfo format 
636  * in @pubkey. The @pubkey should be deinitialized using gnutls_free().
637  *
638  * Note that when generating an elliptic curve key, the curve
639  * can be substituted in the place of the bits parameter using the
640  * GNUTLS_CURVE_TO_BITS() macro.
641  *
642  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
643  *   negative error value.
644  *
645  * Since: 3.1.5
646  **/
647 int
648 gnutls_pkcs11_privkey_generate2(const char *url, gnutls_pk_algorithm_t pk,
649                                 unsigned int bits, const char *label,
650                                 gnutls_x509_crt_fmt_t fmt,
651                                 gnutls_datum_t * pubkey,
652                                 unsigned int flags)
653 {
654         int x;
655 }
656 #endif
657
658 struct dsa_params {
659         /* FIPS 186-3 maximal size for L and N length pair is (3072,256). */
660         uint8_t prime[384];
661         uint8_t subprime[32];
662         uint8_t generator[384];
663 };
664
665 static int
666 _dsa_params_generate(struct ck_function_list *module, ck_session_handle_t session,
667                      unsigned long bits, struct dsa_params *params,
668                      struct ck_attribute *a, int *a_val)
669 {
670         struct ck_mechanism mech = { CKM_DSA_PARAMETER_GEN };
671         struct ck_attribute attr = { CKA_PRIME_BITS, &bits, sizeof(bits) };
672         ck_object_handle_t key;
673         ck_rv_t rv;
674
675         /* Generate DSA parameters from prime length. */
676
677         rv = pkcs11_generate_key(module, session, &mech, &attr, 1, &key);
678         if (rv != CKR_OK) {
679                 gnutls_assert();
680                 _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
681                 return pkcs11_rv_to_err(rv);
682         }
683
684         /* Retrieve generated parameters to be used with the new key pair. */
685
686         a[*a_val + 0].type = CKA_PRIME;
687         a[*a_val + 0].value = params->prime;
688         a[*a_val + 0].value_len = sizeof(params->prime);
689
690         a[*a_val + 1].type = CKA_SUBPRIME;
691         a[*a_val + 1].value = params->subprime;
692         a[*a_val + 1].value_len = sizeof(params->subprime);
693
694         a[*a_val + 2].type = CKA_BASE;
695         a[*a_val + 2].value = params->generator;
696         a[*a_val + 2].value_len = sizeof(params->generator);
697
698         rv = pkcs11_get_attribute_value(module, session, key, &a[*a_val], 3);
699         if (rv != CKR_OK) {
700                 gnutls_assert();
701                 _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
702                 return pkcs11_rv_to_err(rv);
703         }
704
705         *a_val += 3;
706
707         return 0;
708 }
709
710 /**
711  * gnutls_pkcs11_privkey_generate3:
712  * @url: a token URL
713  * @pk: the public key algorithm
714  * @bits: the security bits
715  * @label: a label
716  * @cid: The CKA_ID to use for the new object
717  * @fmt: the format of output params. PEM or DER
718  * @pubkey: will hold the public key (may be %NULL)
719  * @key_usage: One of GNUTLS_KEY_*
720  * @flags: zero or an OR'ed sequence of %GNUTLS_PKCS11_OBJ_FLAGs
721  *
722  * This function will generate a private key in the specified
723  * by the @url token. The private key will be generate within
724  * the token and will not be exportable. This function will
725  * store the DER-encoded public key in the SubjectPublicKeyInfo format 
726  * in @pubkey. The @pubkey should be deinitialized using gnutls_free().
727  *
728  * Note that when generating an elliptic curve key, the curve
729  * can be substituted in the place of the bits parameter using the
730  * GNUTLS_CURVE_TO_BITS() macro.
731  *
732  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
733  *   negative error value.
734  *
735  * Since: 3.4.0
736  **/
737 int
738 gnutls_pkcs11_privkey_generate3(const char *url, gnutls_pk_algorithm_t pk,
739                                 unsigned int bits, const char *label,
740                                 const gnutls_datum_t *cid,
741                                 gnutls_x509_crt_fmt_t fmt,
742                                 gnutls_datum_t * pubkey,
743                                 unsigned int key_usage,
744                                 unsigned int flags)
745 {
746         int ret;
747         const ck_bool_t tval = 1;
748         const ck_bool_t fval = 0;
749         struct pkcs11_session_info sinfo;
750         struct p11_kit_uri *info = NULL;
751         ck_rv_t rv;
752         struct ck_attribute a[22], p[22];
753         ck_object_handle_t pub, priv;
754         unsigned long _bits = bits;
755         int a_val, p_val;
756         struct ck_mechanism mech;
757         gnutls_pubkey_t pkey = NULL;
758         gnutls_pkcs11_obj_t obj = NULL;
759         gnutls_datum_t der = {NULL, 0};
760         ck_key_type_t key_type;
761         char pubEx[3] = { 1,0,1 }; // 65537 = 0x10001
762         uint8_t id[20];
763         struct dsa_params dsa_params;
764
765         PKCS11_CHECK_INIT;
766         FIX_KEY_USAGE(pk, key_usage);
767
768         memset(&sinfo, 0, sizeof(sinfo));
769
770         ret = pkcs11_url_to_info(url, &info, 0);
771         if (ret < 0) {
772                 gnutls_assert();
773                 return ret;
774         }
775
776         ret =
777             pkcs11_open_session(&sinfo, NULL, info,
778                                 SESSION_WRITE |
779                                 pkcs11_obj_flags_to_int(flags));
780         p11_kit_uri_free(info);
781
782         if (ret < 0) {
783                 gnutls_assert();
784                 goto cleanup;
785         }
786
787         /* a holds the public key template
788          * and p the private key */
789         a_val = p_val = 0;
790         mech.parameter = NULL;
791         mech.parameter_len = 0;
792         mech.mechanism = pk_to_genmech(pk, &key_type);
793
794         if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_NO_STORE_PUBKEY)) {
795                 a[a_val].type = CKA_TOKEN;
796                 a[a_val].value = (void *) &tval;
797                 a[a_val].value_len = sizeof(tval);
798                 a_val++;
799
800                 a[a_val].type = CKA_PRIVATE;
801                 a[a_val].value = (void *) &fval;
802                 a[a_val].value_len = sizeof(fval);
803                 a_val++;
804         }
805
806         a[a_val].type = CKA_ID;
807         if (cid == NULL || cid->size == 0) {
808                 ret = gnutls_rnd(GNUTLS_RND_NONCE, id, sizeof(id));
809                 if (ret < 0) {
810                         gnutls_assert();
811                         goto cleanup;
812                 }
813
814                 a[a_val].value = (void *) id;
815                 a[a_val].value_len = sizeof(id);
816         } else {
817                 a[a_val].value = (void *) cid->data;
818                 a[a_val].value_len = cid->size;
819         }
820
821         p[p_val].type = CKA_ID;
822         p[p_val].value = a[a_val].value;
823         p[p_val].value_len = a[a_val].value_len;
824         a_val++;
825         p_val++;
826
827         switch (pk) {
828         case GNUTLS_PK_RSA:
829                 p[p_val].type = CKA_DECRYPT;
830                 if (key_usage & (GNUTLS_KEY_DECIPHER_ONLY|GNUTLS_KEY_ENCIPHER_ONLY)) {
831                         p[p_val].value = (void *) &tval;
832                         p[p_val].value_len = sizeof(tval);
833                 } else {
834                         p[p_val].value = (void *) &fval;
835                         p[p_val].value_len = sizeof(fval);
836                 }
837                 p_val++;
838
839                 p[p_val].type = CKA_SIGN;
840                 if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
841                         p[p_val].value = (void *) &tval;
842                         p[p_val].value_len = sizeof(tval);
843                 } else {
844                         p[p_val].value = (void *) &fval;
845                         p[p_val].value_len = sizeof(fval);
846                 }
847                 p_val++;
848
849                 a[a_val].type = CKA_ENCRYPT;
850                 a[a_val].value = (void *) &tval;
851                 a[a_val].value_len = sizeof(tval);
852                 a_val++;
853
854                 a[a_val].type = CKA_VERIFY;
855                 a[a_val].value = (void *) &tval;
856                 a[a_val].value_len = sizeof(tval);
857                 a_val++;
858
859                 a[a_val].type = CKA_MODULUS_BITS;
860                 a[a_val].value = &_bits;
861                 a[a_val].value_len = sizeof(_bits);
862                 a_val++;
863
864                 a[a_val].type = CKA_PUBLIC_EXPONENT;
865                 a[a_val].value = pubEx;
866                 a[a_val].value_len = sizeof(pubEx);
867                 a_val++;
868
869                 break;
870         case GNUTLS_PK_DSA:
871                 p[p_val].type = CKA_SIGN;
872                 if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
873                         p[p_val].value = (void *) &tval;
874                         p[p_val].value_len = sizeof(tval);
875                 } else {
876                         p[p_val].value = (void *) &fval;
877                         p[p_val].value_len = sizeof(fval);
878                 }
879                 p_val++;
880
881                 a[a_val].type = CKA_VERIFY;
882                 a[a_val].value = (void *) &tval;
883                 a[a_val].value_len = sizeof(tval);
884                 a_val++;
885
886                 ret = _dsa_params_generate(sinfo.module, sinfo.pks, _bits,
887                                            &dsa_params, a, &a_val);
888                 if (ret < 0) {
889                         goto cleanup;
890                 }
891
892                 break;
893         case GNUTLS_PK_EC:
894                 p[p_val].type = CKA_SIGN;
895                 if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
896                         p[p_val].value = (void *) &tval;
897                         p[p_val].value_len = sizeof(tval);
898                 } else {
899                         p[p_val].value = (void *) &fval;
900                         p[p_val].value_len = sizeof(fval);
901                 }
902                 p_val++;
903
904                 a[a_val].type = CKA_VERIFY;
905                 a[a_val].value = (void *) &tval;
906                 a[a_val].value_len = sizeof(tval);
907                 a_val++;
908
909                 if (GNUTLS_BITS_ARE_CURVE(bits)) {
910                         bits = GNUTLS_BITS_TO_CURVE(bits);
911                 } else {
912                         bits = _gnutls_ecc_bits_to_curve(bits);
913                 }
914
915                 ret = _gnutls_x509_write_ecc_params(bits, &der);
916                 if (ret < 0) {
917                         gnutls_assert();
918                         goto cleanup;
919                 }
920
921                 a[a_val].type = CKA_EC_PARAMS;
922                 a[a_val].value = der.data;
923                 a[a_val].value_len = der.size;
924                 a_val++;
925                 break;
926         default:
927                 ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
928                 goto cleanup;
929         }
930
931         /*
932          * on request, add the CKA_WRAP/CKA_UNWRAP key attribute
933          */
934         if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP) {
935                 p[p_val].type = CKA_UNWRAP;
936                 p[p_val].value = (void*)&tval;
937                 p[p_val].value_len = sizeof(tval);
938                 p_val++;
939                 a[a_val].type = CKA_WRAP;
940                 a[a_val].value = (void*)&tval;
941                 a[a_val].value_len = sizeof(tval);
942                 a_val++;
943         }
944
945         /* a private key is set always as private unless
946          * requested otherwise
947          */
948         if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE) {
949                 p[p_val].type = CKA_PRIVATE;
950                 p[p_val].value = (void *) &fval;
951                 p[p_val].value_len = sizeof(fval);
952                 p_val++;
953         } else {
954                 p[p_val].type = CKA_PRIVATE;
955                 p[p_val].value = (void *) &tval;
956                 p[p_val].value_len = sizeof(tval);
957                 p_val++;
958         }
959
960         p[p_val].type = CKA_TOKEN;
961         p[p_val].value = (void *) &tval;
962         p[p_val].value_len = sizeof(tval);
963         p_val++;
964
965         if (label) {
966                 p[p_val].type = CKA_LABEL;
967                 p[p_val].value = (void *) label;
968                 p[p_val].value_len = strlen(label);
969                 p_val++;
970
971                 a[a_val].type = CKA_LABEL;
972                 a[a_val].value = (void *) label;
973                 a[a_val].value_len = strlen(label);
974                 a_val++;
975         }
976
977         if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE) {
978                 p[p_val].type = CKA_SENSITIVE;
979                 p[p_val].value = (void *) &tval;
980                 p[p_val].value_len = sizeof(tval);
981                 p_val++;
982         } else {
983                 p[p_val].type = CKA_SENSITIVE;
984                 p[p_val].value = (void *) &fval;
985                 p[p_val].value_len = sizeof(fval);
986                 p_val++;
987         }
988
989         rv = pkcs11_generate_key_pair(sinfo.module, sinfo.pks, &mech, a,
990                                       a_val, p, p_val, &pub, &priv);
991         if (rv != CKR_OK) {
992                 gnutls_assert();
993                 _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
994                 ret = pkcs11_rv_to_err(rv);
995                 goto cleanup;
996         }
997
998         /* extract the public key */
999         if (pubkey) {
1000
1001                 ret = gnutls_pubkey_init(&pkey);
1002                 if (ret < 0) {
1003                         gnutls_assert();
1004                         goto cleanup;
1005                 }
1006
1007                 ret = gnutls_pkcs11_obj_init(&obj);
1008                 if (ret < 0) {
1009                         gnutls_assert();
1010                         goto cleanup;
1011                 }
1012
1013                 obj->pk_algorithm = pk;
1014                 obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
1015                 ret =
1016                     pkcs11_read_pubkey(sinfo.module, sinfo.pks, pub,
1017                                        key_type, obj);
1018                 if (ret < 0) {
1019                         gnutls_assert();
1020                         goto cleanup;
1021                 }
1022
1023                 ret = gnutls_pubkey_import_pkcs11(pkey, obj, 0);
1024                 if (ret < 0) {
1025                         gnutls_assert();
1026                         goto cleanup;
1027                 }
1028
1029                 ret = gnutls_pubkey_export2(pkey, fmt, pubkey);
1030                 if (ret < 0) {
1031                         gnutls_assert();
1032                         goto cleanup;
1033                 }
1034         }
1035
1036       cleanup:
1037         if (obj != NULL)
1038                 gnutls_pkcs11_obj_deinit(obj);
1039         if (pkey != NULL)
1040                 gnutls_pubkey_deinit(pkey);
1041
1042         if (sinfo.pks != 0)
1043                 pkcs11_close_session(&sinfo);
1044         gnutls_free(der.data);
1045
1046         return ret;
1047 }
1048
1049 /* loads a the corresponding to the private key public key either from 
1050  * a public key object or from a certificate.
1051  */
1052 static int load_pubkey_obj(gnutls_pkcs11_privkey_t pkey, gnutls_pubkey_t pub)
1053 {
1054         int ret, iret;
1055         gnutls_x509_crt_t crt;
1056
1057         ret = gnutls_pubkey_import_url(pub, pkey->url, pkey->flags);
1058         if (ret >= 0) {
1059                 return ret;
1060         }
1061         iret = ret;
1062
1063         /* else try certificate */
1064         ret = gnutls_x509_crt_init(&crt);
1065         if (ret < 0) {
1066                 gnutls_assert();
1067                 return ret;
1068         }
1069
1070         gnutls_x509_crt_set_pin_function(crt, pkey->pin.cb, pkey->pin.data);
1071
1072         ret = gnutls_x509_crt_import_url(crt, pkey->url, pkey->flags);
1073         if (ret < 0) {
1074                 ret = iret;
1075                 goto cleanup;
1076         }
1077
1078         ret = gnutls_pubkey_import_x509(pub, crt, 0);
1079
1080  cleanup:
1081         gnutls_x509_crt_deinit(crt);
1082         return ret;
1083 }
1084
1085 int
1086 _pkcs11_privkey_get_pubkey (gnutls_pkcs11_privkey_t pkey, gnutls_pubkey_t *pub, unsigned flags)
1087 {
1088         gnutls_pubkey_t pubkey = NULL;
1089         gnutls_pkcs11_obj_t obj = NULL;
1090         ck_key_type_t key_type;
1091         int ret;
1092
1093         PKCS11_CHECK_INIT_PRIVKEY(pkey);
1094
1095         if (!pkey) {
1096                 gnutls_assert();
1097                 return GNUTLS_E_INVALID_REQUEST;
1098         }
1099
1100         ret = gnutls_pubkey_init(&pubkey);
1101         if (ret < 0) {
1102                 gnutls_assert();
1103                 goto cleanup;
1104         }
1105
1106         ret = gnutls_pkcs11_obj_init(&obj);
1107         if (ret < 0) {
1108                 gnutls_assert();
1109                 goto cleanup;
1110         }
1111
1112         obj->pk_algorithm = gnutls_pkcs11_privkey_get_pk_algorithm(pkey, 0);
1113         obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
1114         pk_to_genmech(obj->pk_algorithm, &key_type);
1115
1116         gnutls_pubkey_set_pin_function(pubkey, pkey->pin.cb, pkey->pin.data);
1117
1118         /* we can only read the public key from RSA keys */
1119         if (key_type != CKK_RSA) {
1120                 /* try opening the public key object if it exists */
1121                 ret = load_pubkey_obj(pkey, pubkey);
1122                 if (ret < 0) {
1123                         gnutls_assert();
1124                         goto cleanup;
1125                 }
1126         } else {
1127                 ret = pkcs11_read_pubkey(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, key_type, obj);
1128                 if (ret < 0) {
1129                         gnutls_assert();
1130                         goto cleanup;
1131                 }
1132
1133                 ret = gnutls_pubkey_import_pkcs11(pubkey, obj, 0);
1134                 if (ret < 0) {
1135                         gnutls_assert();
1136                         goto cleanup;
1137                 }
1138         }
1139
1140         *pub = pubkey;
1141
1142         pubkey = NULL;
1143         ret = 0;
1144
1145  cleanup:
1146         if (obj != NULL)
1147                 gnutls_pkcs11_obj_deinit(obj);
1148         if (pubkey != NULL)
1149                 gnutls_pubkey_deinit(pubkey);
1150
1151         return ret;
1152 }
1153
1154 /**
1155  * gnutls_pkcs11_privkey_export_pubkey
1156  * @pkey: The private key
1157  * @fmt: the format of output params. PEM or DER.
1158  * @data: will hold the public key
1159  * @flags: should be zero
1160  *
1161  * This function will extract the public key (modulus and public
1162  * exponent) from the private key specified by the @url private key.
1163  * This public key will be stored in @pubkey in the format specified
1164  * by @fmt. @pubkey should be deinitialized using gnutls_free().
1165  *
1166  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1167  *   negative error value.
1168  *
1169  * Since: 3.3.7
1170  **/
1171 int
1172 gnutls_pkcs11_privkey_export_pubkey(gnutls_pkcs11_privkey_t pkey,
1173                                      gnutls_x509_crt_fmt_t fmt,
1174                                      gnutls_datum_t * data,
1175                                      unsigned int flags)
1176 {
1177         int ret;
1178         gnutls_pubkey_t pubkey = NULL;
1179
1180         ret = _pkcs11_privkey_get_pubkey(pkey, &pubkey, flags);
1181         if (ret < 0)
1182                 return gnutls_assert_val(ret);
1183
1184         ret = gnutls_pubkey_export2(pubkey, fmt, data);
1185         if (ret < 0) {
1186                 gnutls_assert();
1187                 goto cleanup;
1188         }
1189
1190         ret = 0;
1191
1192       cleanup:
1193         if (pubkey != NULL)
1194                 gnutls_pubkey_deinit(pubkey);
1195
1196         return ret;
1197 }
1198
1199 /**
1200  * gnutls_pkcs11_privkey_set_pin_function:
1201  * @key: The private key
1202  * @fn: the callback
1203  * @userdata: data associated with the callback
1204  *
1205  * This function will set a callback function to be used when
1206  * required to access the object. This function overrides the global
1207  * set using gnutls_pkcs11_set_pin_function().
1208  *
1209  * Since: 3.1.0
1210  *
1211  **/
1212 void
1213 gnutls_pkcs11_privkey_set_pin_function(gnutls_pkcs11_privkey_t key,
1214                                        gnutls_pin_callback_t fn,
1215                                        void *userdata)
1216 {
1217         key->pin.cb = fn;
1218         key->pin.data = userdata;
1219 }