Fix CVE-2017-6891 in minitasn1 code
[platform/upstream/gnutls.git] / src / pkcs11.c
1 /*
2  * Copyright (C) 2010-2012 Free Software Foundation, Inc.
3  * Author: Nikos Mavrogiannopoulos
4  *
5  * This file is part of GnuTLS.
6  *
7  * GnuTLS is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuTLS 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
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20 #include <config.h>
21
22 #include <getpass.h>
23
24 #include <gnutls/gnutls.h>
25 #include <gnutls/pkcs11.h>
26 #include <gnutls/abstract.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include "p11tool.h"
30 #include "certtool-cfg.h"
31 #include "certtool-common.h"
32 #include <unistd.h>
33 #include <string.h>
34 #include <stdint.h>
35 #include <common.h>
36
37 #ifdef _WIN32
38 # define sleep(x) Sleep(x*1000)
39 #endif
40
41 static
42 char *get_single_token_url(common_info_st * info);
43
44 #define FIX(url, out, det, info) \
45         if (url == NULL) { \
46                 url = get_single_token_url(info); \
47                 if (url == NULL) { \
48                         fprintf(stderr, "warning: no token URL was provided for this operation; the available tokens are:\n"); \
49                         pkcs11_token_list(out, det, info, 1); \
50                         exit(1); \
51                 } \
52         }
53
54 #define CHECK_LOGIN_FLAG(flag) \
55         if (flag == 0) \
56                 fprintf(stderr, \
57                         "warning: --login was not specified and it may be required for this operation.\n")
58
59 void
60 pkcs11_delete(FILE * outfile, const char *url,
61               unsigned int login_flags, common_info_st * info)
62 {
63         int ret;
64         unsigned int obj_flags = 0;
65
66         if (login_flags) obj_flags = login_flags;
67
68         if (info->batch == 0) {
69                 pkcs11_list(outfile, url, PKCS11_TYPE_ALL, login_flags,
70                             GNUTLS_PKCS11_URL_LIB, info);
71                 ret =
72                     read_yesno
73                     ("Are you sure you want to delete those objects? (y/N): ",
74                      0);
75                 if (ret == 0) {
76                         exit(1);
77                 }
78         }
79
80         ret = gnutls_pkcs11_delete_url(url, obj_flags);
81         if (ret < 0) {
82                 fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__,
83                         gnutls_strerror(ret));
84                 exit(1);
85         }
86
87         fprintf(outfile, "\n%d objects deleted\n", ret);
88
89         return;
90 }
91
92 /* lists certificates from a token
93  */
94 void
95 pkcs11_list(FILE * outfile, const char *url, int type, unsigned int flags,
96             unsigned int detailed, common_info_st * info)
97 {
98         gnutls_pkcs11_obj_t *crt_list;
99         unsigned int crt_list_size = 0, i, j;
100         int ret, otype;
101         char *output, *str;
102         int attrs, print_exts = 0;
103         gnutls_x509_ext_st *exts;
104         unsigned exts_size;
105         unsigned int obj_flags = flags;
106
107         pkcs11_common(info);
108
109         FIX(url, outfile, detailed, info);
110
111         gnutls_pkcs11_token_get_flags(url, &flags);
112         if (flags & GNUTLS_PKCS11_TOKEN_TRUSTED)
113                 print_exts = 1;
114
115         if (type == PKCS11_TYPE_TRUSTED) {
116                 attrs = GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED;
117         } else if (type == PKCS11_TYPE_PK) {
118                 attrs = GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY;
119         } else if (type == PKCS11_TYPE_CRT_ALL) {
120                 attrs = GNUTLS_PKCS11_OBJ_ATTR_CRT_ALL;
121                 if (print_exts != 0) print_exts++;
122         } else if (type == PKCS11_TYPE_PRIVKEY) {
123                 attrs = GNUTLS_PKCS11_OBJ_ATTR_PRIVKEY;
124         } else if (type == PKCS11_TYPE_INFO) {
125                 attrs = GNUTLS_PKCS11_OBJ_ATTR_MATCH;
126         } else {
127                 attrs = GNUTLS_PKCS11_OBJ_ATTR_ALL;
128         }
129
130         /* give some initial value to avoid asking for the pkcs11 pin twice.
131          */
132         ret =
133             gnutls_pkcs11_obj_list_import_url2(&crt_list, &crt_list_size,
134                                                url, attrs, obj_flags);
135         if (ret < 0) {
136                 fprintf(stderr, "Error in crt_list_import (1): %s\n",
137                         gnutls_strerror(ret));
138                 exit(1);
139         }
140
141         if (crt_list_size == 0) {
142                 fprintf(stderr, "No matching objects found\n");
143                 exit(0);
144         }
145
146         for (i = 0; i < crt_list_size; i++) {
147                 char buf[128];
148                 size_t size;
149                 unsigned int oflags;
150
151                 ret =
152                     gnutls_pkcs11_obj_export_url(crt_list[i], detailed,
153                                                  &output);
154                 if (ret < 0) {
155                         fprintf(stderr, "Error in %s:%d: %s\n", __func__,
156                                 __LINE__, gnutls_strerror(ret));
157                         exit(1);
158                 }
159
160                 fprintf(outfile, "Object %d:\n\tURL: %s\n", i, output);
161
162                 otype = gnutls_pkcs11_obj_get_type(crt_list[i]);
163                 fprintf(outfile, "\tType: %s\n",
164                         gnutls_pkcs11_type_get_name(otype));
165
166                 size = sizeof(buf);
167                 ret =
168                     gnutls_pkcs11_obj_get_info(crt_list[i],
169                                                GNUTLS_PKCS11_OBJ_LABEL,
170                                                buf, &size);
171                 if (ret < 0) {
172                         fprintf(stderr, "Error in %s:%d: %s\n", __func__,
173                                 __LINE__, gnutls_strerror(ret));
174                         exit(1);
175                 }
176                 fprintf(outfile, "\tLabel: %s\n", buf);
177
178                 oflags = 0;
179                 ret = gnutls_pkcs11_obj_get_flags(crt_list[i], &oflags);
180                 if (ret < 0) {
181                         fprintf(stderr, "Error in %s:%d: %s\n", __func__,
182                                 __LINE__, gnutls_strerror(ret));
183                         exit(1);
184                 }
185                 str = gnutls_pkcs11_obj_flags_get_str(oflags);
186                 if (str != NULL) {
187                         fprintf(outfile, "\tFlags: %s\n", str);
188                         gnutls_free(str);
189                 }
190
191                 size = sizeof(buf);
192                 ret =
193                     gnutls_pkcs11_obj_get_info(crt_list[i],
194                                                GNUTLS_PKCS11_OBJ_ID_HEX,
195                                                buf, &size);
196                 if (ret < 0) {
197                         fprintf(stderr, "Error in %s:%d: %s\n", __func__,
198                                 __LINE__, gnutls_strerror(ret));
199                         exit(1);
200                 }
201                 fprintf(outfile, "\tID: %s\n", buf);
202
203                 if (otype == GNUTLS_PKCS11_OBJ_X509_CRT && print_exts > 0) {
204                         ret = gnutls_pkcs11_obj_get_exts(crt_list[i], &exts, &exts_size, 0);
205                         if (ret >= 0 && exts_size > 0) {
206                                 gnutls_datum_t txt;
207
208                                 if (print_exts > 1) {
209                                         fprintf(outfile, "\tAttached extensions:\n");
210                                         ret = gnutls_x509_ext_print(exts, exts_size, 0, &txt);
211                                         if (ret >= 0) {
212                                                 fprintf(outfile, "%s", (char*)txt.data);
213                                                 gnutls_free(txt.data);
214                                         }
215                                 } else {
216                                         fprintf(outfile, "\tAttached extensions:");
217                                         for (j=0;j<exts_size;j++) {
218                                                 fprintf(outfile, "%s%s", exts[j].oid, (j!=exts_size-1)?",":" ");
219                                         }
220                                 }
221                                 for (j=0;j<exts_size;j++) {
222                                         gnutls_x509_ext_deinit(&exts[j]);
223                                 }
224                                 gnutls_free(exts);
225                                 fprintf(outfile, "\n");
226                         }
227                 }
228
229                 fprintf(outfile, "\n");
230         }
231
232         return;
233 }
234
235 void
236 pkcs11_export(FILE * outfile, const char *url, unsigned int flags,
237               common_info_st * info)
238 {
239         gnutls_pkcs11_obj_t obj;
240         gnutls_datum_t t;
241         int ret;
242         unsigned int obj_flags = flags;
243
244         pkcs11_common(info);
245
246         FIX(url, outfile, 0, info);
247
248         ret = gnutls_pkcs11_obj_init(&obj);
249         if (ret < 0) {
250                 fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__,
251                         gnutls_strerror(ret));
252                 exit(1);
253         }
254
255         ret = gnutls_pkcs11_obj_import_url(obj, url, obj_flags);
256         if (ret < 0) {
257                 fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__,
258                         gnutls_strerror(ret));
259                 exit(1);
260         }
261
262         ret = gnutls_pkcs11_obj_export3(obj, info->outcert_format, &t);
263         if (ret < 0) {
264                 fprintf(stderr, "Error in %s:%d: %s\n", __func__,
265                                 __LINE__, gnutls_strerror(ret));
266                 exit(1);
267         }
268
269         fwrite(t.data, 1, t.size, outfile);
270         gnutls_free(t.data);
271
272         if (info->outcert_format == GNUTLS_X509_FMT_PEM)
273                 fputs("\n\n", outfile);
274
275         gnutls_pkcs11_obj_deinit(obj);
276
277         return;
278 }
279
280 void
281 pkcs11_export_chain(FILE * outfile, const char *url, unsigned int flags,
282               common_info_st * info)
283 {
284         gnutls_pkcs11_obj_t obj;
285         gnutls_x509_crt_t xcrt;
286         gnutls_datum_t t;
287         int ret;
288         unsigned int obj_flags = flags;
289
290         pkcs11_common(info);
291
292         FIX(url, outfile, 0, info);
293
294         ret = gnutls_pkcs11_obj_init(&obj);
295         if (ret < 0) {
296                 fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__,
297                         gnutls_strerror(ret));
298                 exit(1);
299         }
300
301         ret = gnutls_pkcs11_obj_import_url(obj, url, obj_flags);
302         if (ret < 0) {
303                 fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__,
304                         gnutls_strerror(ret));
305                 exit(1);
306         }
307
308         /* make a crt */
309         ret = gnutls_x509_crt_init(&xcrt);
310         if (ret < 0) {
311                 fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__,
312                         gnutls_strerror(ret));
313                 exit(1);
314         }
315
316         ret = gnutls_x509_crt_import_pkcs11(xcrt, obj);
317         if (ret < 0) {
318                 fprintf(stderr, "Error in %s:%d: %s\n", __func__,
319                                 __LINE__, gnutls_strerror(ret));
320                 exit(1);
321         }
322
323         ret = gnutls_pkcs11_obj_export3(obj, GNUTLS_X509_FMT_PEM, &t);
324         if (ret < 0) {
325                 fprintf(stderr, "Error in %s:%d: %s\n", __func__,
326                                 __LINE__, gnutls_strerror(ret));
327                 exit(1);
328         }
329         fwrite(t.data, 1, t.size, outfile);
330         fputs("\n\n", outfile);
331         gnutls_free(t.data);
332
333         gnutls_pkcs11_obj_deinit(obj);
334         
335         do {
336                 ret = gnutls_pkcs11_get_raw_issuer(url, xcrt, &t, GNUTLS_X509_FMT_PEM, 0);
337                 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
338                         break;
339                 if (ret < 0) {
340                         fprintf(stderr, "Error in %s:%d: %s\n", __func__,
341                                         __LINE__, gnutls_strerror(ret));
342                         exit(1);
343                 }
344                 
345                 fwrite(t.data, 1, t.size, outfile);
346                 fputs("\n\n", outfile);
347
348                 gnutls_x509_crt_deinit(xcrt);
349
350                 ret = gnutls_x509_crt_init(&xcrt);
351                 if (ret < 0) {
352                         fprintf(stderr, "Error in %s:%d: %s\n", __func__,
353                                         __LINE__, gnutls_strerror(ret));
354                         exit(1);
355                 }
356
357                 ret = gnutls_x509_crt_import(xcrt, &t, GNUTLS_X509_FMT_PEM);
358                 if (ret < 0) {
359                         fprintf(stderr, "Error in %s:%d: %s\n", __func__,
360                                         __LINE__, gnutls_strerror(ret));
361                         exit(1);
362                 }
363
364                 gnutls_free(t.data);
365                 
366                 ret = gnutls_x509_crt_check_issuer(xcrt, xcrt);
367                 if (ret != 0) {
368                         /* self signed */
369                         break;
370                 }
371                 
372         } while(1);
373         
374         return;
375 }
376
377 /* If there is a single token only present, return its URL.
378  */
379 static
380 char *get_single_token_url(common_info_st * info)
381 {
382         int ret;
383         char *url = NULL, *t = NULL;
384
385         pkcs11_common(info);
386
387         ret = gnutls_pkcs11_token_get_url(0, 0, &url);
388         if (ret < 0)
389                 return NULL;
390
391         ret = gnutls_pkcs11_token_get_url(1, 0, &t);
392         if (ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
393                 gnutls_free(url);
394                 gnutls_free(t);
395                 return NULL;
396         }
397
398         return url;
399 }
400
401 static
402 void print_type(FILE *outfile, unsigned flags)
403 {
404         unsigned print = 0;
405
406         fputs("\tType: ", outfile);
407         if (flags & GNUTLS_PKCS11_TOKEN_HW) {
408                 fputs("Hardware token", outfile);
409                 print++;
410         }
411
412         if (flags & GNUTLS_PKCS11_TOKEN_TRUSTED) {
413                 if (print != 0)
414                         fputs(", ", outfile);
415                 fputs("Trust module", outfile);
416                 print++;
417         }
418
419         if (print == 0)
420                 fputs("Generic token", outfile);
421         fputc('\n', outfile);
422 }
423
424 void
425 pkcs11_token_list(FILE * outfile, unsigned int detailed,
426                   common_info_st * info, unsigned brief)
427 {
428         int ret;
429         int i;
430         char *url;
431         char buf[128];
432         size_t size;
433         unsigned flags;
434
435         pkcs11_common(info);
436
437         for (i = 0;; i++) {
438                 ret = gnutls_pkcs11_token_get_url(i, detailed, &url);
439                 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
440                         break;
441
442                 if (ret < 0) {
443                         fprintf(stderr, "Error in %s:%d: %s\n", __func__,
444                                 __LINE__, gnutls_strerror(ret));
445                         exit(1);
446                 }
447
448                 if (brief != 0) {
449                         fprintf(outfile, "Token %d: %s\n", i, url);
450                         goto cont;
451                 } else {
452                         fprintf(outfile, "Token %d:\n\tURL: %s\n", i, url);
453                 }
454
455                 size = sizeof(buf);
456                 ret =
457                     gnutls_pkcs11_token_get_info(url,
458                                                  GNUTLS_PKCS11_TOKEN_LABEL,
459                                                  buf, &size);
460                 if (ret < 0) {
461                         fprintf(stderr, "Error in %s:%d: %s\n", __func__,
462                                 __LINE__, gnutls_strerror(ret));
463                         exit(1);
464                 }
465
466                 fprintf(outfile, "\tLabel: %s\n", buf);
467
468                 ret = gnutls_pkcs11_token_get_flags(url, &flags);
469                 if (ret < 0) {
470                         fprintf(stderr, "Error in %s:%d: %s\n", __func__,
471                                 __LINE__, gnutls_strerror(ret));
472                 } else {
473                         print_type(outfile, flags);
474                 }
475
476                 size = sizeof(buf);
477                 ret =
478                     gnutls_pkcs11_token_get_info(url,
479                                                  GNUTLS_PKCS11_TOKEN_MANUFACTURER,
480                                                  buf, &size);
481                 if (ret < 0) {
482                         fprintf(stderr, "Error in %s:%d: %s\n", __func__,
483                                 __LINE__, gnutls_strerror(ret));
484                         exit(1);
485                 }
486
487                 fprintf(outfile, "\tManufacturer: %s\n", buf);
488
489                 size = sizeof(buf);
490                 ret =
491                     gnutls_pkcs11_token_get_info(url,
492                                                  GNUTLS_PKCS11_TOKEN_MODEL,
493                                                  buf, &size);
494                 if (ret < 0) {
495                         fprintf(stderr, "Error in %s:%d: %s\n", __func__,
496                                 __LINE__, gnutls_strerror(ret));
497                         exit(1);
498                 }
499
500                 fprintf(outfile, "\tModel: %s\n", buf);
501
502                 size = sizeof(buf);
503                 ret =
504                     gnutls_pkcs11_token_get_info(url,
505                                                  GNUTLS_PKCS11_TOKEN_SERIAL,
506                                                  buf, &size);
507                 if (ret < 0) {
508                         fprintf(stderr, "Error in %s:%d: %s\n", __func__,
509                                 __LINE__, gnutls_strerror(ret));
510                         exit(1);
511                 }
512
513                 fprintf(outfile, "\tSerial: %s\n", buf);
514                 fprintf(outfile, "\n\n");
515  cont:
516                 gnutls_free(url);
517
518         }
519
520         return;
521 }
522
523 void
524 pkcs11_write(FILE * outfile, const char *url, const char *label,
525              const char *id, unsigned flags, common_info_st * info)
526 {
527         gnutls_x509_crt_t xcrt;
528         gnutls_x509_privkey_t xkey;
529         int ret;
530         unsigned int key_usage = 0;
531         gnutls_datum_t *secret_key;
532         unsigned char raw_id[128];
533         size_t raw_id_size;
534         gnutls_datum_t cid = {NULL, 0};
535
536         pkcs11_common(info);
537
538         FIX(url, outfile, 0, info);
539         CHECK_LOGIN_FLAG(flags);
540
541         if (label == NULL && info->batch == 0) {
542                 label = read_str("warning: The object's label was not specified.\nLabel: ");
543         }
544
545         if (id != NULL) {
546                 raw_id_size = sizeof(raw_id);
547                 ret = gnutls_hex2bin(id, strlen(id), raw_id, &raw_id_size);
548                 if (ret < 0) {
549                         fprintf(stderr, "Error converting hex: %s\n", gnutls_strerror(ret));
550                         exit(1);
551                 }
552                 cid.data = raw_id;
553                 cid.size = raw_id_size;
554         }
555
556         secret_key = load_secret_key(0, info);
557         if (secret_key != NULL) {
558                 ret =
559                     gnutls_pkcs11_copy_secret_key(url, secret_key, label,
560                                                   key_usage,
561                                                   flags |
562                                                   GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE);
563                 if (ret < 0) {
564                         fprintf(stderr, "Error in %s:%d: %s\n", __func__,
565                                 __LINE__, gnutls_strerror(ret));
566                         exit(1);
567                 }
568         }
569
570         xcrt = load_cert(0, info);
571         if (xcrt != NULL) {
572                 ret = gnutls_pkcs11_copy_x509_crt2(url, xcrt, label, &cid, flags);
573                 if (ret < 0) {
574                         fprintf(stderr, "Error writing certificate: %s\n", gnutls_strerror(ret));
575                         if (((flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_CA) ||
576                              (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED)) && 
577                             (flags & GNUTLS_PKCS11_OBJ_FLAG_LOGIN_SO) == 0)
578                                 fprintf(stderr, "note: some tokens may require security officer login for this operation\n");
579                         exit(1);
580                 }
581
582                 gnutls_x509_crt_get_key_usage(xcrt, &key_usage, NULL);
583         }
584
585         xkey = load_x509_private_key(0, info);
586         if (xkey != NULL) {
587                 ret =
588                     gnutls_pkcs11_copy_x509_privkey2(url, xkey, label,
589                                                      &cid, key_usage,
590                                                      flags |
591                                                      GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE);
592                 if (ret < 0) {
593                         fprintf(stderr, "Error in %s:%d: %s\n", __func__,
594                                 __LINE__, gnutls_strerror(ret));
595                         exit(1);
596                 }
597         }
598
599         if (xkey == NULL && xcrt == NULL && secret_key == NULL) {
600                 fprintf(stderr,
601                         "You must use --load-privkey, --load-certificate or --secret-key to load the file to be copied\n");
602                 exit(1);
603         }
604
605         return;
606 }
607
608 void
609 pkcs11_generate(FILE * outfile, const char *url, gnutls_pk_algorithm_t pk,
610                 unsigned int bits,
611                 const char *label, const char *id, int detailed,
612                 unsigned int flags, common_info_st * info)
613 {
614         int ret;
615         gnutls_datum_t pubkey;
616         unsigned char raw_id[128];
617         size_t raw_id_size;
618         gnutls_datum_t cid = {NULL, 0};
619
620         pkcs11_common(info);
621
622         FIX(url, outfile, detailed, info);
623         CHECK_LOGIN_FLAG(flags);
624
625         if (id != NULL) {
626                 raw_id_size = sizeof(raw_id);
627                 ret = gnutls_hex2bin(id, strlen(id), raw_id, &raw_id_size);
628                 if (ret < 0) {
629                         fprintf(stderr, "Error converting hex: %s\n", gnutls_strerror(ret));
630                         exit(1);
631                 }
632                 cid.data = raw_id;
633                 cid.size = raw_id_size;
634         }
635
636         if (outfile == stderr || outfile == stdout) {
637                 fprintf(stderr, "warning: no --outfile was specified and the generated public key will be printed on screen.\n");
638                 fprintf(stderr, "note: in some tokens it is impossible to obtain the public key in any other way after generation.\n");
639                 sleep(3);
640         }
641
642         if (label == NULL && info->batch == 0) {
643                 label = read_str("warning: Label was not specified.\nLabel: ");
644         }
645
646         ret =
647             gnutls_pkcs11_privkey_generate3(url, pk, bits, label, &cid,
648                                             GNUTLS_X509_FMT_PEM, &pubkey,
649                                             flags);
650         if (ret < 0) {
651                 fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__,
652                         gnutls_strerror(ret));
653                 if (bits != 1024 && pk == GNUTLS_PK_RSA)
654                         fprintf(stderr,
655                                 "note: several smart cards do not support arbitrary size keys; try --bits 1024 or 2048.\n");
656                 exit(1);
657         }
658
659         fwrite(pubkey.data, 1, pubkey.size, outfile);
660         gnutls_free(pubkey.data);
661
662         return;
663 }
664
665 void
666 pkcs11_export_pubkey(FILE * outfile, const char *url, int detailed, unsigned int flags, common_info_st * info)
667 {
668         int ret;
669         gnutls_datum_t pubkey;
670         gnutls_pkcs11_privkey_t pkey;
671
672         pkcs11_common(info);
673
674         FIX(url, outfile, detailed, info);
675         CHECK_LOGIN_FLAG(flags);
676
677         if (outfile == stderr || outfile == stdout) {
678                 fprintf(stderr, "warning: no --outfile was specified and the public key will be printed on screen.\n");
679                 sleep(3);
680         }
681
682         ret = gnutls_pkcs11_privkey_init(&pkey);
683         if (ret < 0) {
684                 fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__,
685                         gnutls_strerror(ret));
686                 exit(1);
687         }
688
689         ret = gnutls_pkcs11_privkey_import_url(pkey, url, 0);
690         if (ret < 0) {
691                 fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__,
692                         gnutls_strerror(ret));
693                 exit(1);
694         }
695
696         ret =
697             gnutls_pkcs11_privkey_export_pubkey(pkey,
698                                                 GNUTLS_X509_FMT_PEM, &pubkey,
699                                                 flags);
700         if (ret < 0) {
701                 fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__,
702                         gnutls_strerror(ret));
703                 exit(1);
704         }
705         gnutls_pkcs11_privkey_deinit(pkey);
706
707         fwrite(pubkey.data, 1, pubkey.size, outfile);
708         gnutls_free(pubkey.data);
709
710         return;
711 }
712
713 void
714 pkcs11_init(FILE * outfile, const char *url, const char *label,
715             common_info_st * info)
716 {
717         int ret;
718         const char *pin;
719         char so_pin[32];
720
721         pkcs11_common(info);
722
723         if (url == NULL) {
724                 fprintf(stderr, "error: no token URL given to initialize!\n");
725                 exit(1);
726         }
727
728         if (label == NULL) {
729                 fprintf(stderr, "error: no label provided for token initialization!\n");
730                 exit(1);
731         }
732
733         if (info->so_pin != NULL)
734                 pin = info->so_pin;
735         else {
736                 pin = getenv("GNUTLS_SO_PIN");
737                 if (pin == NULL && info->batch == 0)
738                         pin = getpass("Enter Security Officer's PIN: ");
739                 if (pin == NULL)
740                         exit(1);
741         }
742
743         if (strlen(pin) >= sizeof(so_pin) || pin[0] == '\n')
744                 exit(1);
745
746         strcpy(so_pin, pin);
747
748         fprintf(stderr, "Initializing token... ");
749         ret = gnutls_pkcs11_token_init(url, so_pin, label);
750         if (ret < 0) {
751                 fprintf(stderr, "\nError in %s:%d: %s\n", __func__, __LINE__,
752                         gnutls_strerror(ret));
753                 exit(1);
754         }
755         fprintf(stderr, "done\n");
756
757         fprintf(stderr, "Setting token's user PIN...\n");
758         if (info->pin != NULL) {
759                 pin = info->pin;
760         } else {
761                 pin = getenv("GNUTLS_PIN");
762                 if (pin == NULL && info->batch == 0)
763                         pin = getpass("Enter new User's PIN: ");
764                 if (pin == NULL)
765                         exit(1);
766         }
767
768         if (pin == NULL || pin[0] == '\n')
769                 exit(1);
770
771         /* do not ask the SO PIN twice */
772         setenv("GNUTLS_SO_PIN", so_pin, 0);
773
774         ret = gnutls_pkcs11_token_set_pin(url, NULL, pin, GNUTLS_PIN_USER);
775         if (ret < 0) {
776                 fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__,
777                         gnutls_strerror(ret));
778                 exit(1);
779         }
780
781         return;
782 }
783
784 const char *mech_list[] = {
785         [0] = "CKM_RSA_PKCS_KEY_PAIR_GEN",
786         [1] = "CKM_RSA_PKCS",
787         [2] = "CKM_RSA_9796",
788         [3] = "CKM_RSA_X_509",
789         [4] = "CKM_MD2_RSA_PKCS",
790         [5] = "CKM_MD5_RSA_PKCS",
791         [6] = "CKM_SHA1_RSA_PKCS",
792         [7] = "CKM_RIPEMD128_RSA_PKCS",
793         [8] = "CKM_RIPEMD160_RSA_PKCS",
794         [9] = "CKM_RSA_PKCS_OAEP",
795         [0xa] = "CKM_RSA_X9_31_KEY_PAIR_GEN",
796         [0xb] = "CKM_RSA_X9_31",
797         [0xc] = "CKM_SHA1_RSA_X9_31",
798         [0xd] = "CKM_RSA_PKCS_PSS",
799         [0xe] = "CKM_SHA1_RSA_PKCS_PSS",
800         [0x10] = "CKM_DSA_KEY_PAIR_GEN",
801         [0x11] = "CKM_DSA",
802         [0x12] = "CKM_DSA_SHA1",
803         [0x20] = "CKM_DH_PKCS_KEY_PAIR_GEN",
804         [0x21] = "CKM_DH_PKCS_DERIVE",
805         [0x30] = "CKM_X9_42_DH_KEY_PAIR_GEN",
806         [0x31] = "CKM_X9_42_DH_DERIVE",
807         [0x32] = "CKM_X9_42_DH_HYBRID_DERIVE",
808         [0x33] = "CKM_X9_42_MQV_DERIVE",
809         [0x40] = "CKM_SHA256_RSA_PKCS",
810         [0x41] = "CKM_SHA384_RSA_PKCS",
811         [0x42] = "CKM_SHA512_RSA_PKCS",
812         [0x43] = "CKM_SHA256_RSA_PKCS_PSS",
813         [0x44] = "CKM_SHA384_RSA_PKCS_PSS",
814         [0x45] = "CKM_SHA512_RSA_PKCS_PSS",
815         [0x100] = "CKM_RC2_KEY_GEN",
816         [0x101] = "CKM_RC2_ECB",
817         [0x102] = "CKM_RC2_CBC",
818         [0x103] = "CKM_RC2_MAC",
819         [0x104] = "CKM_RC2_MAC_GENERAL",
820         [0x105] = "CKM_RC2_CBC_PAD",
821         [0x110] = "CKM_RC4_KEY_GEN",
822         [0x111] = "CKM_RC4",
823         [0x120] = "CKM_DES_KEY_GEN",
824         [0x121] = "CKM_DES_ECB",
825         [0x122] = "CKM_DES_CBC",
826         [0x123] = "CKM_DES_MAC",
827         [0x124] = "CKM_DES_MAC_GENERAL",
828         [0x125] = "CKM_DES_CBC_PAD",
829         [0x130] = "CKM_DES2_KEY_GEN",
830         [0x131] = "CKM_DES3_KEY_GEN",
831         [0x132] = "CKM_DES3_ECB",
832         [0x133] = "CKM_DES3_CBC",
833         [0x134] = "CKM_DES3_MAC",
834         [0x135] = "CKM_DES3_MAC_GENERAL",
835         [0x136] = "CKM_DES3_CBC_PAD",
836         [0x140] = "CKM_CDMF_KEY_GEN",
837         [0x141] = "CKM_CDMF_ECB",
838         [0x142] = "CKM_CDMF_CBC",
839         [0x143] = "CKM_CDMF_MAC",
840         [0x144] = "CKM_CDMF_MAC_GENERAL",
841         [0x145] = "CKM_CDMF_CBC_PAD",
842         [0x200] = "CKM_MD2",
843         [0x201] = "CKM_MD2_HMAC",
844         [0x202] = "CKM_MD2_HMAC_GENERAL",
845         [0x210] = "CKM_MD5",
846         [0x211] = "CKM_MD5_HMAC",
847         [0x212] = "CKM_MD5_HMAC_GENERAL",
848         [0x220] = "CKM_SHA_1",
849         [0x221] = "CKM_SHA_1_HMAC",
850         [0x222] = "CKM_SHA_1_HMAC_GENERAL",
851         [0x230] = "CKM_RIPEMD128",
852         [0x231] = "CKM_RIPEMD128_HMAC",
853         [0x232] = "CKM_RIPEMD128_HMAC_GENERAL",
854         [0x240] = "CKM_RIPEMD160",
855         [0x241] = "CKM_RIPEMD160_HMAC",
856         [0x242] = "CKM_RIPEMD160_HMAC_GENERAL",
857         [0x250] = "CKM_SHA256",
858         [0x251] = "CKM_SHA256_HMAC",
859         [0x252] = "CKM_SHA256_HMAC_GENERAL",
860         [0x260] = "CKM_SHA384",
861         [0x261] = "CKM_SHA384_HMAC",
862         [0x262] = "CKM_SHA384_HMAC_GENERAL",
863         [0x270] = "CKM_SHA512",
864         [0x271] = "CKM_SHA512_HMAC",
865         [0x272] = "CKM_SHA512_HMAC_GENERAL",
866         [0x300] = "CKM_CAST_KEY_GEN",
867         [0x301] = "CKM_CAST_ECB",
868         [0x302] = "CKM_CAST_CBC",
869         [0x303] = "CKM_CAST_MAC",
870         [0x304] = "CKM_CAST_MAC_GENERAL",
871         [0x305] = "CKM_CAST_CBC_PAD",
872         [0x310] = "CKM_CAST3_KEY_GEN",
873         [0x311] = "CKM_CAST3_ECB",
874         [0x312] = "CKM_CAST3_CBC",
875         [0x313] = "CKM_CAST3_MAC",
876         [0x314] = "CKM_CAST3_MAC_GENERAL",
877         [0x315] = "CKM_CAST3_CBC_PAD",
878         [0x320] = "CKM_CAST128_KEY_GEN",
879         [0x321] = "CKM_CAST128_ECB",
880         [0x322] = "CKM_CAST128_CBC",
881         [0x323] = "CKM_CAST128_MAC",
882         [0x324] = "CKM_CAST128_MAC_GENERAL",
883         [0x325] = "CKM_CAST128_CBC_PAD",
884         [0x330] = "CKM_RC5_KEY_GEN",
885         [0x331] = "CKM_RC5_ECB",
886         [0x332] = "CKM_RC5_CBC",
887         [0x333] = "CKM_RC5_MAC",
888         [0x334] = "CKM_RC5_MAC_GENERAL",
889         [0x335] = "CKM_RC5_CBC_PAD",
890         [0x340] = "CKM_IDEA_KEY_GEN",
891         [0x341] = "CKM_IDEA_ECB",
892         [0x342] = "CKM_IDEA_CBC",
893         [0x343] = "CKM_IDEA_MAC",
894         [0x344] = "CKM_IDEA_MAC_GENERAL",
895         [0x345] = "CKM_IDEA_CBC_PAD",
896         [0x350] = "CKM_GENERIC_SECRET_KEY_GEN",
897         [0x360] = "CKM_CONCATENATE_BASE_AND_KEY",
898         [0x362] = "CKM_CONCATENATE_BASE_AND_DATA",
899         [0x363] = "CKM_CONCATENATE_DATA_AND_BASE",
900         [0x364] = "CKM_XOR_BASE_AND_DATA",
901         [0x365] = "CKM_EXTRACT_KEY_FROM_KEY",
902         [0x370] = "CKM_SSL3_PRE_MASTER_KEY_GEN",
903         [0x371] = "CKM_SSL3_MASTER_KEY_DERIVE",
904         [0x372] = "CKM_SSL3_KEY_AND_MAC_DERIVE",
905         [0x373] = "CKM_SSL3_MASTER_KEY_DERIVE_DH",
906         [0x374] = "CKM_TLS_PRE_MASTER_KEY_GEN",
907         [0x375] = "CKM_TLS_MASTER_KEY_DERIVE",
908         [0x376] = "CKM_TLS_KEY_AND_MAC_DERIVE",
909         [0x377] = "CKM_TLS_MASTER_KEY_DERIVE_DH",
910         [0x380] = "CKM_SSL3_MD5_MAC",
911         [0x381] = "CKM_SSL3_SHA1_MAC",
912         [0x390] = "CKM_MD5_KEY_DERIVATION",
913         [0x391] = "CKM_MD2_KEY_DERIVATION",
914         [0x392] = "CKM_SHA1_KEY_DERIVATION",
915         [0x3a0] = "CKM_PBE_MD2_DES_CBC",
916         [0x3a1] = "CKM_PBE_MD5_DES_CBC",
917         [0x3a2] = "CKM_PBE_MD5_CAST_CBC",
918         [0x3a3] = "CKM_PBE_MD5_CAST3_CBC",
919         [0x3a4] = "CKM_PBE_MD5_CAST128_CBC",
920         [0x3a5] = "CKM_PBE_SHA1_CAST128_CBC",
921         [0x3a6] = "CKM_PBE_SHA1_RC4_128",
922         [0x3a7] = "CKM_PBE_SHA1_RC4_40",
923         [0x3a8] = "CKM_PBE_SHA1_DES3_EDE_CBC",
924         [0x3a9] = "CKM_PBE_SHA1_DES2_EDE_CBC",
925         [0x3aa] = "CKM_PBE_SHA1_RC2_128_CBC",
926         [0x3ab] = "CKM_PBE_SHA1_RC2_40_CBC",
927         [0x3b0] = "CKM_PKCS5_PBKD2",
928         [0x3c0] = "CKM_PBA_SHA1_WITH_SHA1_HMAC",
929         [0x400] = "CKM_KEY_WRAP_LYNKS",
930         [0x401] = "CKM_KEY_WRAP_SET_OAEP",
931         [0x1000] = "CKM_SKIPJACK_KEY_GEN",
932         [0x1001] = "CKM_SKIPJACK_ECB64",
933         [0x1002] = "CKM_SKIPJACK_CBC64",
934         [0x1003] = "CKM_SKIPJACK_OFB64",
935         [0x1004] = "CKM_SKIPJACK_CFB64",
936         [0x1005] = "CKM_SKIPJACK_CFB32",
937         [0x1006] = "CKM_SKIPJACK_CFB16",
938         [0x1007] = "CKM_SKIPJACK_CFB8",
939         [0x1008] = "CKM_SKIPJACK_WRAP",
940         [0x1009] = "CKM_SKIPJACK_PRIVATE_WRAP",
941         [0x100a] = "CKM_SKIPJACK_RELAYX",
942         [0x1010] = "CKM_KEA_KEY_PAIR_GEN",
943         [0x1011] = "CKM_KEA_KEY_DERIVE",
944         [0x1020] = "CKM_FORTEZZA_TIMESTAMP",
945         [0x1030] = "CKM_BATON_KEY_GEN",
946         [0x1031] = "CKM_BATON_ECB128",
947         [0x1032] = "CKM_BATON_ECB96",
948         [0x1033] = "CKM_BATON_CBC128",
949         [0x1034] = "CKM_BATON_COUNTER",
950         [0x1035] = "CKM_BATON_SHUFFLE",
951         [0x1036] = "CKM_BATON_WRAP",
952         [0x1040] = "CKM_ECDSA_KEY_PAIR_GEN",
953         [0x1041] = "CKM_ECDSA",
954         [0x1042] = "CKM_ECDSA_SHA1",
955         [0x1050] = "CKM_ECDH1_DERIVE",
956         [0x1051] = "CKM_ECDH1_COFACTOR_DERIVE",
957         [0x1052] = "CKM_ECMQV_DERIVE",
958         [0x1060] = "CKM_JUNIPER_KEY_GEN",
959         [0x1061] = "CKM_JUNIPER_ECB128",
960         [0x1062] = "CKM_JUNIPER_CBC128",
961         [0x1063] = "CKM_JUNIPER_COUNTER",
962         [0x1064] = "CKM_JUNIPER_SHUFFLE",
963         [0x1065] = "CKM_JUNIPER_WRAP",
964         [0x1070] = "CKM_FASTHASH",
965         [0x1080] = "CKM_AES_KEY_GEN",
966         [0x1081] = "CKM_AES_ECB",
967         [0x1082] = "CKM_AES_CBC",
968         [0x1083] = "CKM_AES_MAC",
969         [0x1084] = "CKM_AES_MAC_GENERAL",
970         [0x1085] = "CKM_AES_CBC_PAD",
971         [0x2000] = "CKM_DSA_PARAMETER_GEN",
972         [0x2001] = "CKM_DH_PKCS_PARAMETER_GEN",
973         [0x2002] = "CKM_X9_42_DH_PARAMETER_GEN",
974         [0x1200] = "CKM_GOSTR3410_KEY_PAIR_GEN",
975         [0x1201] = "CKM_GOSTR3410",
976         [0x1202] = "CKM_GOSTR3410_WITH_GOSTR3411",
977         [0x1203] = "CKM_GOSTR3410_KEY_WRAP",
978         [0x1204] = "CKM_GOSTR3410_DERIVE",
979         [0x1210] = "CKM_GOSTR3411",
980         [0x1211] = "CKM_GOSTR3411_HMAC",
981         [0x255] = "CKM_SHA224",
982         [0x256] = "CKM_SHA224_HMAC",
983         [0x257] = "CKM_SHA224_HMAC_GENERAL",
984         [0x46] = "CKM_SHA224_RSA_PKCS",
985         [0x47] = "CKM_SHA224_RSA_PKCS_PSS",
986         [0x396] = "CKM_SHA224_KEY_DERIVATION",
987         [0x550] = "CKM_CAMELLIA_KEY_GEN",
988         [0x551] = "CKM_CAMELLIA_ECB",
989         [0x552] = "CKM_CAMELLIA_CBC",
990         [0x553] = "CKM_CAMELLIA_MAC",
991         [0x554] = "CKM_CAMELLIA_MAC_GENERAL",
992         [0x555] = "CKM_CAMELLIA_CBC_PAD",
993         [0x556] = "CKM_CAMELLIA_ECB_ENCRYPT_DATA",
994         [0x557] = "CKM_CAMELLIA_CBC_ENCRYPT_DATA"
995 };
996
997 void
998 pkcs11_mechanism_list(FILE * outfile, const char *url, unsigned int flags,
999                       common_info_st * info)
1000 {
1001         int ret;
1002         int idx;
1003         unsigned long mechanism;
1004         const char *str;
1005
1006         pkcs11_common(info);
1007
1008         FIX(url, outfile, 0, info);
1009
1010         idx = 0;
1011         do {
1012                 ret =
1013                     gnutls_pkcs11_token_get_mechanism(url, idx++,
1014                                                       &mechanism);
1015                 if (ret >= 0) {
1016                         str = NULL;
1017                         if (mechanism <=
1018                             sizeof(mech_list) / sizeof(mech_list[0]))
1019                                 str = mech_list[mechanism];
1020                         if (str == NULL)
1021                                 str = "UNKNOWN";
1022
1023                         fprintf(outfile, "[0x%.4lx] %s\n", mechanism, str);
1024                 }
1025         }
1026         while (ret >= 0);
1027
1028
1029         return;
1030 }
1031
1032 void
1033 pkcs11_get_random(FILE * outfile, const char *url, unsigned bytes,
1034                   common_info_st * info)
1035 {
1036         int ret;
1037         uint8_t *output;
1038
1039         pkcs11_common(info);
1040
1041         FIX(url, outfile, 0, info);
1042
1043         output = malloc(bytes);
1044         if (output == NULL) {
1045                 fprintf(stderr, "Memory error\n");
1046                 exit(1);
1047         }
1048
1049         ret = gnutls_pkcs11_token_get_random(url, output, bytes);
1050         if (ret < 0) {
1051                 fprintf(stderr, "gnutls_pkcs11_token_get_random: %s\n",
1052                         gnutls_strerror(ret));
1053                 exit(1);
1054         }
1055
1056         fwrite(output, 1, bytes, outfile);
1057
1058         return;
1059 }
1060
1061 static
1062 void pkcs11_set_val(FILE * outfile, const char *url, int detailed,
1063                    unsigned int flags, common_info_st * info,
1064                    gnutls_pkcs11_obj_info_t val_type, const char *val)
1065 {
1066         int ret;
1067         gnutls_pkcs11_obj_t obj;
1068
1069         pkcs11_common(info);
1070
1071         FIX(url, outfile, detailed, info);
1072         CHECK_LOGIN_FLAG(flags);
1073
1074         ret = gnutls_pkcs11_obj_init(&obj);
1075         if (ret < 0) {
1076                 fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__,
1077                         gnutls_strerror(ret));
1078                 exit(1);
1079         }
1080
1081         ret = gnutls_pkcs11_obj_import_url(obj, url, flags);
1082         if (ret < 0) {
1083                 fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__,
1084                         gnutls_strerror(ret));
1085                 exit(1);
1086         }
1087
1088         ret =
1089             gnutls_pkcs11_obj_set_info(obj, val_type, val, strlen(val), flags);
1090         if (ret < 0) {
1091                 fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__,
1092                         gnutls_strerror(ret));
1093                 exit(1);
1094         }
1095         gnutls_pkcs11_obj_deinit(obj);
1096
1097         return;
1098 }
1099
1100 void pkcs11_set_id(FILE * outfile, const char *url, int detailed,
1101                    unsigned int flags, common_info_st * info,
1102                    const char *id)
1103 {
1104         return pkcs11_set_val(outfile, url, detailed, flags, info, GNUTLS_PKCS11_OBJ_ID_HEX, id);
1105 }
1106
1107 void pkcs11_set_label(FILE * outfile, const char *url, int detailed,
1108                    unsigned int flags, common_info_st * info,
1109                    const char *label)
1110 {
1111         return pkcs11_set_val(outfile, url, detailed, flags, info, GNUTLS_PKCS11_OBJ_LABEL, label);
1112 }