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