Imported Upstream version 3.0.21
[platform/upstream/gnutls.git] / lib / pkcs11_write.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  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 3 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library 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
29 static const ck_bool_t tval = 1;
30 static const ck_bool_t fval = 0;
31
32 /**
33  * gnutls_pkcs11_copy_x509_crt:
34  * @token_url: A PKCS #11 URL specifying a token
35  * @crt: A certificate
36  * @label: A name to be used for the stored data
37  * @flags: One of GNUTLS_PKCS11_OBJ_FLAG_*
38  *
39  * This function will copy a certificate into a PKCS #11 token specified by
40  * a URL. The certificate can be marked as trusted or not.
41  *
42  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
43  *   negative error value.
44  *
45  * Since: 2.12.0
46  **/
47 int
48 gnutls_pkcs11_copy_x509_crt (const char *token_url,
49                              gnutls_x509_crt_t crt, const char *label,
50                              unsigned int flags)
51 {
52   int ret;
53   struct ck_function_list *module;
54   ck_session_handle_t pks;
55   struct p11_kit_uri *info = NULL;
56   ck_rv_t rv;
57   size_t der_size, id_size;
58   uint8_t *der = NULL;
59   uint8_t id[20];
60   struct ck_attribute a[16];
61   ck_object_class_t class = CKO_CERTIFICATE;
62   ck_certificate_type_t type = CKC_X_509;
63   ck_object_handle_t obj;
64   int a_val;
65   gnutls_datum_t subject = { NULL, 0 };
66
67   ret = pkcs11_url_to_info (token_url, &info);
68   if (ret < 0)
69     {
70       gnutls_assert ();
71       return ret;
72     }
73
74   ret =
75     pkcs11_open_session (&module, &pks, info,
76                          SESSION_WRITE | pkcs11_obj_flags_to_int (flags));
77   p11_kit_uri_free (info);
78
79   if (ret < 0)
80     {
81       gnutls_assert ();
82       return ret;
83     }
84
85   ret = gnutls_x509_crt_export (crt, GNUTLS_X509_FMT_DER, NULL, &der_size);
86   if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
87     {
88       gnutls_assert ();
89       goto cleanup;
90     }
91
92   der = gnutls_malloc (der_size);
93   if (der == NULL)
94     {
95       gnutls_assert ();
96       ret = GNUTLS_E_MEMORY_ERROR;
97       goto cleanup;
98     }
99
100   ret = gnutls_x509_crt_export (crt, GNUTLS_X509_FMT_DER, der, &der_size);
101   if (ret < 0)
102     {
103       gnutls_assert ();
104       goto cleanup;
105     }
106
107   id_size = sizeof (id);
108   ret = gnutls_x509_crt_get_key_id (crt, 0, id, &id_size);
109   if (ret < 0)
110     {
111       gnutls_assert ();
112       goto cleanup;
113     }
114   
115   ret = gnutls_x509_crt_get_raw_dn (crt, &subject);
116   if (ret < 0)
117     {
118       gnutls_assert ();
119       goto cleanup;
120     }
121
122   /* FIXME: copy key usage flags */
123
124   a[0].type = CKA_CLASS;
125   a[0].value = &class;
126   a[0].value_len = sizeof (class);
127   a[1].type = CKA_ID;
128   a[1].value = id;
129   a[1].value_len = id_size;
130   a[2].type = CKA_VALUE;
131   a[2].value = der;
132   a[2].value_len = der_size;
133   a[3].type = CKA_TOKEN;
134   a[3].value = (void*)&tval;
135   a[3].value_len = sizeof (tval);
136   a[4].type = CKA_CERTIFICATE_TYPE;
137   a[4].value = &type;
138   a[4].value_len = sizeof (type);
139
140   a_val = 5;
141
142   a[a_val].type = CKA_SUBJECT;
143   a[a_val].value = subject.data;
144   a[a_val].value_len = subject.size;
145   a_val++;
146
147   if (label)
148     {
149       a[a_val].type = CKA_LABEL;
150       a[a_val].value = (void *) label;
151       a[a_val].value_len = strlen (label);
152       a_val++;
153     }
154
155   if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED)
156     {
157       a[a_val].type = CKA_TRUSTED;
158       a[a_val].value = (void*)&tval;
159       a[a_val].value_len = sizeof (tval);
160       a_val++;
161
162       a[a_val].type = CKA_PRIVATE;
163       a[a_val].value = (void*)&fval;
164       a[a_val].value_len = sizeof(fval);
165       a_val++;
166     }
167   else
168     {
169       if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE)
170         {
171           a[a_val].type = CKA_PRIVATE;
172           a[a_val].value = (void*)&tval;
173           a[a_val].value_len = sizeof(tval);
174           a_val++;
175         }
176       else if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE)
177         {
178           a[a_val].type = CKA_PRIVATE;
179           a[a_val].value = (void*)&fval;
180           a[a_val].value_len = sizeof(fval);
181           a_val++;
182         }
183     }
184
185   rv = pkcs11_create_object (module, pks, a, a_val, &obj);
186   if (rv != CKR_OK)
187     {
188       gnutls_assert ();
189       _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv));
190       ret = pkcs11_rv_to_err (rv);
191       goto cleanup;
192     }
193
194   /* generated! 
195    */
196
197   ret = 0;
198
199 cleanup:
200   gnutls_free (der);
201   pkcs11_close_session (module, pks);
202   _gnutls_free_datum(&subject);
203   return ret;
204
205 }
206
207 /**
208  * gnutls_pkcs11_copy_x509_privkey:
209  * @token_url: A PKCS #11 URL specifying a token
210  * @key: A private key
211  * @label: A name to be used for the stored data
212  * @key_usage: One of GNUTLS_KEY_*
213  * @flags: One of GNUTLS_PKCS11_OBJ_* flags
214  *
215  * This function will copy a private key into a PKCS #11 token specified by
216  * a URL. It is highly recommended flags to contain %GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE
217  * unless there is a strong reason not to.
218  *
219  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
220  *   negative error value.
221  *
222  * Since: 2.12.0
223  **/
224 int
225 gnutls_pkcs11_copy_x509_privkey (const char *token_url,
226                                  gnutls_x509_privkey_t key,
227                                  const char *label,
228                                  unsigned int key_usage, unsigned int flags)
229 {
230   int ret;
231   struct ck_function_list *module;
232   ck_session_handle_t pks = 0;
233   struct p11_kit_uri *info = NULL;
234   ck_rv_t rv;
235   size_t id_size;
236   uint8_t id[20];
237   struct ck_attribute a[16];
238   ck_object_class_t class = CKO_PRIVATE_KEY;
239   ck_object_handle_t obj;
240   ck_key_type_t type;
241   int a_val;
242   gnutls_pk_algorithm_t pk;
243   gnutls_datum_t p, q, g, y, x;
244   gnutls_datum_t m, e, d, u, exp1, exp2;
245
246   memset(&p, 0, sizeof(p));
247   memset(&q, 0, sizeof(q));
248   memset(&g, 0, sizeof(g));
249   memset(&y, 0, sizeof(y));
250   memset(&x, 0, sizeof(x));
251   memset(&m, 0, sizeof(m));
252   memset(&e, 0, sizeof(e));
253   memset(&d, 0, sizeof(d));
254   memset(&u, 0, sizeof(u));
255   memset(&exp1, 0, sizeof(exp1));
256   memset(&exp2, 0, sizeof(exp2));
257
258   ret = pkcs11_url_to_info (token_url, &info);
259   if (ret < 0)
260     {
261       gnutls_assert ();
262       return ret;
263     }
264
265   id_size = sizeof (id);
266   ret = gnutls_x509_privkey_get_key_id (key, 0, id, &id_size);
267   if (ret < 0)
268     {
269       p11_kit_uri_free (info);
270       gnutls_assert ();
271       return ret;
272     }
273
274   ret =
275     pkcs11_open_session (&module, &pks, info,
276                          SESSION_WRITE | pkcs11_obj_flags_to_int (flags));
277   p11_kit_uri_free (info);
278
279   if (ret < 0)
280     {
281       gnutls_assert ();
282       return ret;
283     }
284
285   /* FIXME: copy key usage flags */
286   a_val = 0;
287   a[a_val].type = CKA_CLASS;
288   a[a_val].value = &class;
289   a[a_val].value_len = sizeof (class);
290   a_val++;
291
292   a[a_val].type = CKA_ID;
293   a[a_val].value = id;
294   a[a_val].value_len = id_size;
295   a_val++;
296
297   a[a_val].type = CKA_KEY_TYPE;
298   a[a_val].value = &type;
299   a[a_val].value_len = sizeof (type);
300   a_val++;
301
302   a[a_val].type = CKA_TOKEN;
303   a[a_val].value = (void*)&tval;
304   a[a_val].value_len = sizeof (tval);
305   a_val++;
306
307   /* a private key is set always as private unless
308    * requested otherwise
309    */
310   if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE)
311     {
312       a[a_val].type = CKA_PRIVATE;
313       a[a_val].value = (void*)&fval;
314       a[a_val].value_len = sizeof(fval);
315       a_val++;
316     }
317   else
318     {
319       a[a_val].type = CKA_PRIVATE;
320       a[a_val].value = (void*)&tval;
321       a[a_val].value_len = sizeof (tval);
322       a_val++;
323     }
324
325   if (label)
326     {
327       a[a_val].type = CKA_LABEL;
328       a[a_val].value = (void *) label;
329       a[a_val].value_len = strlen (label);
330       a_val++;
331     }
332
333   if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE)
334     {
335       a[a_val].type = CKA_SENSITIVE;
336       a[a_val].value = (void*)&tval;
337       a[a_val].value_len = sizeof (tval);
338       a_val++;
339     }
340   else
341     {
342       a[a_val].type = CKA_SENSITIVE;
343       a[a_val].value = (void*)&fval;
344       a[a_val].value_len = sizeof (fval);
345       a_val++;
346     }
347
348   pk = gnutls_x509_privkey_get_pk_algorithm (key);
349   switch (pk)
350     {
351     case GNUTLS_PK_RSA:
352       {
353
354         ret =
355           gnutls_x509_privkey_export_rsa_raw2 (key, &m,
356                                                &e, &d, &p,
357                                                &q, &u, &exp1, &exp2);
358         if (ret < 0)
359           {
360             gnutls_assert ();
361             goto cleanup;
362           }
363
364         type = CKK_RSA;
365
366         a[a_val].type = CKA_MODULUS;
367         a[a_val].value = m.data;
368         a[a_val].value_len = m.size;
369         a_val++;
370
371         a[a_val].type = CKA_PUBLIC_EXPONENT;
372         a[a_val].value = e.data;
373         a[a_val].value_len = e.size;
374         a_val++;
375
376         a[a_val].type = CKA_PRIVATE_EXPONENT;
377         a[a_val].value = d.data;
378         a[a_val].value_len = d.size;
379         a_val++;
380
381         a[a_val].type = CKA_PRIME_1;
382         a[a_val].value = p.data;
383         a[a_val].value_len = p.size;
384         a_val++;
385
386         a[a_val].type = CKA_PRIME_2;
387         a[a_val].value = q.data;
388         a[a_val].value_len = q.size;
389         a_val++;
390
391         a[a_val].type = CKA_COEFFICIENT;
392         a[a_val].value = u.data;
393         a[a_val].value_len = u.size;
394         a_val++;
395
396         a[a_val].type = CKA_EXPONENT_1;
397         a[a_val].value = exp1.data;
398         a[a_val].value_len = exp1.size;
399         a_val++;
400
401         a[a_val].type = CKA_EXPONENT_2;
402         a[a_val].value = exp2.data;
403         a[a_val].value_len = exp2.size;
404         a_val++;
405
406         break;
407       }
408     case GNUTLS_PK_DSA:
409       {
410         ret = gnutls_x509_privkey_export_dsa_raw (key, &p, &q, &g, &y, &x);
411         if (ret < 0)
412           {
413             gnutls_assert ();
414             goto cleanup;
415           }
416
417         type = CKK_DSA;
418
419         a[a_val].type = CKA_PRIME;
420         a[a_val].value = p.data;
421         a[a_val].value_len = p.size;
422         a_val++;
423
424         a[a_val].type = CKA_SUBPRIME;
425         a[a_val].value = q.data;
426         a[a_val].value_len = q.size;
427         a_val++;
428
429         a[a_val].type = CKA_BASE;
430         a[a_val].value = g.data;
431         a[a_val].value_len = g.size;
432         a_val++;
433
434         a[a_val].type = CKA_VALUE;
435         a[a_val].value = x.data;
436         a[a_val].value_len = x.size;
437         a_val++;
438
439         break;
440       }
441     case GNUTLS_PK_EC:
442       {
443         ret = _gnutls_x509_write_ecc_params(&key->params, &p);
444         if (ret < 0)
445           {
446             gnutls_assert ();
447             goto cleanup;
448           }
449
450         ret = _gnutls_mpi_dprint_lz(&key->params.params[ECC_K], &x);
451         if (ret < 0)
452           {
453             gnutls_assert ();
454             goto cleanup;
455           }
456
457         type = CKK_ECDSA;
458
459         a[a_val].type = CKA_EC_PARAMS;
460         a[a_val].value = p.data;
461         a[a_val].value_len = p.size;
462         a_val++;
463
464         a[a_val].type = CKA_VALUE;
465         a[a_val].value = x.data;
466         a[a_val].value_len = x.size;
467         a_val++;
468
469         break;
470       }
471     default:
472       gnutls_assert ();
473       ret = GNUTLS_E_INVALID_REQUEST;
474       goto cleanup;
475     }
476
477   rv = pkcs11_create_object (module, pks, a, a_val, &obj);
478   if (rv != CKR_OK)
479     {
480       gnutls_assert ();
481       _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv));
482       ret = pkcs11_rv_to_err (rv);
483       goto cleanup;
484     }
485
486   ret = 0;
487
488 cleanup:
489   switch (pk)
490     {
491     case GNUTLS_PK_RSA:
492       {
493         gnutls_free (m.data);
494         gnutls_free (e.data);
495         gnutls_free (d.data);
496         gnutls_free (p.data);
497         gnutls_free (q.data);
498         gnutls_free (u.data);
499         gnutls_free (exp1.data);
500         gnutls_free (exp2.data);
501         break;
502       }
503     case GNUTLS_PK_DSA:
504       {
505         gnutls_free (p.data);
506         gnutls_free (q.data);
507         gnutls_free (g.data);
508         gnutls_free (y.data);
509         gnutls_free (x.data);
510         break;
511       }
512     case GNUTLS_PK_EC:
513       {
514         gnutls_free (p.data);
515         gnutls_free (x.data);
516         break;
517       }
518     default:
519       gnutls_assert ();
520       ret = GNUTLS_E_INVALID_REQUEST;
521       break;
522     }
523
524   if (pks != 0)
525     pkcs11_close_session (module, pks);
526
527   return ret;
528
529 }
530
531 struct delete_data_st
532 {
533   struct p11_kit_uri *info;
534   unsigned int deleted;         /* how many */
535 };
536
537 static int
538 delete_obj_url (struct ck_function_list *module,
539                 ck_session_handle_t pks,
540                 struct token_info *info,
541                 struct ck_info *lib_info, void *input)
542 {
543   struct delete_data_st *find_data = input;
544   struct ck_attribute a[4];
545   struct ck_attribute *attr;
546   ck_object_class_t class;
547   ck_certificate_type_t type = (ck_certificate_type_t)-1;
548   ck_rv_t rv;
549   ck_object_handle_t obj;
550   unsigned long count, a_vals;
551   int found = 0, ret;
552
553
554   if (info == NULL)
555     {                           /* we don't support multiple calls */
556       gnutls_assert ();
557       return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
558     }
559
560   /* do not bother reading the token if basic fields do not match
561    */
562   if (!p11_kit_uri_match_module_info (find_data->info, lib_info) ||
563       !p11_kit_uri_match_token_info (find_data->info, &info->tinfo))
564     {
565       gnutls_assert ();
566       return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
567     }
568
569   /* Find objects with given class and type */
570   class = CKO_CERTIFICATE;      /* default  */
571   a_vals = 0;
572
573   attr = p11_kit_uri_get_attribute (find_data->info, CKA_CLASS);
574   if (attr != NULL)
575     {
576       if(attr->value && attr->value_len == sizeof (ck_object_class_t))
577         class = *((ck_object_class_t*)attr->value);
578       if (class == CKO_CERTIFICATE)
579         type = CKC_X_509;
580     }
581
582   a[a_vals].type = CKA_CLASS;
583   a[a_vals].value = &class;
584   a[a_vals].value_len = sizeof (class);
585   a_vals++;
586
587   attr = p11_kit_uri_get_attribute (find_data->info, CKA_ID);
588   if (attr != NULL)
589     {
590       memcpy (a + a_vals, attr, sizeof (struct ck_attribute));
591       a_vals++;
592     }
593
594   if (type != (ck_certificate_type_t)-1)
595     {
596       a[a_vals].type = CKA_CERTIFICATE_TYPE;
597       a[a_vals].value = &type;
598       a[a_vals].value_len = sizeof type;
599       a_vals++;
600     }
601
602   attr = p11_kit_uri_get_attribute (find_data->info, CKA_LABEL);
603   if (attr != NULL)
604     {
605       memcpy (a + a_vals, attr, sizeof (struct ck_attribute));
606       a_vals++;
607     }
608
609   rv = pkcs11_find_objects_init (module, pks, a, a_vals);
610   if (rv != CKR_OK)
611     {
612       gnutls_assert ();
613       _gnutls_debug_log ("pk11: FindObjectsInit failed.\n");
614       ret = pkcs11_rv_to_err (rv);
615       goto cleanup;
616     }
617
618   while (pkcs11_find_objects (module, pks, &obj, 1, &count) == CKR_OK && count == 1)
619     {
620       rv = pkcs11_destroy_object (module, pks, obj);
621       if (rv != CKR_OK)
622         {
623           _gnutls_debug_log
624             ("pkcs11: Cannot destroy object: %s\n", pkcs11_strerror (rv));
625         }
626       else
627         {
628           find_data->deleted++;
629         }
630
631       found = 1;
632     }
633
634   if (found == 0)
635     {
636       gnutls_assert ();
637       ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
638     }
639   else
640     {
641       ret = 0;
642     }
643
644 cleanup:
645   pkcs11_find_objects_final (module, pks);
646
647   return ret;
648 }
649
650
651 /**
652  * gnutls_pkcs11_delete_url:
653  * @object_url: The URL of the object to delete.
654  * @flags: One of GNUTLS_PKCS11_OBJ_* flags
655  * 
656  * This function will delete objects matching the given URL.
657  * Note that not all tokens support the delete operation.
658  *
659  * Returns: On success, the number of objects deleted is returned, otherwise a
660  *   negative error value.
661  *
662  * Since: 2.12.0
663  **/
664 int
665 gnutls_pkcs11_delete_url (const char *object_url, unsigned int flags)
666 {
667   int ret;
668   struct delete_data_st find_data;
669
670   memset (&find_data, 0, sizeof (find_data));
671
672   ret = pkcs11_url_to_info (object_url, &find_data.info);
673   if (ret < 0)
674     {
675       gnutls_assert ();
676       return ret;
677     }
678
679   ret =
680     _pkcs11_traverse_tokens (delete_obj_url, &find_data, find_data.info,
681                              SESSION_WRITE | pkcs11_obj_flags_to_int (flags));
682   p11_kit_uri_free (find_data.info);
683
684   if (ret < 0)
685     {
686       gnutls_assert ();
687       return ret;
688     }
689
690   return find_data.deleted;
691
692 }
693
694 /**
695  * gnutls_pkcs11_token_init:
696  * @token_url: A PKCS #11 URL specifying a token
697  * @so_pin: Security Officer's PIN
698  * @label: A name to be used for the token
699  *
700  * This function will initialize (format) a token. If the token is
701  * at a factory defaults state the security officer's PIN given will be
702  * set to be the default. Otherwise it should match the officer's PIN.
703  *
704  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
705  *   negative error value.
706  **/
707 int
708 gnutls_pkcs11_token_init (const char *token_url,
709                           const char *so_pin, const char *label)
710 {
711   int ret;
712   struct p11_kit_uri *info = NULL;
713   ck_rv_t rv;
714   struct ck_function_list *module;
715   ck_slot_id_t slot;
716   char flabel[32];
717
718   ret = pkcs11_url_to_info (token_url, &info);
719   if (ret < 0)
720     {
721       gnutls_assert ();
722       return ret;
723     }
724
725   ret = pkcs11_find_slot (&module, &slot, info, NULL);
726   p11_kit_uri_free (info);
727
728   if (ret < 0)
729     {
730       gnutls_assert ();
731       return ret;
732     }
733
734   /* so it seems memset has other uses than zeroing! */
735   memset (flabel, ' ', sizeof (flabel));
736   if (label != NULL)
737     memcpy (flabel, label, strlen (label));
738
739   rv =
740     pkcs11_init_token (module, slot, (uint8_t*)so_pin, strlen (so_pin),
741                        (uint8_t*)flabel);
742   if (rv != CKR_OK)
743     {
744       gnutls_assert ();
745       _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv));
746       return pkcs11_rv_to_err (rv);
747     }
748
749   return 0;
750
751 }
752
753 /**
754  * gnutls_pkcs11_token_set_pin:
755  * @token_url: A PKCS #11 URL specifying a token
756  * @oldpin: old user's PIN
757  * @newpin: new user's PIN
758  * @flags: one of #gnutls_pkcs11_pin_flag_t.
759  *
760  * This function will modify or set a user's PIN for the given token. 
761  * If it is called to set a user pin for first time the oldpin must
762  * be NULL.
763  *
764  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
765  *   negative error value.
766  **/
767 int
768 gnutls_pkcs11_token_set_pin (const char *token_url,
769                              const char *oldpin,
770                              const char *newpin, unsigned int flags)
771 {
772   int ret;
773   struct ck_function_list *module;
774   ck_session_handle_t pks;
775   struct p11_kit_uri *info = NULL;
776   ck_rv_t rv;
777   unsigned int ses_flags;
778
779   ret = pkcs11_url_to_info (token_url, &info);
780   if (ret < 0)
781     {
782       gnutls_assert ();
783       return ret;
784     }
785
786   if (((flags & GNUTLS_PKCS11_PIN_USER) && oldpin == NULL) ||
787       (flags & GNUTLS_PKCS11_PIN_SO))
788     ses_flags = SESSION_WRITE | SESSION_LOGIN | SESSION_SO;
789   else
790     ses_flags = SESSION_WRITE | SESSION_LOGIN;
791
792   ret = pkcs11_open_session (&module, &pks, info, ses_flags);
793   p11_kit_uri_free (info);
794
795   if (ret < 0)
796     {
797       gnutls_assert ();
798       return ret;
799     }
800
801   if (oldpin == NULL)
802     {
803       rv = pkcs11_init_pin (module, pks, (uint8_t *) newpin, strlen (newpin));
804       if (rv != CKR_OK)
805         {
806           gnutls_assert ();
807           _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv));
808           ret = pkcs11_rv_to_err (rv);
809           goto finish;
810         }
811     }
812   else
813     {
814       rv = pkcs11_set_pin (module, pks,
815                            oldpin, strlen (oldpin),
816                            newpin, strlen (newpin));
817       if (rv != CKR_OK)
818         {
819           gnutls_assert ();
820           _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv));
821           ret = pkcs11_rv_to_err (rv);
822           goto finish;
823         }
824     }
825
826   ret = 0;
827
828 finish:
829   pkcs11_close_session (module, pks);
830   return ret;
831
832 }
833