Fix CVE-2017-6891 in minitasn1 code
[platform/upstream/gnutls.git] / src / certtool-common.c
1 /*
2  * Copyright (C) 2003-2012 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuTLS.
5  *
6  * GnuTLS is free software: you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuTLS is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see
18  * <http://www.gnu.org/licenses/>.
19  *
20  * In addition, as a special exception, the copyright holders give
21  * permission to link the code of portions of this program with the
22  * OpenSSL library under certain conditions as described in each
23  * individual source file, and distribute linked combinations including
24  * the two.
25  * 
26  * You must obey the GNU General Public License in all respects for all
27  * of the code used other than OpenSSL. If you modify file(s) with this
28  * exception, you may extend this exception to your version of the
29  * file(s), but you are not obligated to do so. If you do not wish to do
30  * so, delete this exception statement from your version. If you delete
31  * this exception statement from all source files in the program, then
32  * also delete it here.
33  */
34
35 #include <config.h>
36
37 #include <gnutls/gnutls.h>
38 #include <gnutls/x509.h>
39 #include <gnutls/openpgp.h>
40 #include <gnutls/pkcs12.h>
41 #include <gnutls/pkcs11.h>
42 #include <gnutls/abstract.h>
43
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <ctype.h>
48 #include <time.h>
49 #include <unistd.h>
50 #include <errno.h>
51 #include <sys/types.h>
52 #include <sys/stat.h>
53 #include <fcntl.h>
54 #include <common.h>
55 #include "certtool-common.h"
56 #include "certtool-args.h"
57 #include "certtool-cfg.h"
58 #include <minmax.h>
59
60 /* Gnulib portability files. */
61 #include <read-file.h>
62
63 unsigned char *lbuffer = NULL;
64 unsigned long lbuffer_size = 0;
65
66 static unsigned long file_size(FILE *fp)
67 {
68         unsigned long size;
69         unsigned long cur = ftell(fp);
70         fseek(fp, 0, SEEK_END);
71         size = ftell(fp);
72         fseek(fp, cur, SEEK_SET);
73         return size;
74 }
75
76 void fix_lbuffer(unsigned long size)
77 {
78         if (lbuffer_size == 0 || lbuffer == NULL) {
79                 if (size == 0)
80                         lbuffer_size = 64*1024;
81                 else
82                         lbuffer_size = MAX(64*1024,size+1);
83                 lbuffer = malloc(lbuffer_size);
84         } else if (size > lbuffer_size) {
85                 lbuffer_size = MAX(64*1024,size+1);
86                 lbuffer = realloc(lbuffer, lbuffer_size);
87         }
88
89         if (lbuffer == NULL) {
90                 fprintf(stderr, "memory error");
91                 exit(1);
92         }
93 }
94
95 FILE *safe_open_rw(const char *file, int privkey_op)
96 {
97         mode_t omask = 0;
98         FILE *fh;
99
100         if (privkey_op != 0) {
101                 omask = umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
102         }
103
104         fh = fopen(file, "wb");
105
106         if (privkey_op != 0) {
107                 umask(omask);
108         }
109
110         return fh;
111 }
112
113 gnutls_datum_t *load_secret_key(int mand, common_info_st * info)
114 {
115         static char raw_key[64];
116         size_t raw_key_size = sizeof(raw_key);
117         static gnutls_datum_t key;
118         gnutls_datum_t hex_key;
119         int ret;
120
121         if (info->verbose)
122                 fprintf(stderr, "Loading secret key...\n");
123
124         if (info->secret_key == NULL) {
125                 if (mand) {
126                         fprintf(stderr, "missing --secret-key\n");
127                         exit(1);
128                 } else
129                         return NULL;
130         }
131
132         hex_key.data = (void *) info->secret_key;
133         hex_key.size = strlen(info->secret_key);
134
135         ret = gnutls_hex_decode(&hex_key, raw_key, &raw_key_size);
136         if (ret < 0) {
137                 fprintf(stderr, "hex_decode: %s\n", gnutls_strerror(ret));
138                 exit(1);
139         }
140
141         key.data = (void *) raw_key;
142         key.size = raw_key_size;
143
144         return &key;
145 }
146
147 const char *get_password(common_info_st * cinfo, unsigned int *flags,
148                          int confirm)
149 {
150         const char *p;
151
152         if (cinfo->null_password) {
153                 if (flags)
154                         *flags |= GNUTLS_PKCS_NULL_PASSWORD;
155                 return NULL;
156         } else if (cinfo->password) {
157                 p = cinfo->password;
158         } else {
159                 if (confirm)
160                         p = get_confirmed_pass(true);
161                 else
162                         p = get_pass();
163         }
164
165         if ((p == NULL || p[0] == 0) && flags && !cinfo->empty_password)
166                 *flags |= GNUTLS_PKCS_PLAIN;
167
168         return p;
169 }
170
171 static gnutls_privkey_t _load_privkey(gnutls_datum_t * dat,
172                                       common_info_st * info)
173 {
174         int ret;
175         gnutls_privkey_t key;
176         unsigned int flags = 0;
177         const char *pass;
178
179         ret = gnutls_privkey_init(&key);
180         if (ret < 0) {
181                 fprintf(stderr, "privkey_init: %s\n", gnutls_strerror(ret));
182                 exit(1);
183         }
184
185         ret =
186             gnutls_privkey_import_x509_raw(key, dat, info->incert_format,
187                                            NULL, 0);
188         if (ret == GNUTLS_E_DECRYPTION_FAILED) {
189                 pass = get_password(info, &flags, 0);
190                 ret =
191                     gnutls_privkey_import_x509_raw(key, dat,
192                                                    info->incert_format,
193                                                    pass, flags);
194         }
195
196         if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR) {
197                 fprintf(stderr,
198                         "import error: could not find a valid PEM header; "
199                         "check if your key is PKCS #12 encoded\n");
200                 exit(1);
201         }
202
203         if (ret < 0) {
204                 fprintf(stderr, "importing --load-privkey: %s: %s\n",
205                         info->privkey, gnutls_strerror(ret));
206                 exit(1);
207         }
208
209         return key;
210 }
211
212 static gnutls_privkey_t _load_url_privkey(const char *url)
213 {
214         int ret;
215         gnutls_privkey_t key;
216
217         ret = gnutls_privkey_init(&key);
218         if (ret < 0) {
219                 fprintf(stderr, "privkey_init: %s\n", gnutls_strerror(ret));
220                 exit(1);
221         }
222
223         ret = gnutls_privkey_import_url(key, url, 0);
224         if (ret < 0) {
225                 fprintf(stderr, "importing key: %s: %s\n",
226                         url, gnutls_strerror(ret));
227                 exit(1);
228         }
229
230         return key;
231 }
232
233 static gnutls_pubkey_t _load_url_pubkey(const char *url)
234 {
235         int ret;
236         gnutls_pubkey_t pubkey;
237         unsigned int obj_flags = 0;
238
239         ret = gnutls_pubkey_init(&pubkey);
240         if (ret < 0) {
241                 fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__,
242                         gnutls_strerror(ret));
243                 exit(1);
244         }
245
246         ret = gnutls_pubkey_import_url(pubkey, url, obj_flags);
247         if (ret < 0) {
248                 fprintf(stderr, "Error in %s:%d: %s: %s\n", __func__,
249                         __LINE__, gnutls_strerror(ret), url);
250                 exit(1);
251         }
252
253         return pubkey;
254 }
255
256 /* Load the private key.
257  * @mand should be non zero if it is required to read a private key.
258  */
259 gnutls_privkey_t load_private_key(int mand, common_info_st * info)
260 {
261         gnutls_privkey_t key;
262         gnutls_datum_t dat;
263         size_t size;
264
265         if (!info->privkey && !mand)
266                 return NULL;
267
268         if (info->privkey == NULL) {
269                 fprintf(stderr, "missing --load-privkey\n");
270                 exit(1);
271         }
272
273         if (gnutls_url_is_supported(info->privkey) != 0)
274                 return _load_url_privkey(info->privkey);
275
276         dat.data = (void *) read_binary_file(info->privkey, &size);
277         dat.size = size;
278
279         if (!dat.data) {
280                 fprintf(stderr, "reading --load-privkey: %s\n",
281                         info->privkey);
282                 exit(1);
283         }
284
285         key = _load_privkey(&dat, info);
286
287         free(dat.data);
288
289         return key;
290 }
291
292 /* Load the private key.
293  * @mand should be non zero if it is required to read a private key.
294  */
295 gnutls_x509_privkey_t
296 load_x509_private_key(int mand, common_info_st * info)
297 {
298         gnutls_x509_privkey_t key;
299         int ret;
300         gnutls_datum_t dat;
301         size_t size;
302         unsigned int flags = 0;
303         const char *pass;
304
305         if (!info->privkey && !mand)
306                 return NULL;
307
308         if (info->privkey == NULL) {
309                 fprintf(stderr, "missing --load-privkey\n");
310                 exit(1);
311         }
312
313         ret = gnutls_x509_privkey_init(&key);
314         if (ret < 0) {
315                 fprintf(stderr, "privkey_init: %s\n", gnutls_strerror(ret));
316                 exit(1);
317         }
318
319         dat.data = (void *) read_binary_file(info->privkey, &size);
320         dat.size = size;
321
322         if (!dat.data) {
323                 fprintf(stderr, "reading --load-privkey: %s\n",
324                         info->privkey);
325                 exit(1);
326         }
327
328         if (info->pkcs8) {
329                 pass = get_password(info, &flags, 0);
330                 ret =
331                     gnutls_x509_privkey_import_pkcs8(key, &dat,
332                                                      info->incert_format,
333                                                      pass, flags);
334         } else {
335                 ret =
336                     gnutls_x509_privkey_import2(key, &dat,
337                                                 info->incert_format, NULL,
338                                                 0);
339                 if (ret == GNUTLS_E_DECRYPTION_FAILED) {
340                         pass = get_password(info, &flags, 0);
341                         ret =
342                             gnutls_x509_privkey_import2(key, &dat,
343                                                         info->
344                                                         incert_format,
345                                                         pass, flags);
346                 }
347         }
348
349         free(dat.data);
350
351         if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR) {
352                 fprintf(stderr,
353                         "import error: could not find a valid PEM header; "
354                         "check if your key is PEM encoded\n");
355                 exit(1);
356         }
357
358         if (ret < 0) {
359                 fprintf(stderr, "importing --load-privkey: %s: %s\n",
360                         info->privkey, gnutls_strerror(ret));
361                 exit(1);
362         }
363
364         return key;
365 }
366
367
368 /* Loads the certificate
369  * If mand is non zero then a certificate is mandatory. Otherwise
370  * null will be returned if the certificate loading fails.
371  */
372 gnutls_x509_crt_t load_cert(int mand, common_info_st * info)
373 {
374         gnutls_x509_crt_t *crt;
375         gnutls_x509_crt_t ret_crt;
376         size_t size, i;
377
378         crt = load_cert_list(mand, &size, info);
379         if (crt) {
380                 ret_crt = crt[0];
381                 for (i=1;i<size;i++)
382                         gnutls_x509_crt_deinit(crt[i]);
383                 gnutls_free(crt);
384                 return ret_crt;
385         }
386
387         return NULL;
388 }
389
390 /* Loads a certificate list
391  */
392 gnutls_x509_crt_t *load_cert_list(int mand, size_t * crt_size,
393                                   common_info_st * info)
394 {
395         FILE *fd;
396         static gnutls_x509_crt_t *crt;
397         int ret;
398         gnutls_datum_t dat;
399         unsigned size;
400         unsigned int crt_max;
401
402         *crt_size = 0;
403         if (info->verbose)
404                 fprintf(stderr, "Loading certificate list...\n");
405
406         if (info->cert == NULL) {
407                 if (mand) {
408                         fprintf(stderr, "missing --load-certificate\n");
409                         exit(1);
410                 } else
411                         return NULL;
412         }
413
414         fd = fopen(info->cert, "r");
415         if (fd == NULL) {
416                 fprintf(stderr, "Could not open %s\n", info->cert);
417                 exit(1);
418         }
419
420         fix_lbuffer(file_size(fd));
421
422         size = fread(lbuffer, 1, lbuffer_size - 1, fd);
423         lbuffer[size] = 0;
424
425         fclose(fd);
426
427         dat.data = (void *) lbuffer;
428         dat.size = size;
429
430         ret = gnutls_x509_crt_list_import2(&crt, &crt_max, &dat, GNUTLS_X509_FMT_PEM, 0);
431         if (ret < 0) {
432                 fprintf(stderr, "Error loading certificates: %s\n", gnutls_strerror(ret));
433                 exit(1);
434         }
435
436         *crt_size = crt_max;
437
438         if (info->verbose)
439                 fprintf(stderr, "Loaded %d certificates.\n",
440                         (int) crt_max);
441
442         return crt;
443 }
444
445 /* Load the Certificate Request.
446  */
447 gnutls_x509_crq_t load_request(common_info_st * info)
448 {
449         gnutls_x509_crq_t crq;
450         int ret;
451         gnutls_datum_t dat;
452         size_t size;
453
454         if (!info->request)
455                 return NULL;
456
457         ret = gnutls_x509_crq_init(&crq);
458         if (ret < 0) {
459                 fprintf(stderr, "crq_init: %s\n", gnutls_strerror(ret));
460                 exit(1);
461         }
462
463         dat.data = (void *) read_binary_file(info->request, &size);
464         dat.size = size;
465
466         if (!dat.data) {
467                 fprintf(stderr, "reading --load-request: %s\n",
468                         info->request);
469                 exit(1);
470         }
471
472         ret = gnutls_x509_crq_import(crq, &dat, info->incert_format);
473         if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR) {
474                 fprintf(stderr,
475                         "import error: could not find a valid PEM header\n");
476                 exit(1);
477         }
478
479         free(dat.data);
480         if (ret < 0) {
481                 fprintf(stderr, "importing --load-request: %s: %s\n",
482                         info->request, gnutls_strerror(ret));
483                 exit(1);
484         }
485         return crq;
486 }
487
488 /* Load the CA's private key.
489  */
490 gnutls_privkey_t load_ca_private_key(common_info_st * info)
491 {
492         gnutls_privkey_t key;
493         gnutls_datum_t dat;
494         size_t size;
495
496         if (info->ca_privkey == NULL) {
497                 fprintf(stderr, "missing --load-ca-privkey\n");
498                 exit(1);
499         }
500
501         if (gnutls_url_is_supported(info->ca_privkey) != 0)
502                 return _load_url_privkey(info->ca_privkey);
503
504         dat.data = (void *) read_binary_file(info->ca_privkey, &size);
505         dat.size = size;
506
507         if (!dat.data) {
508                 fprintf(stderr, "reading --load-ca-privkey: %s\n",
509                         info->ca_privkey);
510                 exit(1);
511         }
512
513         key = _load_privkey(&dat, info);
514
515         free(dat.data);
516
517         return key;
518 }
519
520 /* Loads the CA's certificate
521  */
522 gnutls_x509_crt_t load_ca_cert(unsigned mand, common_info_st * info)
523 {
524         gnutls_x509_crt_t crt;
525         int ret;
526         gnutls_datum_t dat;
527         size_t size;
528
529         if (mand == 0 && info->ca == NULL) {
530                 return NULL;
531         }
532
533         if (info->ca == NULL) {
534                 fprintf(stderr, "missing --load-ca-certificate\n");
535                 exit(1);
536         }
537
538         ret = gnutls_x509_crt_init(&crt);
539         if (ret < 0) {
540                 fprintf(stderr, "crt_init: %s\n", gnutls_strerror(ret));
541                 exit(1);
542         }
543
544         dat.data = (void *) read_binary_file(info->ca, &size);
545         dat.size = size;
546
547         if (!dat.data) {
548                 fprintf(stderr, "error reading --load-ca-certificate: %s\n",
549                         info->ca);
550                 exit(1);
551         }
552
553         ret = gnutls_x509_crt_import(crt, &dat, info->incert_format);
554         free(dat.data);
555         if (ret < 0) {
556                 fprintf(stderr, "importing --load-ca-certificate: %s: %s\n",
557                         info->ca, gnutls_strerror(ret));
558                 exit(1);
559         }
560
561         return crt;
562 }
563
564 /* Load a public key.
565  * @mand should be non zero if it is required to read a public key.
566  */
567 gnutls_pubkey_t load_pubkey(int mand, common_info_st * info)
568 {
569         gnutls_pubkey_t key;
570         int ret;
571         gnutls_datum_t dat;
572         size_t size;
573
574         if (!info->pubkey && !mand)
575                 return NULL;
576
577         if (info->pubkey == NULL) {
578                 fprintf(stderr, "missing --load-pubkey\n");
579                 exit(1);
580         }
581
582         if (gnutls_url_is_supported(info->pubkey) != 0)
583                 return _load_url_pubkey(info->pubkey);
584
585         ret = gnutls_pubkey_init(&key);
586         if (ret < 0) {
587                 fprintf(stderr, "privkey_init: %s\n", gnutls_strerror(ret));
588                 exit(1);
589         }
590
591         dat.data = (void *) read_binary_file(info->pubkey, &size);
592         dat.size = size;
593
594         if (!dat.data) {
595                 fprintf(stderr, "reading --load-pubkey: %s\n", info->pubkey);
596                 exit(1);
597         }
598
599         ret = gnutls_pubkey_import(key, &dat, info->incert_format);
600
601         free(dat.data);
602
603         if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR) {
604                 fprintf(stderr,
605                         "import error: could not find a valid PEM header; "
606                         "check if your key has the PUBLIC KEY header\n");
607                 exit(1);
608         }
609
610         if (ret < 0) {
611                 fprintf(stderr, "importing --load-pubkey: %s: %s\n",
612                         info->pubkey, gnutls_strerror(ret));
613                 exit(1);
614         }
615
616         return key;
617 }
618
619 gnutls_pubkey_t load_public_key_or_import(int mand,
620                                           gnutls_privkey_t privkey,
621                                           common_info_st * info)
622 {
623         gnutls_pubkey_t pubkey;
624         int ret;
625
626         ret = gnutls_pubkey_init(&pubkey);
627         if (ret < 0) {
628                 fprintf(stderr, "gnutls_pubkey_init: %s\n",
629                         gnutls_strerror(ret));
630                 exit(1);
631         }
632
633         if (!privkey || (ret = gnutls_pubkey_import_privkey(pubkey, privkey, 0, 0)) < 0) {      /* could not get (e.g. on PKCS #11 */
634                 gnutls_pubkey_deinit(pubkey);
635                 pubkey = load_pubkey(0, info);
636                 if (pubkey == NULL && mand) {
637                         fprintf(stderr, "You must specify --load-privkey\n");
638                         exit(1);
639                 }
640         }
641
642         return pubkey;
643 }
644
645 int
646 get_bits(gnutls_pk_algorithm_t key_type, int info_bits,
647          const char *info_sec_param, int warn)
648 {
649         int bits;
650
651         if (info_bits != 0) {
652                 static int warned = 0;
653
654                 if (warned == 0 && warn != 0 && GNUTLS_BITS_ARE_CURVE(info_bits)==0) {
655                         warned = 1;
656                         fprintf(stderr,
657                                 "** Note: Please use the --sec-param instead of --bits\n");
658                 }
659                 bits = info_bits;
660         } else {
661                 if (info_sec_param == 0) {
662                         /* For ECDSA keys use 256 bits or better, as they are widely supported */
663                         if (key_type == GNUTLS_PK_EC)
664                                 info_sec_param = "HIGH";
665                         else
666                                 info_sec_param = "MEDIUM";
667                 }
668                 bits =
669                     gnutls_sec_param_to_pk_bits(key_type,
670                                                 str_to_sec_param
671                                                 (info_sec_param));
672         }
673
674         return bits;
675 }
676
677 gnutls_sec_param_t str_to_sec_param(const char *str)
678 {
679         if (strcasecmp(str, "low") == 0) {
680                 return GNUTLS_SEC_PARAM_LOW;
681         } else if (strcasecmp(str, "legacy") == 0) {
682                 return GNUTLS_SEC_PARAM_LEGACY;
683         } else if (strcasecmp(str, "normal") == 0 || strcasecmp(str, "medium") == 0) {
684                 return GNUTLS_SEC_PARAM_MEDIUM;
685         } else if (strcasecmp(str, "high") == 0) {
686                 return GNUTLS_SEC_PARAM_HIGH;
687         } else if (strcasecmp(str, "ultra") == 0) {
688                 return GNUTLS_SEC_PARAM_ULTRA;
689         } else {
690                 fprintf(stderr, "Unknown security parameter string: %s\n",
691                         str);
692                 exit(1);
693         }
694
695 }
696
697 #define SPACE "\t"
698 static void
699 print_hex_datum(FILE * outfile, gnutls_datum_t * dat, int cprint)
700 {
701         unsigned int j;
702
703         if (cprint != 0) {
704                 fprintf(outfile, "\n" SPACE "\"");
705                 for (j = 0; j < dat->size; j++) {
706                         fprintf(outfile, "\\x%.2x",
707                                 (unsigned char) dat->data[j]);
708                         if ((j + 1) % 15 == 0)
709                                 fprintf(outfile, "\"\n" SPACE "\"");
710                 }
711                 fprintf(outfile, "\";\n\n");
712
713                 return;
714         }
715
716         fprintf(outfile, "\n" SPACE);
717         for (j = 0; j < dat->size; j++) {
718                 fprintf(outfile, "%.2x:", (unsigned char) dat->data[j]);
719                 if ((j + 1) % 15 == 0)
720                         fprintf(outfile, "\n" SPACE);
721         }
722         fprintf(outfile, "\n\n");
723 }
724
725 static void print_head(FILE * out, const char *txt, unsigned int size,
726                        int cprint)
727 {
728         unsigned i;
729         char *p, *ntxt;
730
731         if (cprint != 0) {
732                 if (size > 0)
733                         asprintf(&ntxt, "const unsigned char %s[%u] =",
734                                  txt, size);
735                 else
736                         asprintf(&ntxt, "const unsigned char %s[] =\n",
737                                  txt);
738
739                 p = strstr(ntxt, "char");
740                 p += 5;
741
742                 for (i = 0; i < strlen(txt); i++)
743                         if (p[i] == ' ')
744                                 p[i] = '_';
745
746                 fprintf(out, "%s", ntxt);
747                 free(ntxt);
748
749                 return;
750         }
751         fprintf(out, "%s:", txt);
752 }
753
754 void
755 print_dsa_pkey(FILE * outfile, gnutls_datum_t * x, gnutls_datum_t * y,
756                gnutls_datum_t * p, gnutls_datum_t * q, gnutls_datum_t * g,
757                int cprint)
758 {
759         if (x) {
760                 print_head(outfile, "private key", x->size, cprint);
761                 print_hex_datum(outfile, x, cprint);
762         }
763         print_head(outfile, "public key", y->size, cprint);
764         print_hex_datum(outfile, y, cprint);
765         print_head(outfile, "p", p->size, cprint);
766         print_hex_datum(outfile, p, cprint);
767         print_head(outfile, "q", q->size, cprint);
768         print_hex_datum(outfile, q, cprint);
769         print_head(outfile, "g", g->size, cprint);
770         print_hex_datum(outfile, g, cprint);
771 }
772
773 gnutls_ecc_curve_t str_to_curve(const char *str)
774 {
775 unsigned num = 0;
776 const gnutls_ecc_curve_t *list, *p;
777
778         list = gnutls_ecc_curve_list();
779
780         p = list;
781         while(*p != 0) {
782                 if (strcasecmp(str, gnutls_ecc_curve_get_name(*p)) == 0)
783                         return *p;
784                 p++;
785                 num++;
786         }
787
788         fprintf(stderr, "Unsupported curve: %s\nAvailable curves:\n", str);
789         if (num == 0)
790                 printf("none\n");
791         p = list;
792         while(*p != 0) {
793                 fprintf(stderr, "\t- %s\n",
794                        gnutls_ecc_curve_get_name(*p));
795                 p++;
796         }
797         exit(1);
798 }
799
800 void
801 print_ecc_pkey(FILE * outfile, gnutls_ecc_curve_t curve,
802                gnutls_datum_t * k, gnutls_datum_t * x, gnutls_datum_t * y,
803                int cprint)
804 {
805         if (cprint != 0)
806                 fprintf(outfile, "/* curve: %s */\n",
807                         gnutls_ecc_curve_get_name(curve));
808         else
809                 fprintf(outfile, "curve:\t%s\n",
810                         gnutls_ecc_curve_get_name(curve));
811
812         if (k) {
813                 print_head(outfile, "private key", k->size, cprint);
814                 print_hex_datum(outfile, k, cprint);
815         }
816         print_head(outfile, "x", x->size, cprint);
817         print_hex_datum(outfile, x, cprint);
818         print_head(outfile, "y", y->size, cprint);
819         print_hex_datum(outfile, y, cprint);
820 }
821
822
823 void
824 print_rsa_pkey(FILE * outfile, gnutls_datum_t * m, gnutls_datum_t * e,
825                gnutls_datum_t * d, gnutls_datum_t * p, gnutls_datum_t * q,
826                gnutls_datum_t * u, gnutls_datum_t * exp1,
827                gnutls_datum_t * exp2, int cprint)
828 {
829         print_head(outfile, "modulus", m->size, cprint);
830         print_hex_datum(outfile, m, cprint);
831         print_head(outfile, "public exponent", e->size, cprint);
832         print_hex_datum(outfile, e, cprint);
833         if (d) {
834                 print_head(outfile, "private exponent", d->size, cprint);
835                 print_hex_datum(outfile, d, cprint);
836                 print_head(outfile, "prime1", p->size, cprint);
837                 print_hex_datum(outfile, p, cprint);
838                 print_head(outfile, "prime2", q->size, cprint);
839                 print_hex_datum(outfile, q, cprint);
840                 print_head(outfile, "coefficient", u->size, cprint);
841                 print_hex_datum(outfile, u, cprint);
842                 if (exp1 && exp2) {
843                         print_head(outfile, "exp1", exp1->size, cprint);
844                         print_hex_datum(outfile, exp1, cprint);
845                         print_head(outfile, "exp2", exp2->size, cprint);
846                         print_hex_datum(outfile, exp2, cprint);
847                 }
848         }
849 }
850
851 void _pubkey_info(FILE * outfile,
852                   gnutls_certificate_print_formats_t format,
853                   gnutls_pubkey_t pubkey)
854 {
855         gnutls_datum_t data;
856         int ret;
857         size_t size;
858
859         fix_lbuffer(0);
860
861         ret = gnutls_pubkey_print(pubkey, format, &data);
862         if (ret < 0) {
863                 fprintf(stderr, "pubkey_print error: %s\n",
864                         gnutls_strerror(ret));
865                 exit(1);
866         }
867
868         fprintf(outfile, "%s\n", data.data);
869         gnutls_free(data.data);
870
871         size = lbuffer_size;
872         ret =
873             gnutls_pubkey_export(pubkey, GNUTLS_X509_FMT_PEM, lbuffer,
874                                  &size);
875         if (ret < 0) {
876                 fprintf(stderr, "export error: %s\n", gnutls_strerror(ret));
877                 exit(1);
878         }
879
880         fprintf(outfile, "\n%s\n", lbuffer);
881 }
882
883 static void
884 print_dh_info(FILE * outfile, gnutls_datum_t * p, gnutls_datum_t * g,
885               unsigned int q_bits, int cprint)
886 {
887         if (q_bits > 0) {
888                 if (cprint != 0)
889                         fprintf(outfile,
890                                 "\n /* recommended key length: %d bytes */\n\n",
891                                 (7 + q_bits) / 8);
892                 else
893                         fprintf(outfile,
894                                 "\nRecommended key length: %d bits\n\n",
895                                 q_bits);
896         }
897
898         print_head(outfile, "generator", g->size, cprint);
899         print_hex_datum(outfile, g, cprint);
900
901         print_head(outfile, "prime", p->size, cprint);
902         print_hex_datum(outfile, p, cprint);
903
904
905 }
906
907 void dh_info(FILE * infile, FILE * outfile, common_info_st * ci)
908 {
909         gnutls_datum_t params;
910         size_t size;
911         int ret;
912         gnutls_dh_params_t dh_params;
913         gnutls_datum_t p, g;
914         unsigned int q_bits = 0;
915
916         fix_lbuffer(0);
917
918         if (gnutls_dh_params_init(&dh_params) < 0) {
919                 fprintf(stderr, "Error in dh parameter initialization\n");
920                 exit(1);
921         }
922
923         params.data = (void *) fread_file(infile, &size);
924         params.size = size;
925
926         ret =
927             gnutls_dh_params_import_pkcs3(dh_params, &params,
928                                           ci->incert_format);
929         if (ret < 0) {
930                 fprintf(stderr, "Error parsing dh params: %s\n",
931                         gnutls_strerror(ret));
932                 exit(1);
933         }
934
935         ret = gnutls_dh_params_export_raw(dh_params, &p, &g, &q_bits);
936         if (ret < 0) {
937                 fprintf(stderr, "Error exporting parameters: %s\n",
938                         gnutls_strerror(ret));
939                 exit(1);
940         }
941
942         if (ci->outcert_format == GNUTLS_X509_FMT_PEM)
943                 print_dh_info(outfile, &p, &g, q_bits, ci->cprint);
944
945         if (!ci->cprint) {      /* generate a PKCS#3 structure */
946                 size_t len = lbuffer_size;
947
948                 ret =
949                     gnutls_dh_params_export_pkcs3(dh_params,
950                                                   ci->outcert_format,
951                                                   lbuffer, &len);
952
953                 if (ret == 0) {
954                         if (ci->outcert_format == GNUTLS_X509_FMT_PEM) {
955                                 fprintf(outfile, "\n%s", lbuffer);
956                         } else {
957                                 fwrite(lbuffer, 1, len, outfile);
958                         }
959                 } else {
960                         fprintf(stderr, "Error: %s\n",
961                                 gnutls_strerror(ret));
962                 }
963         }
964
965         gnutls_dh_params_deinit(dh_params);
966 }
967
968 /* If how is zero then the included parameters are used.
969  */
970 int generate_prime(FILE * outfile, int how, common_info_st * info)
971 {
972         int ret;
973         gnutls_dh_params_t dh_params;
974         gnutls_datum_t p, g;
975         int bits = get_bits(GNUTLS_PK_DH, info->bits, info->sec_param, 1);
976         unsigned int q_bits = 0;
977
978         fix_lbuffer(0);
979
980         gnutls_dh_params_init(&dh_params);
981
982         if (how != 0) {
983                 fprintf(stderr, "Generating DH parameters (%d bits)...\n",
984                         bits);
985                 fprintf(stderr, "(might take long time)\n");
986         } else
987                 fprintf(stderr, "Retrieving DH parameters...\n");
988
989         if (how != 0) {
990                 ret = gnutls_dh_params_generate2(dh_params, bits);
991                 if (ret < 0) {
992                         fprintf(stderr,
993                                 "Error generating parameters: %s\n",
994                                 gnutls_strerror(ret));
995                         exit(1);
996                 }
997
998                 ret =
999                     gnutls_dh_params_export_raw(dh_params, &p, &g,
1000                                                 &q_bits);
1001                 if (ret < 0) {
1002                         fprintf(stderr, "Error exporting parameters: %s\n",
1003                                 gnutls_strerror(ret));
1004                         exit(1);
1005                 }
1006         } else {
1007 #ifdef ENABLE_SRP
1008                 if (bits <= 1024) {
1009                         p = gnutls_srp_1024_group_prime;
1010                         g = gnutls_srp_1024_group_generator;
1011                         bits = 1024;
1012                 } else if (bits <= 1536) {
1013                         p = gnutls_srp_1536_group_prime;
1014                         g = gnutls_srp_1536_group_generator;
1015                         bits = 1536;
1016                 } else if (bits <= 2048) {
1017                         p = gnutls_srp_2048_group_prime;
1018                         g = gnutls_srp_2048_group_generator;
1019                         bits = 2048;
1020                 } else if (bits <= 3072) {
1021                         p = gnutls_srp_3072_group_prime;
1022                         g = gnutls_srp_3072_group_generator;
1023                         bits = 3072;
1024                 } else {
1025                         p = gnutls_srp_4096_group_prime;
1026                         g = gnutls_srp_4096_group_generator;
1027                         bits = 4096;
1028                 }
1029
1030                 ret = gnutls_dh_params_import_raw(dh_params, &p, &g);
1031                 if (ret < 0) {
1032                         fprintf(stderr, "Error exporting parameters: %s\n",
1033                                 gnutls_strerror(ret));
1034                         exit(1);
1035                 }
1036 #else
1037                 fprintf(stderr,
1038                         "Parameters unavailable as SRP is disabled.\n");
1039                 exit(1);
1040 #endif
1041         }
1042
1043         print_dh_info(outfile, &p, &g, q_bits, info->cprint);
1044
1045         if (!info->cprint) {    /* generate a PKCS#3 structure */
1046                 size_t len = lbuffer_size;
1047
1048                 ret =
1049                     gnutls_dh_params_export_pkcs3(dh_params,
1050                                                   GNUTLS_X509_FMT_PEM,
1051                                                   lbuffer, &len);
1052
1053                 if (ret == 0) {
1054                         fprintf(outfile, "\n%s", lbuffer);
1055                 } else {
1056                         fprintf(stderr, "Error: %s\n",
1057                                 gnutls_strerror(ret));
1058                 }
1059
1060         }
1061
1062         gnutls_dh_params_deinit(dh_params);
1063
1064         return 0;
1065 }