Tizen 2.0 Release
[external/libgnutls26.git] / src / certtool.c
1 /*
2  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
3  *   2011 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuTLS.
6  *
7  * GnuTLS is free software: you can redistribute it and/or modify it
8  * 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, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * 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
19  * <http://www.gnu.org/licenses/>.
20  */
21
22 #include <config.h>
23
24 #include <gnutls/gnutls.h>
25 #include <gnutls/x509.h>
26 #include <gnutls/openpgp.h>
27 #include <gnutls/pkcs12.h>
28 #include <gnutls/pkcs11.h>
29 #include <gnutls/abstract.h>
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include <time.h>
36 #include <unistd.h>
37 #include <errno.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <fcntl.h>
41 #include <error.h>
42
43 /* Gnulib portability files. */
44 #include <read-file.h>
45 #include <progname.h>
46 #include <version-etc.h>
47
48 #include <certtool-cfg.h>
49 #include <p11common.h>
50 #include "certtool-gaa.h"
51 #include "certtool-common.h"
52
53 #define SIGN_HASH GNUTLS_DIG_SHA1
54
55 static void print_crl_info (gnutls_x509_crl_t crl, FILE * out);
56 void pkcs7_info (void);
57 void crq_info (void);
58 void smime_to_pkcs7 (void);
59 void pkcs12_info (void);
60 void generate_pkcs12 (common_info_st *);
61 void generate_pkcs8 (common_info_st *);
62 void verify_chain (void);
63 void verify_crl (common_info_st * cinfo);
64 void pubkey_info (gnutls_x509_crt crt, common_info_st *);
65 void pgp_privkey_info (void);
66 void pgp_ring_info (void);
67 void certificate_info (int, common_info_st *);
68 void pgp_certificate_info (void);
69 void crl_info (void);
70 void privkey_info (void);
71 static void gaa_parser (int argc, char **argv);
72 void generate_self_signed (common_info_st *);
73 void generate_request (common_info_st *);
74 static void print_certificate_info (gnutls_x509_crt_t crt, FILE * out,
75                                     unsigned int all);
76
77 static void print_hex_datum (gnutls_datum_t * dat);
78
79 static gaainfo info;
80 FILE *outfile;
81 FILE *infile;
82 gnutls_digest_algorithm_t default_dig;
83
84 /* non interactive operation if set
85  */
86 int batch;
87
88
89 static void
90 tls_log_func (int level, const char *str)
91 {
92   fprintf (stderr, "|<%d>| %s", level, str);
93 }
94
95 int
96 main (int argc, char **argv)
97 {
98   set_program_name (argv[0]);
99   cfg_init ();
100   gaa_parser (argc, argv);
101
102   return 0;
103 }
104
105 static const char *
106 raw_to_string (const unsigned char *raw, size_t raw_size)
107 {
108   static char buf[1024];
109   size_t i;
110   if (raw_size == 0)
111     return NULL;
112
113   if (raw_size * 3 + 1 >= sizeof (buf))
114     return NULL;
115
116   for (i = 0; i < raw_size; i++)
117     {
118       sprintf (&(buf[i * 3]), "%02X%s", raw[i],
119                (i == raw_size - 1) ? "" : ":");
120     }
121   buf[sizeof (buf) - 1] = '\0';
122
123   return buf;
124 }
125
126 static void
127 print_dsa_pkey (gnutls_datum_t * x, gnutls_datum_t * y, gnutls_datum_t * p,
128                 gnutls_datum_t * q, gnutls_datum_t * g)
129 {
130   if (x)
131     {
132       fprintf (outfile, "private key:");
133       print_hex_datum (x);
134     }
135   fprintf (outfile, "public key:");
136   print_hex_datum (y);
137   fprintf (outfile, "p:");
138   print_hex_datum (p);
139   fprintf (outfile, "q:");
140   print_hex_datum (q);
141   fprintf (outfile, "g:");
142   print_hex_datum (g);
143 }
144
145 static void
146 print_rsa_pkey (gnutls_datum_t * m, gnutls_datum_t * e, gnutls_datum_t * d,
147                 gnutls_datum_t * p, gnutls_datum_t * q, gnutls_datum_t * u,
148                 gnutls_datum_t * exp1, gnutls_datum_t * exp2)
149 {
150   fprintf (outfile, "modulus:");
151   print_hex_datum (m);
152   fprintf (outfile, "public exponent:");
153   print_hex_datum (e);
154   if (d)
155     {
156       fprintf (outfile, "private exponent:");
157       print_hex_datum (d);
158       fprintf (outfile, "prime1:");
159       print_hex_datum (p);
160       fprintf (outfile, "prime2:");
161       print_hex_datum (q);
162       fprintf (outfile, "coefficient:");
163       print_hex_datum (u);
164       if (exp1 && exp2)
165         {
166           fprintf (outfile, "exp1:");
167           print_hex_datum (exp1);
168           fprintf (outfile, "exp2:");
169           print_hex_datum (exp2);
170         }
171     }
172 }
173
174 static gnutls_sec_param_t
175 str_to_sec_param (const char *str)
176 {
177   if (strcasecmp (str, "low") == 0)
178     {
179       return GNUTLS_SEC_PARAM_LOW;
180     }
181   else if (strcasecmp (str, "normal") == 0)
182     {
183       return GNUTLS_SEC_PARAM_NORMAL;
184     }
185   else if (strcasecmp (str, "high") == 0)
186     {
187       return GNUTLS_SEC_PARAM_HIGH;
188     }
189   else if (strcasecmp (str, "ultra") == 0)
190     {
191       return GNUTLS_SEC_PARAM_ULTRA;
192     }
193   else
194     {
195       fprintf (stderr, "Unknown security parameter string: %s\n", str);
196       exit (1);
197     }
198
199 }
200
201 int
202 get_bits (gnutls_pk_algorithm_t key_type)
203 {
204   int bits;
205
206   if (info.bits != 0)
207     {
208       static int warned = 0;
209
210       if (warned == 0)
211         {
212           warned = 1;
213           fprintf (stderr,
214                    "** Note: Please use the --sec-param instead of --bits\n");
215         }
216       bits = info.bits;
217     }
218   else
219     {
220       if (info.sec_param)
221         {
222           bits =
223             gnutls_sec_param_to_pk_bits (key_type,
224                                          str_to_sec_param (info.sec_param));
225         }
226       else
227         bits =
228           gnutls_sec_param_to_pk_bits (key_type, GNUTLS_SEC_PARAM_NORMAL);
229     }
230
231   return bits;
232 }
233
234
235 static gnutls_x509_privkey_t
236 generate_private_key_int (void)
237 {
238   gnutls_x509_privkey_t key;
239   int ret, key_type, bits;
240
241   if (info.dsa)
242     {
243       key_type = GNUTLS_PK_DSA;
244     }
245   else
246     key_type = GNUTLS_PK_RSA;
247
248   ret = gnutls_x509_privkey_init (&key);
249   if (ret < 0)
250     error (EXIT_FAILURE, 0, "privkey_init: %s", gnutls_strerror (ret));
251
252   bits = get_bits (key_type);
253
254   fprintf (stderr, "Generating a %d bit %s private key...\n",
255            bits, gnutls_pk_algorithm_get_name (key_type));
256
257   if (info.quick_random == 0)
258     fprintf (stderr,
259              "This might take several minutes depending on availability of randomness"
260              " in /dev/random.\n");
261
262   if (bits > 1024 && key_type == GNUTLS_PK_DSA)
263     fprintf (stderr,
264              "Note that DSA keys with size over 1024 can only be used with TLS 1.2 or later.\n\n");
265
266   ret = gnutls_x509_privkey_generate (key, key_type,bits, 0);
267   if (ret < 0)
268     error (EXIT_FAILURE, 0, "privkey_generate: %s", gnutls_strerror (ret));
269
270   return key;
271 }
272
273 static int
274 cipher_to_flags (const char *cipher)
275 {
276   if (strcasecmp (cipher, "3des") == 0)
277     {
278       return GNUTLS_PKCS_USE_PBES2_3DES;
279     }
280   else if (strcasecmp (cipher, "3des-pkcs12") == 0)
281     {
282       return GNUTLS_PKCS_USE_PKCS12_3DES;
283     }
284   else if (strcasecmp (cipher, "arcfour") == 0)
285     {
286       return GNUTLS_PKCS_USE_PKCS12_ARCFOUR;
287     }
288   else if (strcasecmp (cipher, "aes-128") == 0)
289     {
290       return GNUTLS_PKCS_USE_PBES2_AES_128;
291     }
292   else if (strcasecmp (cipher, "aes-192") == 0)
293     {
294       return GNUTLS_PKCS_USE_PBES2_AES_192;
295     }
296   else if (strcasecmp (cipher, "aes-256") == 0)
297     {
298       return GNUTLS_PKCS_USE_PBES2_AES_256;
299     }
300   else if (strcasecmp (cipher, "rc2-40") == 0)
301     {
302       return GNUTLS_PKCS_USE_PKCS12_RC2_40;
303     }
304
305   error (EXIT_FAILURE, 0, "Unknown cipher %s\n", cipher);
306   return -1;
307 }
308
309
310 static void
311 print_private_key (gnutls_x509_privkey_t key)
312 {
313   int ret;
314   size_t size;
315
316   if (!key)
317     return;
318
319   if (!info.pkcs8)
320     {
321       size = buffer_size;
322       ret = gnutls_x509_privkey_export (key, info.outcert_format,
323                                         buffer, &size);
324       if (ret < 0)
325         error (EXIT_FAILURE, 0, "privkey_export: %s", gnutls_strerror (ret));
326     }
327   else
328     {
329       unsigned int flags;
330       const char *pass;
331
332       if (info.export)
333         flags = GNUTLS_PKCS_USE_PKCS12_RC2_40;
334       else
335         flags = cipher_to_flags (info.pkcs_cipher);
336
337       if ((pass = get_confirmed_pass (true)) == NULL || *pass == '\0')
338         flags = GNUTLS_PKCS_PLAIN;
339
340       size = buffer_size;
341       ret =
342         gnutls_x509_privkey_export_pkcs8 (key, info.outcert_format, pass,
343                                           flags, buffer, &size);
344       if (ret < 0)
345         error (EXIT_FAILURE, 0, "privkey_export_pkcs8: %s",
346                gnutls_strerror (ret));
347     }
348
349   fwrite (buffer, 1, size, outfile);
350 }
351
352 static void
353 generate_private_key (void)
354 {
355   gnutls_x509_privkey_t key;
356
357   key = generate_private_key_int ();
358
359   print_private_key (key);
360
361   gnutls_x509_privkey_deinit (key);
362 }
363
364
365 static gnutls_x509_crt_t
366 generate_certificate (gnutls_privkey_t * ret_key,
367                       gnutls_x509_crt_t ca_crt, int proxy,
368                       common_info_st * cinfo)
369 {
370   gnutls_x509_crt_t crt;
371   gnutls_privkey_t key = NULL;
372   gnutls_pubkey_t pubkey;
373   size_t size;
374   int ret;
375   int client;
376   int days, result, ca_status = 0, is_ike = 0, path_len;
377   int vers;
378   unsigned int usage = 0, server;
379   gnutls_x509_crq_t crq;        /* request */
380
381   ret = gnutls_x509_crt_init (&crt);
382   if (ret < 0)
383     error (EXIT_FAILURE, 0, "crt_init: %s", gnutls_strerror (ret));
384
385   crq = load_request (cinfo);
386
387   if (crq == NULL)
388     {
389
390       key = load_private_key (1, cinfo);
391       
392       pubkey = load_public_key_or_import (1, key, cinfo);
393
394       if (!batch)
395         fprintf (stderr,
396                  "Please enter the details of the certificate's distinguished name. "
397                  "Just press enter to ignore a field.\n");
398
399       /* set the DN.
400        */
401       if (proxy)
402         {
403           result = gnutls_x509_crt_set_proxy_dn (crt, ca_crt, 0, NULL, 0);
404           if (result < 0)
405             error (EXIT_FAILURE, 0, "set_proxy_dn: %s",
406                    gnutls_strerror (result));
407
408           get_cn_crt_set (crt);
409         }
410       else
411         {
412           get_country_crt_set (crt);
413           get_organization_crt_set (crt);
414           get_unit_crt_set (crt);
415           get_locality_crt_set (crt);
416           get_state_crt_set (crt);
417           get_cn_crt_set (crt);
418           get_uid_crt_set (crt);
419           get_oid_crt_set (crt);
420           get_key_purpose_set (crt);
421
422           if (!batch)
423             fprintf (stderr,
424                      "This field should not be used in new certificates.\n");
425
426           get_pkcs9_email_crt_set (crt);
427         }
428
429       result = gnutls_x509_crt_set_pubkey (crt, pubkey);
430       if (result < 0)
431         error (EXIT_FAILURE, 0, "set_key: %s", gnutls_strerror (result));
432     }
433   else
434     {
435       result = gnutls_x509_crt_set_crq (crt, crq);
436       if (result < 0)
437         error (EXIT_FAILURE, 0, "set_crq: %s", gnutls_strerror (result));
438     }
439
440
441   {
442     int serial = get_serial ();
443     char bin_serial[5];
444
445     bin_serial[4] = serial & 0xff;
446     bin_serial[3] = (serial >> 8) & 0xff;
447     bin_serial[2] = (serial >> 16) & 0xff;
448     bin_serial[1] = (serial >> 24) & 0xff;
449     bin_serial[0] = 0;
450
451     result = gnutls_x509_crt_set_serial (crt, bin_serial, 5);
452     if (result < 0)
453       error (EXIT_FAILURE, 0, "serial: %s", gnutls_strerror (result));
454   }
455
456   if (!batch)
457     fprintf (stderr, "\n\nActivation/Expiration time.\n");
458
459   gnutls_x509_crt_set_activation_time (crt, time (NULL));
460
461   days = get_days ();
462
463   result =
464     gnutls_x509_crt_set_expiration_time (crt,
465                                          time (NULL) + days * 24 * 60 * 60);
466   if (result < 0)
467     error (EXIT_FAILURE, 0, "set_expiration: %s", gnutls_strerror (result));
468
469   if (!batch)
470     fprintf (stderr, "\n\nExtensions.\n");
471
472   /* do not allow extensions on a v1 certificate */
473   if (crq && get_crq_extensions_status () != 0)
474     {
475       result = gnutls_x509_crt_set_crq_extensions (crt, crq);
476       if (result < 0)
477         error (EXIT_FAILURE, 0, "set_crq: %s", gnutls_strerror (result));
478     }
479
480   /* append additional extensions */
481   if (info.v1_cert == 0)
482     {
483
484       if (proxy)
485         {
486           const char *policylanguage;
487           char *policy;
488           size_t policylen;
489           int proxypathlen = get_path_len ();
490
491           if (!batch)
492             {
493               printf ("1.3.6.1.5.5.7.21.1 ::= id-ppl-inheritALL\n");
494               printf ("1.3.6.1.5.5.7.21.2 ::= id-ppl-independent\n");
495             }
496
497           policylanguage = get_proxy_policy (&policy, &policylen);
498
499           result =
500             gnutls_x509_crt_set_proxy (crt, proxypathlen, policylanguage,
501                                        policy, policylen);
502           if (result < 0)
503             error (EXIT_FAILURE, 0, "set_proxy: %s",
504                    gnutls_strerror (result));
505         }
506
507       if (!proxy)
508         ca_status = get_ca_status ();
509       if (ca_status)
510         path_len = get_path_len ();
511       else
512         path_len = -1;
513
514       result =
515         gnutls_x509_crt_set_basic_constraints (crt, ca_status, path_len);
516       if (result < 0)
517         error (EXIT_FAILURE, 0, "basic_constraints: %s",
518                gnutls_strerror (result));
519
520       client = get_tls_client_status ();
521       if (client != 0)
522         {
523           result = gnutls_x509_crt_set_key_purpose_oid (crt,
524                                                         GNUTLS_KP_TLS_WWW_CLIENT,
525                                                         0);
526           if (result < 0)
527             error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (result));
528         }
529
530       is_ike = get_ipsec_ike_status ();
531       server = get_tls_server_status ();
532       if ((server != 0 && !proxy) || is_ike)
533         {
534           get_dns_name_set (TYPE_CRT, crt);
535           get_ip_addr_set (TYPE_CRT, crt);
536         }
537
538       if (server != 0)
539         {
540           result = 0;
541
542           result =
543             gnutls_x509_crt_set_key_purpose_oid (crt,
544                                                  GNUTLS_KP_TLS_WWW_SERVER, 0);
545           if (result < 0)
546             error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (result));
547         }
548       else if (!proxy)
549         {
550           get_email_set (TYPE_CRT, crt);
551         }
552
553       if (!ca_status || server)
554         {
555           int pk;
556
557
558           pk = gnutls_x509_crt_get_pk_algorithm (crt, NULL);
559
560           if (pk != GNUTLS_PK_DSA)
561             {                   /* DSA keys can only sign.
562                                  */
563               result = get_sign_status (server);
564               if (result)
565                 usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
566
567               result = get_encrypt_status (server);
568               if (result)
569                 usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
570             }
571           else
572             usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
573
574           if (is_ike)
575             {
576               result =
577                 gnutls_x509_crt_set_key_purpose_oid (crt,
578                                                      GNUTLS_KP_IPSEC_IKE, 0);
579               if (result < 0)
580                 error (EXIT_FAILURE, 0, "key_kp: %s",
581                        gnutls_strerror (result));
582             }
583         }
584
585
586       if (ca_status)
587         {
588           result = get_cert_sign_status ();
589           if (result)
590             usage |= GNUTLS_KEY_KEY_CERT_SIGN;
591
592           result = get_crl_sign_status ();
593           if (result)
594             usage |= GNUTLS_KEY_CRL_SIGN;
595
596           result = get_code_sign_status ();
597           if (result)
598             {
599               result =
600                 gnutls_x509_crt_set_key_purpose_oid (crt,
601                                                      GNUTLS_KP_CODE_SIGNING,
602                                                      0);
603               if (result < 0)
604                 error (EXIT_FAILURE, 0, "key_kp: %s",
605                        gnutls_strerror (result));
606             }
607
608           result = get_ocsp_sign_status ();
609           if (result)
610             {
611               result =
612                 gnutls_x509_crt_set_key_purpose_oid (crt,
613                                                      GNUTLS_KP_OCSP_SIGNING,
614                                                      0);
615               if (result < 0)
616                 error (EXIT_FAILURE, 0, "key_kp: %s",
617                        gnutls_strerror (result));
618             }
619
620           result = get_time_stamp_status ();
621           if (result)
622             {
623               result =
624                 gnutls_x509_crt_set_key_purpose_oid (crt,
625                                                      GNUTLS_KP_TIME_STAMPING,
626                                                      0);
627               if (result < 0)
628                 error (EXIT_FAILURE, 0, "key_kp: %s",
629                        gnutls_strerror (result));
630             }
631         }
632
633       if (usage != 0)
634         {
635           /* http://tools.ietf.org/html/rfc4945#section-5.1.3.2: if any KU is
636              set, then either digitalSignature or the nonRepudiation bits in the
637              KeyUsage extension MUST for all IKE certs */
638           if (is_ike && (get_sign_status (server) != 1))
639             usage |= GNUTLS_KEY_NON_REPUDIATION;
640           result = gnutls_x509_crt_set_key_usage (crt, usage);
641           if (result < 0)
642             error (EXIT_FAILURE, 0, "key_usage: %s",
643                    gnutls_strerror (result));
644         }
645
646       /* Subject Key ID.
647        */
648       size = buffer_size;
649       result = gnutls_x509_crt_get_key_id (crt, 0, buffer, &size);
650       if (result >= 0)
651         {
652           result = gnutls_x509_crt_set_subject_key_id (crt, buffer, size);
653           if (result < 0)
654             error (EXIT_FAILURE, 0, "set_subject_key_id: %s",
655                    gnutls_strerror (result));
656         }
657
658       /* Authority Key ID.
659        */
660       if (ca_crt != NULL)
661         {
662           size = buffer_size;
663           result = gnutls_x509_crt_get_subject_key_id (ca_crt, buffer,
664                                                        &size, NULL);
665           if (result < 0)
666             {
667               size = buffer_size;
668               result = gnutls_x509_crt_get_key_id (ca_crt, 0, buffer, &size);
669             }
670           if (result >= 0)
671             {
672               result =
673                 gnutls_x509_crt_set_authority_key_id (crt, buffer, size);
674               if (result < 0)
675                 error (EXIT_FAILURE, 0, "set_authority_key_id: %s",
676                        gnutls_strerror (result));
677             }
678         }
679     }
680
681   /* Version.
682    */
683   if (info.v1_cert != 0)
684     vers = 1;
685   else
686     vers = 3;
687   result = gnutls_x509_crt_set_version (crt, vers);
688   if (result < 0)
689     error (EXIT_FAILURE, 0, "set_version: %s", gnutls_strerror (result));
690
691   *ret_key = key;
692   return crt;
693
694 }
695
696 static gnutls_x509_crl_t
697 generate_crl (gnutls_x509_crt_t ca_crt, common_info_st * cinfo)
698 {
699   gnutls_x509_crl_t crl;
700   gnutls_x509_crt_t *crts;
701   size_t size;
702   int days, result;
703   unsigned int i;
704   time_t now = time (NULL);
705
706   result = gnutls_x509_crl_init (&crl);
707   if (result < 0)
708     error (EXIT_FAILURE, 0, "crl_init: %s", gnutls_strerror (result));
709
710   crts = load_cert_list (0, &size, cinfo);
711
712   for (i = 0; i < size; i++)
713     {
714       result = gnutls_x509_crl_set_crt (crl, crts[i], now);
715       if (result < 0)
716         error (EXIT_FAILURE, 0, "crl_set_crt: %s", gnutls_strerror (result));
717     }
718
719   result = gnutls_x509_crl_set_this_update (crl, now);
720   if (result < 0)
721     error (EXIT_FAILURE, 0, "this_update: %s", gnutls_strerror (result));
722
723   fprintf (stderr, "Update times.\n");
724   days = get_crl_next_update ();
725
726   result = gnutls_x509_crl_set_next_update (crl, now + days * 24 * 60 * 60);
727   if (result < 0)
728     error (EXIT_FAILURE, 0, "next_update: %s", gnutls_strerror (result));
729
730   result = gnutls_x509_crl_set_version (crl, 2);
731   if (result < 0)
732     error (EXIT_FAILURE, 0, "set_version: %s", gnutls_strerror (result));
733
734   /* Authority Key ID.
735    */
736   if (ca_crt != NULL)
737     {
738       size = buffer_size;
739       result = gnutls_x509_crt_get_subject_key_id (ca_crt, buffer,
740                                                    &size, NULL);
741       if (result < 0)
742         {
743           size = buffer_size;
744           result = gnutls_x509_crt_get_key_id (ca_crt, 0, buffer, &size);
745         }
746       if (result >= 0)
747         {
748           result = gnutls_x509_crl_set_authority_key_id (crl, buffer, size);
749           if (result < 0)
750             error (EXIT_FAILURE, 0, "set_authority_key_id: %s",
751                    gnutls_strerror (result));
752         }
753     }
754
755   {
756     unsigned int number = get_crl_number ();
757     char bin_number[5];
758
759     bin_number[4] = number & 0xff;
760     bin_number[3] = (number >> 8) & 0xff;
761     bin_number[2] = (number >> 16) & 0xff;
762     bin_number[1] = (number >> 24) & 0xff;
763     bin_number[0] = 0;
764
765     result = gnutls_x509_crl_set_number (crl, bin_number, 5);
766     if (result < 0)
767       error (EXIT_FAILURE, 0, "set_number: %s", gnutls_strerror (result));
768   }
769
770   return crl;
771 }
772
773 static gnutls_digest_algorithm_t
774 get_dig (gnutls_x509_crt crt)
775 {
776   gnutls_digest_algorithm_t dig;
777   gnutls_pubkey_t pubkey;
778   int result;
779   unsigned int mand;
780
781   gnutls_pubkey_init(&pubkey);
782
783   result = gnutls_pubkey_import_x509(pubkey, crt, 0);
784   if (result < 0)
785     {
786       error (EXIT_FAILURE, 0, "gnutls_pubkey_import_x509: %s",
787              gnutls_strerror (result));
788     }
789
790   result = gnutls_pubkey_get_preferred_hash_algorithm (pubkey, &dig, &mand);
791   if (result < 0)
792     {
793       error (EXIT_FAILURE, 0, "crt_get_preferred_hash_algorithm: %s",
794              gnutls_strerror (result));
795     }
796
797   gnutls_pubkey_deinit(pubkey);
798
799   /* if algorithm allows alternatives */
800   if (mand == 0 && default_dig != GNUTLS_DIG_UNKNOWN)
801     dig = default_dig;
802
803   return dig;
804 }
805
806 void
807 generate_self_signed (common_info_st * cinfo)
808 {
809   gnutls_x509_crt_t crt;
810   gnutls_privkey_t key;
811   size_t size;
812   int result;
813   const char *uri;
814
815   fprintf (stderr, "Generating a self signed certificate...\n");
816
817   crt = generate_certificate (&key, NULL, 0, cinfo);
818
819   if (!key)
820     key = load_private_key (1, cinfo);
821
822   uri = get_crl_dist_point_url ();
823   if (uri)
824     {
825       result = gnutls_x509_crt_set_crl_dist_points (crt, GNUTLS_SAN_URI,
826                                                     uri,
827                                                     0 /* all reasons */ );
828       if (result < 0)
829         error (EXIT_FAILURE, 0, "crl_dist_points: %s",
830                gnutls_strerror (result));
831     }
832
833   print_certificate_info (crt, stderr, 0);
834
835   fprintf (stderr, "\n\nSigning certificate...\n");
836
837   result = gnutls_x509_crt_privkey_sign (crt, crt, key, get_dig (crt), 0);
838   if (result < 0)
839     error (EXIT_FAILURE, 0, "crt_sign: %s", gnutls_strerror (result));
840
841   size = buffer_size;
842   result = gnutls_x509_crt_export (crt, info.outcert_format, buffer, &size);
843   if (result < 0)
844     error (EXIT_FAILURE, 0, "crt_export: %s", gnutls_strerror (result));
845
846   fwrite (buffer, 1, size, outfile);
847
848   gnutls_x509_crt_deinit (crt);
849   gnutls_privkey_deinit (key);
850 }
851
852 static void
853 generate_signed_certificate (common_info_st * cinfo)
854 {
855   gnutls_x509_crt_t crt;
856   gnutls_privkey_t key;
857   size_t size;
858   int result;
859   gnutls_privkey_t ca_key;
860   gnutls_x509_crt_t ca_crt;
861
862   fprintf (stderr, "Generating a signed certificate...\n");
863
864   ca_key = load_ca_private_key (cinfo);
865   ca_crt = load_ca_cert (cinfo);
866
867   crt = generate_certificate (&key, ca_crt, 0, cinfo);
868
869   /* Copy the CRL distribution points.
870    */
871   gnutls_x509_crt_cpy_crl_dist_points (crt, ca_crt);
872   /* it doesn't matter if we couldn't copy the CRL dist points.
873    */
874
875   print_certificate_info (crt, stderr, 0);
876
877   fprintf (stderr, "\n\nSigning certificate...\n");
878
879   result = gnutls_x509_crt_privkey_sign (crt, ca_crt, ca_key, get_dig (ca_crt), 0);
880   if (result < 0)
881     error (EXIT_FAILURE, 0, "crt_sign: %s", gnutls_strerror (result));
882
883   size = buffer_size;
884   result = gnutls_x509_crt_export (crt, info.outcert_format, buffer, &size);
885   if (result < 0)
886     error (EXIT_FAILURE, 0, "crt_export: %s", gnutls_strerror (result));
887
888   fwrite (buffer, 1, size, outfile);
889
890   gnutls_x509_crt_deinit (crt);
891   gnutls_privkey_deinit (key);
892   gnutls_privkey_deinit(ca_key);
893 }
894
895 static void
896 generate_proxy_certificate (common_info_st * cinfo)
897 {
898   gnutls_x509_crt_t crt, eecrt;
899   gnutls_privkey_t key, eekey;
900   size_t size;
901   int result;
902
903   fprintf (stderr, "Generating a proxy certificate...\n");
904
905   eekey = load_ca_private_key (cinfo);
906   eecrt = load_cert (1, cinfo);
907
908   crt = generate_certificate (&key, eecrt, 1, cinfo);
909
910   print_certificate_info (crt, stderr, 0);
911
912   fprintf (stderr, "\n\nSigning certificate...\n");
913
914   result = gnutls_x509_crt_privkey_sign (crt, eecrt, eekey, get_dig (eecrt), 0);
915   if (result < 0)
916     error (EXIT_FAILURE, 0, "crt_sign: %s", gnutls_strerror (result));
917
918   size = buffer_size;
919   result = gnutls_x509_crt_export (crt, info.outcert_format, buffer, &size);
920   if (result < 0)
921     error (EXIT_FAILURE, 0, "crt_export: %s", gnutls_strerror (result));
922
923   fwrite (buffer, 1, size, outfile);
924
925   gnutls_x509_crt_deinit (eecrt);
926   gnutls_x509_crt_deinit (crt);
927   gnutls_privkey_deinit (key);
928   gnutls_privkey_deinit (eekey);
929 }
930
931 static void
932 generate_signed_crl (common_info_st * cinfo)
933 {
934   gnutls_x509_crl_t crl;
935   int result;
936   gnutls_privkey_t ca_key;
937   gnutls_x509_crt_t ca_crt;
938
939   fprintf (stderr, "Generating a signed CRL...\n");
940
941   ca_key = load_ca_private_key (cinfo);
942   ca_crt = load_ca_cert (cinfo);
943   crl = generate_crl (ca_crt, cinfo);
944
945   fprintf (stderr, "\n");
946   result = gnutls_x509_crl_privkey_sign(crl, ca_crt, ca_key, SIGN_HASH, 0);
947   if (result < 0)
948     error (EXIT_FAILURE, 0, "crl_privkey_sign: %s", gnutls_strerror (result));
949
950   print_crl_info (crl, stderr);
951
952   gnutls_privkey_deinit( ca_key);
953   gnutls_x509_crl_deinit (crl);
954 }
955
956 static void
957 update_signed_certificate (common_info_st * cinfo)
958 {
959   gnutls_x509_crt_t crt;
960   size_t size;
961   int result;
962   gnutls_privkey_t ca_key;
963   gnutls_x509_crt_t ca_crt;
964   int days;
965   time_t tim = time (NULL);
966
967   fprintf (stderr, "Generating a signed certificate...\n");
968
969   ca_key = load_ca_private_key (cinfo);
970   ca_crt = load_ca_cert (cinfo);
971   crt = load_cert (1, cinfo);
972
973   fprintf (stderr, "Activation/Expiration time.\n");
974   gnutls_x509_crt_set_activation_time (crt, tim);
975
976   days = get_days ();
977
978   result =
979     gnutls_x509_crt_set_expiration_time (crt, tim + days * 24 * 60 * 60);
980   if (result < 0)
981     error (EXIT_FAILURE, 0, "set_expiration: %s", gnutls_strerror (result));
982
983   fprintf (stderr, "\n\nSigning certificate...\n");
984
985   result = gnutls_x509_crt_privkey_sign (crt, ca_crt, ca_key, get_dig (ca_crt), 0);
986   if (result < 0)
987     error (EXIT_FAILURE, 0, "crt_sign: %s", gnutls_strerror (result));
988
989   size = buffer_size;
990   result = gnutls_x509_crt_export (crt, info.outcert_format, buffer, &size);
991   if (result < 0)
992     error (EXIT_FAILURE, 0, "crt_export: %s", gnutls_strerror (result));
993
994   fwrite (buffer, 1, size, outfile);
995
996   gnutls_x509_crt_deinit (crt);
997 }
998
999 void
1000 gaa_parser (int argc, char **argv)
1001 {
1002   int ret;
1003   common_info_st cinfo;
1004
1005   if (gaa (argc, argv, &info) != -1)
1006     {
1007       fprintf (stderr, "Try `%s --help' for more information.\n",
1008                program_name);
1009       exit (1);
1010     }
1011
1012   if (info.outfile)
1013     {
1014       outfile = safe_open_rw (info.outfile, info.privkey_op);
1015       if (outfile == NULL)
1016         error (EXIT_FAILURE, errno, "%s", info.outfile);
1017     }
1018   else
1019     outfile = stdout;
1020
1021   if (info.infile)
1022     {
1023       infile = fopen (info.infile, "rb");
1024       if (infile == NULL)
1025         error (EXIT_FAILURE, errno, "%s", info.infile);
1026     }
1027   else
1028     infile = stdin;
1029
1030   if (info.incert_format)
1031     info.incert_format = GNUTLS_X509_FMT_DER;
1032   else
1033     info.incert_format = GNUTLS_X509_FMT_PEM;
1034
1035   if (info.outcert_format)
1036     info.outcert_format = GNUTLS_X509_FMT_DER;
1037   else
1038     info.outcert_format = GNUTLS_X509_FMT_PEM;
1039
1040   default_dig = GNUTLS_DIG_UNKNOWN;
1041   if (info.hash != NULL)
1042     {
1043       if (strcasecmp (info.hash, "md5") == 0)
1044         {
1045           fprintf (stderr,
1046                    "Warning: MD5 is broken, and should not be used any more for digital signatures.\n");
1047           default_dig = GNUTLS_DIG_MD5;
1048         }
1049       else if (strcasecmp (info.hash, "sha1") == 0)
1050         default_dig = GNUTLS_DIG_SHA1;
1051       else if (strcasecmp (info.hash, "sha256") == 0)
1052         default_dig = GNUTLS_DIG_SHA256;
1053       else if (strcasecmp (info.hash, "sha224") == 0)
1054         default_dig = GNUTLS_DIG_SHA224;
1055       else if (strcasecmp (info.hash, "sha384") == 0)
1056         default_dig = GNUTLS_DIG_SHA384;
1057       else if (strcasecmp (info.hash, "sha512") == 0)
1058         default_dig = GNUTLS_DIG_SHA512;
1059       else if (strcasecmp (info.hash, "rmd160") == 0)
1060         default_dig = GNUTLS_DIG_RMD160;
1061       else
1062         error (EXIT_FAILURE, 0, "invalid hash: %s", info.hash);
1063     }
1064
1065   batch = 0;
1066   if (info.template)
1067     {
1068       batch = 1;
1069       template_parse (info.template);
1070     }
1071
1072   gnutls_global_set_log_function (tls_log_func);
1073   gnutls_global_set_log_level (info.debug);
1074   if (info.debug > 1)
1075     printf ("Setting log level to %d\n", info.debug);
1076
1077   if ((ret = gnutls_global_init ()) < 0)
1078     error (EXIT_FAILURE, 0, "global_init: %s", gnutls_strerror (ret));
1079
1080 #ifdef ENABLE_PKCS11
1081   pkcs11_common();
1082 #endif
1083
1084   memset (&cinfo, 0, sizeof (cinfo));
1085   cinfo.privkey = info.privkey;
1086   cinfo.pubkey = info.pubkey;
1087   cinfo.pkcs8 = info.pkcs8;
1088   cinfo.incert_format = info.incert_format;
1089   cinfo.cert = info.cert;
1090   cinfo.request = info.request;
1091   cinfo.ca = info.ca;
1092   cinfo.ca_privkey = info.ca_privkey;
1093
1094   switch (info.action)
1095     {
1096     case ACTION_SELF_SIGNED:
1097       generate_self_signed (&cinfo);
1098       break;
1099     case ACTION_GENERATE_PRIVKEY:
1100       generate_private_key ();
1101       break;
1102     case ACTION_CERT_INFO:
1103       certificate_info (0, &cinfo);
1104       break;
1105     case ACTION_CERT_PUBKEY:
1106       certificate_info (1, &cinfo);
1107       break;
1108     case ACTION_GENERATE_REQUEST:
1109       generate_request (&cinfo);
1110       break;
1111     case ACTION_GENERATE_CERTIFICATE:
1112       generate_signed_certificate (&cinfo);
1113       break;
1114     case ACTION_VERIFY_CHAIN:
1115       verify_chain ();
1116       break;
1117     case ACTION_PRIVKEY_INFO:
1118       privkey_info ();
1119       break;
1120     case ACTION_PUBKEY_INFO:
1121       pubkey_info (NULL, &cinfo);
1122       break;
1123     case ACTION_UPDATE_CERTIFICATE:
1124       update_signed_certificate (&cinfo);
1125       break;
1126     case ACTION_TO_PKCS12:
1127       generate_pkcs12 (&cinfo);
1128       break;
1129     case ACTION_PKCS12_INFO:
1130       pkcs12_info ();
1131       break;
1132     case ACTION_GENERATE_DH:
1133       generate_prime (1);
1134       break;
1135     case ACTION_GET_DH:
1136       generate_prime (0);
1137       break;
1138     case ACTION_CRL_INFO:
1139       crl_info ();
1140       break;
1141     case ACTION_P7_INFO:
1142       pkcs7_info ();
1143       break;
1144     case ACTION_GENERATE_CRL:
1145       generate_signed_crl (&cinfo);
1146       break;
1147     case ACTION_VERIFY_CRL:
1148       verify_crl (&cinfo);
1149       break;
1150     case ACTION_SMIME_TO_P7:
1151       smime_to_pkcs7 ();
1152       break;
1153     case ACTION_GENERATE_PROXY:
1154       generate_proxy_certificate (&cinfo);
1155       break;
1156     case ACTION_GENERATE_PKCS8:
1157       generate_pkcs8 (&cinfo);
1158       break;
1159 #ifdef ENABLE_OPENPGP
1160     case ACTION_PGP_INFO:
1161       pgp_certificate_info ();
1162       break;
1163     case ACTION_PGP_PRIVKEY_INFO:
1164       pgp_privkey_info ();
1165       break;
1166     case ACTION_RING_INFO:
1167       pgp_ring_info ();
1168       break;
1169 #endif
1170     case ACTION_REQUEST:
1171       crq_info ();
1172       break;
1173     default:
1174       gaa_help ();
1175       exit (0);
1176     }
1177   fclose (outfile);
1178
1179 #ifdef ENABLE_PKCS11
1180   gnutls_pkcs11_deinit ();
1181 #endif
1182   gnutls_global_deinit ();
1183 }
1184
1185 #define MAX_CRTS 500
1186 void
1187 certificate_info (int pubkey, common_info_st * cinfo)
1188 {
1189   gnutls_x509_crt_t crt[MAX_CRTS];
1190   size_t size;
1191   int ret, i, count;
1192   gnutls_datum_t pem;
1193   unsigned int crt_num;
1194
1195   pem.data = fread_file (infile, &size);
1196   pem.size = size;
1197
1198   crt_num = MAX_CRTS;
1199   ret =
1200     gnutls_x509_crt_list_import (crt, &crt_num, &pem, info.incert_format,
1201                                  GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);
1202   if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
1203     {
1204       error (0, 0, "too many certificates (%d); "
1205              "will only read the first %d", crt_num, MAX_CRTS);
1206       crt_num = MAX_CRTS;
1207       ret = gnutls_x509_crt_list_import (crt, &crt_num, &pem,
1208                                          info.incert_format, 0);
1209     }
1210   if (ret < 0)
1211     error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));
1212
1213   free (pem.data);
1214
1215   count = ret;
1216
1217   if (count > 1 && info.outcert_format == GNUTLS_X509_FMT_DER)
1218     {
1219       error (0, 0, "cannot output multiple certificates in DER format; "
1220              "using PEM instead");
1221       info.outcert_format = GNUTLS_X509_FMT_PEM;
1222     }
1223
1224   for (i = 0; i < count; i++)
1225     {
1226       if (i > 0)
1227         fprintf (outfile, "\n");
1228
1229       if (info.outcert_format == GNUTLS_X509_FMT_PEM)
1230         print_certificate_info (crt[i], outfile, 1);
1231
1232       size = buffer_size;
1233       ret = gnutls_x509_crt_export (crt[i], info.outcert_format, buffer,
1234                                     &size);
1235       if (ret < 0)
1236         error (EXIT_FAILURE, 0, "export error: %s", gnutls_strerror (ret));
1237
1238       fwrite (buffer, 1, size, outfile);
1239
1240       if (pubkey)
1241         pubkey_info (crt[i], cinfo);
1242
1243       gnutls_x509_crt_deinit (crt[i]);
1244     }
1245 }
1246
1247 #ifdef ENABLE_OPENPGP
1248
1249 void
1250 pgp_certificate_info (void)
1251 {
1252   gnutls_openpgp_crt_t crt;
1253   size_t size;
1254   int ret;
1255   gnutls_datum_t pem, out_data;
1256   unsigned int verify_status;
1257
1258   pem.data = fread_file (infile, &size);
1259   pem.size = size;
1260
1261   ret = gnutls_openpgp_crt_init (&crt);
1262   if (ret < 0)
1263     error (EXIT_FAILURE, 0, "openpgp_crt_init: %s", gnutls_strerror (ret));
1264
1265   ret = gnutls_openpgp_crt_import (crt, &pem, info.incert_format);
1266
1267   if (ret < 0)
1268     error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));
1269
1270   free (pem.data);
1271
1272   if (info.outcert_format == GNUTLS_OPENPGP_FMT_BASE64)
1273     {
1274       ret = gnutls_openpgp_crt_print (crt, 0, &out_data);
1275
1276       if (ret == 0)
1277         {
1278           fprintf (outfile, "%s\n", out_data.data);
1279           gnutls_free (out_data.data);
1280         }
1281     }
1282
1283
1284   ret = gnutls_openpgp_crt_verify_self (crt, 0, &verify_status);
1285   if (ret < 0)
1286     {
1287       error (EXIT_FAILURE, 0, "verify signature error: %s",
1288              gnutls_strerror (ret));
1289     }
1290
1291   if (verify_status & GNUTLS_CERT_INVALID)
1292     {
1293       fprintf (outfile, "Self Signature verification: failed\n\n");
1294     }
1295   else
1296     {
1297       fprintf (outfile, "Self Signature verification: ok (%x)\n\n",
1298                verify_status);
1299     }
1300
1301   size = buffer_size;
1302   ret = gnutls_openpgp_crt_export (crt, info.outcert_format, buffer, &size);
1303   if (ret < 0)
1304     {
1305       error (EXIT_FAILURE, 0, "export error: %s", gnutls_strerror (ret));
1306       fwrite (buffer, 1, size, outfile);
1307     }
1308
1309   fprintf (outfile, "%s\n", buffer);
1310   gnutls_openpgp_crt_deinit (crt);
1311 }
1312
1313 void
1314 pgp_privkey_info (void)
1315 {
1316   gnutls_openpgp_privkey_t key;
1317   unsigned char keyid[GNUTLS_OPENPGP_KEYID_SIZE];
1318   size_t size;
1319   int ret, i, subkeys;
1320   gnutls_datum_t pem;
1321   const char *cprint;
1322
1323   size = fread (buffer, 1, buffer_size - 1, infile);
1324   buffer[size] = 0;
1325
1326   gnutls_openpgp_privkey_init (&key);
1327
1328   pem.data = buffer;
1329   pem.size = size;
1330
1331   ret = gnutls_openpgp_privkey_import (key, &pem, info.incert_format,
1332                                        NULL, 0);
1333
1334   if (ret < 0)
1335     error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));
1336
1337   /* Public key algorithm
1338    */
1339   subkeys = gnutls_openpgp_privkey_get_subkey_count (key);
1340   if (subkeys < 0)
1341     error (EXIT_FAILURE, 0, "privkey_get_subkey_count: %s",
1342            gnutls_strerror (subkeys));
1343
1344   for (i = -1; i < subkeys; i++)
1345     {
1346
1347       if (i != -1)
1348         fprintf (outfile, "Subkey[%d]:\n", i);
1349
1350       fprintf (outfile, "Public Key Info:\n");
1351
1352       if (i == -1)
1353         ret = gnutls_openpgp_privkey_get_pk_algorithm (key, NULL);
1354       else
1355         ret = gnutls_openpgp_privkey_get_subkey_pk_algorithm (key, i, NULL);
1356
1357       fprintf (outfile, "\tPublic Key Algorithm: ");
1358       cprint = gnutls_pk_algorithm_get_name (ret);
1359       fprintf (outfile, "%s\n", cprint ? cprint : "Unknown");
1360       fprintf (outfile, "\tKey Security Level: %s\n",
1361                gnutls_sec_param_get_name (gnutls_openpgp_privkey_sec_param
1362                                           (key)));
1363
1364       /* Print the raw public and private keys
1365        */
1366
1367       if (ret == GNUTLS_PK_RSA)
1368         {
1369           gnutls_datum_t m, e, d, p, q, u;
1370
1371           if (i == -1)
1372             ret =
1373               gnutls_openpgp_privkey_export_rsa_raw (key, &m, &e, &d, &p,
1374                                                      &q, &u);
1375           else
1376             ret =
1377               gnutls_openpgp_privkey_export_subkey_rsa_raw (key, i, &m,
1378                                                             &e, &d, &p,
1379                                                             &q, &u);
1380           if (ret < 0)
1381             fprintf (stderr, "Error in key RSA data export: %s\n",
1382                      gnutls_strerror (ret));
1383           else
1384             print_rsa_pkey (&m, &e, &d, &p, &q, &u, NULL, NULL);
1385
1386         }
1387       else if (ret == GNUTLS_PK_DSA)
1388         {
1389           gnutls_datum_t p, q, g, y, x;
1390
1391           if (i == -1)
1392             ret =
1393               gnutls_openpgp_privkey_export_dsa_raw (key, &p, &q, &g, &y, &x);
1394           else
1395             ret =
1396               gnutls_openpgp_privkey_export_subkey_dsa_raw (key, i, &p,
1397                                                             &q, &g, &y, &x);
1398           if (ret < 0)
1399             fprintf (stderr, "Error in key DSA data export: %s\n",
1400                      gnutls_strerror (ret));
1401           else
1402             print_dsa_pkey (&x, &y, &p, &q, &g);
1403         }
1404
1405       fprintf (outfile, "\n");
1406
1407       size = buffer_size;
1408       if (i == -1)
1409         ret = gnutls_openpgp_privkey_get_key_id (key, keyid);
1410       else
1411         ret = gnutls_openpgp_privkey_get_subkey_id (key, i, keyid);
1412
1413       if (ret < 0)
1414         {
1415           fprintf (stderr, "Error in key id calculation: %s\n",
1416                    gnutls_strerror (ret));
1417         }
1418       else
1419         {
1420           fprintf (outfile, "Public Key ID: %s\n", raw_to_string (keyid, 8));
1421         }
1422
1423     }
1424
1425   size = buffer_size;
1426   ret = gnutls_openpgp_privkey_export (key, GNUTLS_OPENPGP_FMT_BASE64,
1427                                        NULL, 0, buffer, &size);
1428   if (ret < 0)
1429     error (EXIT_FAILURE, 0, "export error: %s", gnutls_strerror (ret));
1430
1431   fprintf (outfile, "\n%s\n", buffer);
1432
1433   gnutls_openpgp_privkey_deinit (key);
1434 }
1435
1436 void
1437 pgp_ring_info (void)
1438 {
1439   gnutls_openpgp_keyring_t ring;
1440   gnutls_openpgp_crt_t crt;
1441   size_t size;
1442   int ret, i, count;
1443   gnutls_datum_t pem;
1444
1445   pem.data = fread_file (infile, &size);
1446   pem.size = size;
1447
1448   ret = gnutls_openpgp_keyring_init (&ring);
1449   if (ret < 0)
1450     error (EXIT_FAILURE, 0, "openpgp_keyring_init: %s",
1451            gnutls_strerror (ret));
1452
1453   ret = gnutls_openpgp_keyring_import (ring, &pem, info.incert_format);
1454
1455   if (ret < 0)
1456     error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));
1457
1458   free (pem.data);
1459
1460   count = gnutls_openpgp_keyring_get_crt_count (ring);
1461   if (count > 0)
1462     fprintf (outfile, "Keyring contains %d OpenPGP certificates\n\n", count);
1463   else
1464     error (EXIT_FAILURE, 0, "keyring error: %s", gnutls_strerror (count));
1465
1466   for (i = 0; i < count; i++)
1467     {
1468       ret = gnutls_openpgp_keyring_get_crt (ring, i, &crt);
1469       if (ret < 0)
1470         error (EXIT_FAILURE, 0, "export error: %s", gnutls_strerror (ret));
1471
1472       size = buffer_size;
1473       ret = gnutls_openpgp_crt_export (crt, info.outcert_format,
1474                                        buffer, &size);
1475       if (ret < 0)
1476         error (EXIT_FAILURE, 0, "export error: %s", gnutls_strerror (ret));
1477
1478       fwrite (buffer, 1, size, outfile);
1479       fprintf (outfile, "\n\n");
1480
1481       gnutls_openpgp_crt_deinit (crt);
1482
1483
1484     }
1485
1486   gnutls_openpgp_keyring_deinit (ring);
1487 }
1488
1489
1490 #endif
1491
1492 static void
1493 print_hex_datum (gnutls_datum_t * dat)
1494 {
1495   unsigned int j;
1496 #define SPACE "\t"
1497   fprintf (outfile, "\n" SPACE);
1498   for (j = 0; j < dat->size; j++)
1499     {
1500       fprintf (outfile, "%.2x:", (unsigned char) dat->data[j]);
1501       if ((j + 1) % 15 == 0)
1502         fprintf (outfile, "\n" SPACE);
1503     }
1504   fprintf (outfile, "\n");
1505 }
1506
1507
1508 static void
1509 print_certificate_info (gnutls_x509_crt_t crt, FILE * out, unsigned int all)
1510 {
1511   gnutls_datum_t cinfo;
1512   int ret;
1513
1514   if (all)
1515     ret = gnutls_x509_crt_print (crt, GNUTLS_CRT_PRINT_FULL, &cinfo);
1516   else
1517     ret = gnutls_x509_crt_print (crt, GNUTLS_CRT_PRINT_UNSIGNED_FULL, &cinfo);
1518   if (ret == 0)
1519     {
1520       fprintf (out, "%s\n", cinfo.data);
1521       gnutls_free (cinfo.data);
1522     }
1523
1524   if (out == stderr && batch == 0)      /* interactive */
1525     if (read_yesno ("Is the above information ok? (y/N): ") == 0)
1526       {
1527         exit (1);
1528       }
1529 }
1530
1531 static void
1532 print_crl_info (gnutls_x509_crl_t crl, FILE * out)
1533 {
1534   gnutls_datum_t cinfo;
1535   int ret;
1536   size_t size;
1537
1538   ret = gnutls_x509_crl_print (crl, GNUTLS_CRT_PRINT_FULL, &cinfo);
1539   if (ret < 0)
1540     error (EXIT_FAILURE, 0, "crl_print: %s", gnutls_strerror (ret));
1541
1542   fprintf (out, "%s\n", cinfo.data);
1543
1544   gnutls_free (cinfo.data);
1545
1546   size = buffer_size;
1547   ret = gnutls_x509_crl_export (crl, GNUTLS_X509_FMT_PEM, buffer, &size);
1548   if (ret < 0)
1549     error (EXIT_FAILURE, 0, "crl_export: %s", gnutls_strerror (ret));
1550
1551   fwrite (buffer, 1, size, outfile);
1552 }
1553
1554 void
1555 crl_info (void)
1556 {
1557   gnutls_x509_crl_t crl;
1558   int ret;
1559   size_t size;
1560   gnutls_datum_t pem;
1561
1562   ret = gnutls_x509_crl_init (&crl);
1563   if (ret < 0)
1564     error (EXIT_FAILURE, 0, "crl_init: %s", gnutls_strerror (ret));
1565
1566   pem.data = fread_file (infile, &size);
1567   pem.size = size;
1568
1569   if (!pem.data)
1570     error (EXIT_FAILURE, errno, "%s", info.infile ? info.infile :
1571            "standard input");
1572
1573   ret = gnutls_x509_crl_import (crl, &pem, info.incert_format);
1574
1575   free (pem.data);
1576   if (ret < 0)
1577     error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));
1578
1579   print_crl_info (crl, outfile);
1580
1581   gnutls_x509_crl_deinit (crl);
1582 }
1583
1584 static void
1585 print_crq_info (gnutls_x509_crq_t crq, FILE * out)
1586 {
1587   gnutls_datum_t cinfo;
1588   int ret;
1589   size_t size;
1590
1591   if (info.outcert_format == GNUTLS_X509_FMT_PEM)
1592     {
1593       ret = gnutls_x509_crq_print (crq, GNUTLS_CRT_PRINT_FULL, &cinfo);
1594       if (ret < 0)
1595         error (EXIT_FAILURE, 0, "crq_print: %s", gnutls_strerror (ret));
1596
1597       fprintf (out, "%s\n", cinfo.data);
1598
1599       gnutls_free (cinfo.data);
1600     }
1601
1602   size = buffer_size;
1603   ret = gnutls_x509_crq_export (crq, info.outcert_format, buffer, &size);
1604   if (ret < 0)
1605     error (EXIT_FAILURE, 0, "crq_export: %s", gnutls_strerror (ret));
1606
1607   fwrite (buffer, 1, size, outfile);
1608 }
1609
1610 void
1611 crq_info (void)
1612 {
1613   gnutls_x509_crq_t crq;
1614   int ret;
1615   size_t size;
1616   gnutls_datum_t pem;
1617
1618   ret = gnutls_x509_crq_init (&crq);
1619   if (ret < 0)
1620     error (EXIT_FAILURE, 0, "crq_init: %s", gnutls_strerror (ret));
1621
1622   pem.data = fread_file (infile, &size);
1623   pem.size = size;
1624
1625   if (!pem.data)
1626     error (EXIT_FAILURE, errno, "%s", info.infile ? info.infile :
1627            "standard input");
1628
1629   ret = gnutls_x509_crq_import (crq, &pem, info.incert_format);
1630
1631   free (pem.data);
1632   if (ret < 0)
1633     error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));
1634
1635   print_crq_info (crq, outfile);
1636
1637   gnutls_x509_crq_deinit (crq);
1638 }
1639
1640 void
1641 privkey_info (void)
1642 {
1643   gnutls_x509_privkey_t key;
1644   size_t size;
1645   int ret;
1646   gnutls_datum_t pem;
1647   const char *cprint;
1648   const char *pass;
1649
1650   size = fread (buffer, 1, buffer_size - 1, infile);
1651   buffer[size] = 0;
1652
1653   gnutls_x509_privkey_init (&key);
1654
1655   pem.data = buffer;
1656   pem.size = size;
1657
1658   ret = 0;
1659   if (!info.pkcs8)
1660     ret = gnutls_x509_privkey_import (key, &pem, info.incert_format);
1661
1662   /* If we failed to import the certificate previously try PKCS #8 */
1663   if (info.pkcs8 || ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
1664     {
1665       if (info.pass)
1666         pass = info.pass;
1667       else
1668         pass = get_pass ();
1669       ret = gnutls_x509_privkey_import_pkcs8 (key, &pem,
1670                                               info.incert_format, pass, 0);
1671     }
1672   if (ret < 0)
1673     error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));
1674
1675   /* Public key algorithm
1676    */
1677   fprintf (outfile, "Public Key Info:\n");
1678   ret = gnutls_x509_privkey_get_pk_algorithm (key);
1679   fprintf (outfile, "\tPublic Key Algorithm: ");
1680
1681   cprint = gnutls_pk_algorithm_get_name (ret);
1682   fprintf (outfile, "%s\n", cprint ? cprint : "Unknown");
1683   fprintf (outfile, "\tKey Security Level: %s\n",
1684            gnutls_sec_param_get_name (gnutls_x509_privkey_sec_param (key)));
1685
1686   /* Print the raw public and private keys
1687    */
1688   if (ret == GNUTLS_PK_RSA)
1689     {
1690       gnutls_datum_t m, e, d, p, q, u, exp1, exp2;
1691
1692       ret =
1693         gnutls_x509_privkey_export_rsa_raw2 (key, &m, &e, &d, &p, &q, &u,
1694                                              &exp1, &exp2);
1695       if (ret < 0)
1696         fprintf (stderr, "Error in key RSA data export: %s\n",
1697                  gnutls_strerror (ret));
1698       else
1699         {
1700           print_rsa_pkey (&m, &e, &d, &p, &q, &u, &exp1, &exp2);
1701           gnutls_free (m.data);
1702           gnutls_free (e.data);
1703           gnutls_free (d.data);
1704           gnutls_free (p.data);
1705           gnutls_free (q.data);
1706           gnutls_free (u.data);
1707           gnutls_free (exp1.data);
1708           gnutls_free (exp2.data);
1709         }
1710     }
1711   else if (ret == GNUTLS_PK_DSA)
1712     {
1713       gnutls_datum_t p, q, g, y, x;
1714
1715       ret = gnutls_x509_privkey_export_dsa_raw (key, &p, &q, &g, &y, &x);
1716       if (ret < 0)
1717         fprintf (stderr, "Error in key DSA data export: %s\n",
1718                  gnutls_strerror (ret));
1719       else
1720         {
1721           print_dsa_pkey (&x, &y, &p, &q, &g);
1722           gnutls_free (x.data);
1723           gnutls_free (y.data);
1724           gnutls_free (p.data);
1725           gnutls_free (q.data);
1726           gnutls_free (g.data);
1727         }
1728     }
1729
1730   fprintf (outfile, "\n");
1731
1732   size = buffer_size;
1733   if ((ret = gnutls_x509_privkey_get_key_id (key, 0, buffer, &size)) < 0)
1734     {
1735       fprintf (stderr, "Error in key id calculation: %s\n",
1736                gnutls_strerror (ret));
1737     }
1738   else
1739     {
1740       fprintf (outfile, "Public Key ID: %s\n", raw_to_string (buffer, size));
1741     }
1742
1743   if (info.fix_key != 0)
1744     {
1745       ret = gnutls_x509_privkey_fix (key);
1746       if (ret < 0)
1747         error (EXIT_FAILURE, 0, "privkey_fix: %s", gnutls_strerror (ret));
1748     }
1749
1750   size = buffer_size;
1751   ret = gnutls_x509_privkey_export (key, GNUTLS_X509_FMT_PEM, buffer, &size);
1752   if (ret < 0)
1753     error (EXIT_FAILURE, 0, "export error: %s", gnutls_strerror (ret));
1754
1755   fprintf (outfile, "\n%s\n", buffer);
1756
1757   gnutls_x509_privkey_deinit (key);
1758 }
1759
1760
1761 /* Generate a PKCS #10 certificate request.
1762  */
1763 void
1764 generate_request (common_info_st * cinfo)
1765 {
1766   gnutls_x509_crq_t crq;
1767   gnutls_x509_privkey_t xkey;
1768   gnutls_pubkey_t pubkey;
1769   gnutls_privkey_t pkey;
1770   int ret, ca_status, path_len;
1771   const char *pass;
1772   unsigned int usage = 0;
1773
1774   fprintf (stderr, "Generating a PKCS #10 certificate request...\n");
1775
1776   ret = gnutls_x509_crq_init (&crq);
1777   if (ret < 0)
1778     error (EXIT_FAILURE, 0, "crq_init: %s", gnutls_strerror (ret));
1779
1780
1781   /* Load the private key.
1782    */
1783   pkey = load_private_key (0, cinfo);
1784   if (!pkey)
1785     {
1786       ret = gnutls_privkey_init (&pkey);
1787       if (ret < 0)
1788         error (EXIT_FAILURE, 0, "privkey_init: %s", gnutls_strerror (ret));
1789
1790       xkey = generate_private_key_int ();
1791
1792       print_private_key (xkey);
1793
1794       ret = gnutls_privkey_import_x509(pkey, xkey, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
1795       if (ret < 0)
1796         error (EXIT_FAILURE, 0, "privkey_import_x509: %s", gnutls_strerror (ret));
1797     }
1798
1799   pubkey = load_public_key_or_import (1, pkey, cinfo);
1800
1801   /* Set the DN.
1802    */
1803   get_country_crq_set (crq);
1804   get_organization_crq_set (crq);
1805   get_unit_crq_set (crq);
1806   get_locality_crq_set (crq);
1807   get_state_crq_set (crq);
1808   get_cn_crq_set (crq);
1809   get_uid_crq_set (crq);
1810   get_oid_crq_set (crq);
1811
1812   get_dns_name_set (TYPE_CRQ, crq);
1813   get_ip_addr_set (TYPE_CRQ, crq);
1814   get_email_set (TYPE_CRQ, crq);
1815
1816   pass = get_challenge_pass ();
1817
1818   if (pass != NULL && pass[0] != 0)
1819     {
1820       ret = gnutls_x509_crq_set_challenge_password (crq, pass);
1821       if (ret < 0)
1822         error (EXIT_FAILURE, 0, "set_pass: %s", gnutls_strerror (ret));
1823     }
1824
1825   if (info.crq_extensions != 0)
1826     {
1827       ca_status = get_ca_status ();
1828       if (ca_status)
1829         path_len = get_path_len ();
1830       else
1831         path_len = -1;
1832
1833       ret = gnutls_x509_crq_set_basic_constraints (crq, ca_status, path_len);
1834       if (ret < 0)
1835         error (EXIT_FAILURE, 0, "set_basic_constraints: %s",
1836                gnutls_strerror (ret));
1837
1838       ret = get_sign_status (1);
1839       if (ret)
1840         usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
1841
1842       ret = get_encrypt_status (1);
1843       if (ret)
1844         usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
1845       else
1846         usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
1847
1848       if (ca_status)
1849         {
1850           ret = get_cert_sign_status ();
1851           if (ret)
1852             usage |= GNUTLS_KEY_KEY_CERT_SIGN;
1853
1854           ret = get_crl_sign_status ();
1855           if (ret)
1856             usage |= GNUTLS_KEY_CRL_SIGN;
1857
1858           ret = get_code_sign_status ();
1859           if (ret)
1860             {
1861               ret = gnutls_x509_crq_set_key_purpose_oid
1862                 (crq, GNUTLS_KP_CODE_SIGNING, 0);
1863               if (ret < 0)
1864                 error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (ret));
1865             }
1866
1867           ret = get_ocsp_sign_status ();
1868           if (ret)
1869             {
1870               ret = gnutls_x509_crq_set_key_purpose_oid
1871                 (crq, GNUTLS_KP_OCSP_SIGNING, 0);
1872               if (ret < 0)
1873                 error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (ret));
1874             }
1875
1876           ret = get_time_stamp_status ();
1877           if (ret)
1878             {
1879               ret = gnutls_x509_crq_set_key_purpose_oid
1880                 (crq, GNUTLS_KP_TIME_STAMPING, 0);
1881               if (ret < 0)
1882                 error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (ret));
1883             }
1884
1885           ret = get_ipsec_ike_status ();
1886           if (ret)
1887             {
1888               ret = gnutls_x509_crq_set_key_purpose_oid
1889                 (crq, GNUTLS_KP_IPSEC_IKE, 0);
1890               if (ret < 0)
1891                 error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (ret));
1892             }
1893         }
1894
1895       ret = gnutls_x509_crq_set_key_usage (crq, usage);
1896       if (ret < 0)
1897         error (EXIT_FAILURE, 0, "key_usage: %s", gnutls_strerror (ret));
1898
1899       ret = get_tls_client_status ();
1900       if (ret != 0)
1901         {
1902           ret = gnutls_x509_crq_set_key_purpose_oid
1903             (crq, GNUTLS_KP_TLS_WWW_CLIENT, 0);
1904           if (ret < 0)
1905             error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (ret));
1906         }
1907
1908       ret = get_tls_server_status ();
1909       if (ret != 0)
1910         {
1911           ret = gnutls_x509_crq_set_key_purpose_oid
1912             (crq, GNUTLS_KP_TLS_WWW_SERVER, 0);
1913           if (ret < 0)
1914             error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (ret));
1915         }
1916     }
1917
1918   ret = gnutls_x509_crq_set_pubkey (crq, pubkey);
1919   if (ret < 0)
1920     error (EXIT_FAILURE, 0, "set_key: %s", gnutls_strerror (ret));
1921
1922   ret = gnutls_x509_crq_privkey_sign (crq, pkey, SIGN_HASH, 0);
1923   if (ret < 0)
1924     error (EXIT_FAILURE, 0, "sign: %s", gnutls_strerror (ret));
1925
1926   print_crq_info (crq, outfile);
1927
1928   gnutls_x509_crq_deinit (crq);
1929   gnutls_privkey_deinit( pkey);
1930   gnutls_pubkey_deinit( pubkey);
1931
1932 }
1933
1934 static void print_verification_res (gnutls_x509_crt_t crt,
1935                                     gnutls_x509_crt_t issuer,
1936                                     gnutls_x509_crl_t * crl_list,
1937                                     int crl_list_size, unsigned int flags);
1938
1939 #define CERT_SEP "-----BEGIN CERT"
1940 #define CRL_SEP "-----BEGIN X509 CRL"
1941 static int
1942 _verify_x509_mem (const void *cert, int cert_size)
1943 {
1944   const char *ptr;
1945   int ret, i;
1946   char name[512];
1947   char issuer_name[512];
1948   size_t name_size;
1949   size_t issuer_name_size;
1950   gnutls_datum_t tmp;
1951   gnutls_x509_crt_t *x509_cert_list = NULL;
1952   gnutls_x509_crl_t *x509_crl_list = NULL;
1953   int x509_ncerts, x509_ncrls;
1954
1955
1956   /* Decode the CA certificate
1957    */
1958
1959   /* Decode the CRL list
1960    */
1961   ptr = cert;
1962
1963   i = 1;
1964
1965   if (strstr (ptr, CRL_SEP) != NULL)    /* if CRLs exist */
1966     do
1967       {
1968         x509_crl_list =
1969           (gnutls_x509_crl_t *) realloc (x509_crl_list,
1970                                          i * sizeof (gnutls_x509_crl_t));
1971         if (x509_crl_list == NULL)
1972           error (EXIT_FAILURE, 0, "memory error");
1973
1974         tmp.data = (char *) ptr;
1975         tmp.size = cert_size;
1976         tmp.size -=
1977           (unsigned int) ((unsigned char *) ptr - (unsigned char *) cert);
1978
1979         ret = gnutls_x509_crl_init (&x509_crl_list[i - 1]);
1980         if (ret < 0)
1981           error (EXIT_FAILURE, 0, "error parsing CRL[%d]: %s", i,
1982                  gnutls_strerror (ret));
1983
1984         ret = gnutls_x509_crl_import (x509_crl_list[i - 1], &tmp,
1985                                       GNUTLS_X509_FMT_PEM);
1986         if (ret < 0)
1987           error (EXIT_FAILURE, 0, "error parsing CRL[%d]: %s", i,
1988                  gnutls_strerror (ret));
1989
1990         /* now we move ptr after the pem header */
1991         ptr = strstr (ptr, CRL_SEP);
1992         if (ptr != NULL)
1993           ptr++;
1994
1995         i++;
1996       }
1997     while ((ptr = strstr (ptr, CRL_SEP)) != NULL);
1998
1999   x509_ncrls = i - 1;
2000
2001
2002   /* Decode the certificate chain. 
2003    */
2004   ptr = cert;
2005
2006   i = 1;
2007
2008   do
2009     {
2010       x509_cert_list =
2011         (gnutls_x509_crt_t *) realloc (x509_cert_list,
2012                                        i * sizeof (gnutls_x509_crt_t));
2013       if (x509_cert_list == NULL)
2014         error (EXIT_FAILURE, 0, "memory error");
2015
2016
2017       tmp.data = (char *) ptr;
2018       tmp.size = cert_size;
2019       tmp.size -=
2020         (unsigned int) ((unsigned char *) ptr - (unsigned char *) cert);
2021
2022       ret = gnutls_x509_crt_init (&x509_cert_list[i - 1]);
2023       if (ret < 0)
2024         error (EXIT_FAILURE, 0, "error parsing certificate[%d]: %s", i,
2025                gnutls_strerror (ret));
2026
2027       ret =
2028         gnutls_x509_crt_import (x509_cert_list[i - 1], &tmp,
2029                                 GNUTLS_X509_FMT_PEM);
2030       if (ret < 0)
2031         error (EXIT_FAILURE, 0, "error parsing certificate[%d]: %s", i,
2032                gnutls_strerror (ret));
2033
2034
2035       if (i - 1 != 0)
2036         {
2037           /* verify the previous certificate using this one 
2038            * as CA.
2039            */
2040
2041           name_size = sizeof (name);
2042           ret =
2043             gnutls_x509_crt_get_dn (x509_cert_list[i - 2], name, &name_size);
2044           if (ret < 0)
2045             error (EXIT_FAILURE, 0, "get_dn: %s", gnutls_strerror (ret));
2046
2047           fprintf (outfile, "Certificate[%d]: %s\n", i - 2, name);
2048
2049           /* print issuer 
2050            */
2051           issuer_name_size = sizeof (issuer_name);
2052           ret =
2053             gnutls_x509_crt_get_issuer_dn (x509_cert_list[i - 2],
2054                                            issuer_name, &issuer_name_size);
2055           if (ret < 0)
2056             error (EXIT_FAILURE, 0, "get_issuer_dn: %s",
2057                    gnutls_strerror (ret));
2058
2059           fprintf (outfile, "\tIssued by: %s\n", issuer_name);
2060
2061           /* Get the Issuer's name
2062            */
2063           name_size = sizeof (name);
2064           ret =
2065             gnutls_x509_crt_get_dn (x509_cert_list[i - 1], name, &name_size);
2066           if (ret < 0)
2067             error (EXIT_FAILURE, 0, "get_dn: %s", gnutls_strerror (ret));
2068
2069           fprintf (outfile, "\tVerifying against certificate[%d].\n", i - 1);
2070
2071           if (strcmp (issuer_name, name) != 0)
2072             {
2073               fprintf (stderr, "Error: Issuer's name: %s\n", name);
2074               error (EXIT_FAILURE, 0,
2075                      "issuer name does not match the next certificate");
2076             }
2077
2078           fprintf (outfile, "\tVerification output: ");
2079           print_verification_res (x509_cert_list[i - 2],
2080                                   x509_cert_list[i - 1], x509_crl_list,
2081                                   x509_ncrls,
2082                                   GNUTLS_VERIFY_DO_NOT_ALLOW_SAME);
2083           fprintf (outfile, ".\n\n");
2084
2085         }
2086
2087
2088       /* now we move ptr after the pem header 
2089        */
2090       ptr = strstr (ptr, CERT_SEP);
2091       if (ptr != NULL)
2092         ptr++;
2093
2094       i++;
2095     }
2096   while ((ptr = strstr (ptr, CERT_SEP)) != NULL);
2097
2098   x509_ncerts = i - 1;
2099
2100   /* The last certificate in the list will be used as
2101    * a CA (should be self signed).
2102    */
2103   name_size = sizeof (name);
2104   ret = gnutls_x509_crt_get_dn (x509_cert_list[x509_ncerts - 1], name,
2105                                 &name_size);
2106   if (ret < 0)
2107     error (EXIT_FAILURE, 0, "get_dn: %s", gnutls_strerror (ret));
2108
2109   fprintf (outfile, "Certificate[%d]: %s\n", x509_ncerts - 1, name);
2110
2111   /* print issuer 
2112    */
2113   issuer_name_size = sizeof (issuer_name);
2114   ret =
2115     gnutls_x509_crt_get_issuer_dn (x509_cert_list[x509_ncerts - 1],
2116                                    issuer_name, &issuer_name_size);
2117   if (ret < 0)
2118     error (EXIT_FAILURE, 0, "get_issuer_dn: %s", gnutls_strerror (ret));
2119
2120   fprintf (outfile, "\tIssued by: %s\n", name);
2121
2122   if (strcmp (issuer_name, name) != 0)
2123     error (EXIT_FAILURE, 0, "the last certificate is not self signed");
2124
2125   fprintf (outfile, "\tVerification output: ");
2126   print_verification_res (x509_cert_list[x509_ncerts - 1],
2127                           x509_cert_list[x509_ncerts - 1], x509_crl_list,
2128                           /* we add GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT since it is
2129                            * self signed. */
2130                           x509_ncrls,
2131                           GNUTLS_VERIFY_DO_NOT_ALLOW_SAME |
2132                           GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
2133
2134   fprintf (outfile, ".\n\n");
2135
2136   /* Verify using internal algorithm too. */
2137   {
2138     int verify_status;
2139
2140     ret = gnutls_x509_crt_list_verify (x509_cert_list, x509_ncerts,
2141                                        &x509_cert_list[x509_ncerts - 1], 1,
2142                                        x509_crl_list,
2143                                        x509_ncrls,
2144                                        GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT |
2145                                        GNUTLS_VERIFY_DO_NOT_ALLOW_SAME,
2146                                        &verify_status);
2147     if (ret < 0)
2148       error (EXIT_FAILURE, 0, "gnutls_x509_crt_list_verify: %s",
2149              gnutls_strerror (ret));
2150
2151     fprintf (outfile, "Chain verification output: ");
2152
2153     if (verify_status & GNUTLS_CERT_INVALID)
2154       {
2155         fprintf (outfile, "Not verified");
2156       }
2157     else
2158       {
2159         fprintf (outfile, "Verified");
2160       }
2161
2162     if (verify_status & GNUTLS_CERT_SIGNER_NOT_CA)
2163       {
2164         fprintf (outfile, ", ");
2165         fprintf (outfile, "Issuer is not a CA");
2166       }
2167
2168     if (verify_status & GNUTLS_CERT_INSECURE_ALGORITHM)
2169       {
2170         fprintf (outfile, ", ");
2171         fprintf (outfile, "Insecure algorithm");
2172       }
2173
2174     fprintf (outfile, ".\n");
2175   }
2176
2177   for (i = 0; i < x509_ncerts; i++)
2178     gnutls_x509_crt_deinit (x509_cert_list[i]);
2179
2180   for (i = 0; i < x509_ncrls; i++)
2181     gnutls_x509_crl_deinit (x509_crl_list[i]);
2182
2183   free (x509_cert_list);
2184   free (x509_crl_list);
2185
2186   if (ret < 0)
2187     error (EXIT_FAILURE, 0, "verification error: %s", gnutls_strerror (ret));
2188
2189   return 0;
2190 }
2191
2192 static void
2193 print_verification_res (gnutls_x509_crt_t crt,
2194                         gnutls_x509_crt_t issuer,
2195                         gnutls_x509_crl_t * crl_list, int crl_list_size,
2196                         unsigned int flags)
2197 {
2198   unsigned int output;
2199   int comma = 0;
2200   int ret;
2201
2202   ret = gnutls_x509_crt_verify (crt, &issuer, 1, flags, &output);
2203   if (ret < 0)
2204     error (EXIT_FAILURE, 0, "verification error: %s", gnutls_strerror (ret));
2205
2206   if (output & GNUTLS_CERT_INVALID)
2207     {
2208       fprintf (outfile, "Not verified");
2209       comma = 1;
2210     }
2211   else
2212     {
2213       fprintf (outfile, "Verified");
2214       comma = 1;
2215     }
2216
2217   if (output & GNUTLS_CERT_SIGNER_NOT_CA)
2218     {
2219       if (comma)
2220         fprintf (outfile, ", ");
2221       fprintf (outfile, "Issuer is not a CA");
2222       comma = 1;
2223     }
2224
2225   if (output & GNUTLS_CERT_INSECURE_ALGORITHM)
2226     {
2227       if (comma)
2228         fprintf (outfile, ", ");
2229       fprintf (outfile, "Insecure algorithm");
2230       comma = 1;
2231     }
2232
2233   if (output & GNUTLS_CERT_NOT_ACTIVATED)
2234     {
2235       if (comma)
2236         fprintf (outfile, ", ");
2237       fprintf (outfile, "Not activated");
2238       comma = 1;
2239     }
2240
2241   if (output & GNUTLS_CERT_EXPIRED)
2242     {
2243       if (comma)
2244         fprintf (outfile, ", ");
2245       fprintf (outfile, "Expired");
2246       comma = 1;
2247     }
2248
2249   ret = gnutls_x509_crt_check_revocation (crt, crl_list, crl_list_size);
2250   if (ret < 0)
2251     error (EXIT_FAILURE, 0, "revocation check: %s", gnutls_strerror (ret));
2252
2253   if (ret == 1)
2254     {                           /* revoked */
2255       if (comma)
2256         fprintf (outfile, ", ");
2257       comma = 1;
2258       fprintf (outfile, "Revoked");
2259     }
2260 }
2261
2262 void
2263 verify_chain (void)
2264 {
2265   char *buf;
2266   size_t size;
2267
2268   buf = fread_file (infile, &size);
2269   if (buf == NULL)
2270     error (EXIT_FAILURE, errno, "reading chain");
2271
2272   buf[size] = 0;
2273
2274   _verify_x509_mem (buf, size);
2275
2276 }
2277
2278 void
2279 verify_crl (common_info_st * cinfo)
2280 {
2281   size_t size, dn_size;
2282   char dn[128];
2283   unsigned int output;
2284   int comma = 0;
2285   int ret;
2286   gnutls_datum_t pem;
2287   gnutls_x509_crl_t crl;
2288   time_t now = time (0);
2289   gnutls_x509_crt_t issuer;
2290
2291   issuer = load_ca_cert (cinfo);
2292
2293   fprintf (outfile, "\nCA certificate:\n");
2294
2295   dn_size = sizeof (dn);
2296   ret = gnutls_x509_crt_get_dn (issuer, dn, &dn_size);
2297   if (ret < 0)
2298     error (EXIT_FAILURE, 0, "crt_get_dn: %s", gnutls_strerror (ret));
2299
2300   fprintf (outfile, "\tSubject: %s\n\n", dn);
2301
2302   ret = gnutls_x509_crl_init (&crl);
2303   if (ret < 0)
2304     error (EXIT_FAILURE, 0, "crl_init: %s", gnutls_strerror (ret));
2305
2306   pem.data = fread_file (infile, &size);
2307   pem.size = size;
2308
2309   ret = gnutls_x509_crl_import (crl, &pem, info.incert_format);
2310   free (pem.data);
2311   if (ret < 0)
2312     error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));
2313
2314   print_crl_info (crl, outfile);
2315
2316   fprintf (outfile, "Verification output: ");
2317   ret = gnutls_x509_crl_verify (crl, &issuer, 1, 0, &output);
2318   if (ret < 0)
2319     error (EXIT_FAILURE, 0, "verification error: %s", gnutls_strerror (ret));
2320
2321   if (output & GNUTLS_CERT_INVALID)
2322     {
2323       fprintf (outfile, "Not verified");
2324       comma = 1;
2325     }
2326   else
2327     {
2328       fprintf (outfile, "Verified");
2329       comma = 1;
2330     }
2331
2332   if (output & GNUTLS_CERT_SIGNER_NOT_CA)
2333     {
2334       if (comma)
2335         fprintf (outfile, ", ");
2336       fprintf (outfile, "Issuer is not a CA");
2337       comma = 1;
2338     }
2339
2340   if (output & GNUTLS_CERT_INSECURE_ALGORITHM)
2341     {
2342       if (comma)
2343         fprintf (outfile, ", ");
2344       fprintf (outfile, "Insecure algorithm");
2345       comma = 1;
2346     }
2347
2348   /* Check expiration dates.
2349    */
2350
2351   if (gnutls_x509_crl_get_this_update (crl) > now)
2352     {
2353       if (comma)
2354         fprintf (outfile, ", ");
2355       comma = 1;
2356       fprintf (outfile, "Issued in the future!");
2357     }
2358
2359   if (gnutls_x509_crl_get_next_update (crl) < now)
2360     {
2361       if (comma)
2362         fprintf (outfile, ", ");
2363       comma = 1;
2364       fprintf (outfile, "CRL is not up to date");
2365     }
2366
2367   fprintf (outfile, "\n");
2368 }
2369
2370
2371 void
2372 generate_pkcs8 (common_info_st * cinfo)
2373 {
2374   gnutls_x509_privkey_t key;
2375   int result;
2376   size_t size;
2377   int flags = 0;
2378   const char *password;
2379
2380   fprintf (stderr, "Generating a PKCS #8 key structure...\n");
2381
2382   key = load_x509_private_key (1, cinfo);
2383
2384   if (info.pass)
2385     password = info.pass;
2386   else
2387     password = get_pass ();
2388
2389   if (info.export)
2390     flags = GNUTLS_PKCS_USE_PKCS12_RC2_40;
2391   else
2392     flags = cipher_to_flags (info.pkcs_cipher);
2393
2394   if (password == NULL || password[0] == 0)
2395     {
2396       flags = GNUTLS_PKCS_PLAIN;
2397     }
2398
2399   size = buffer_size;
2400   result =
2401     gnutls_x509_privkey_export_pkcs8 (key, info.outcert_format,
2402                                       password, flags, buffer, &size);
2403
2404   if (result < 0)
2405     error (EXIT_FAILURE, 0, "key_export: %s", gnutls_strerror (result));
2406
2407   fwrite (buffer, 1, size, outfile);
2408
2409 }
2410
2411
2412 #include <gnutls/pkcs12.h>
2413 #include <unistd.h>
2414
2415 void
2416 generate_pkcs12 (common_info_st * cinfo)
2417 {
2418   gnutls_pkcs12_t pkcs12;
2419   gnutls_x509_crt_t *crts;
2420   gnutls_x509_privkey_t key;
2421   int result;
2422   size_t size;
2423   gnutls_datum_t data;
2424   const char *pass;
2425   const char *name;
2426   unsigned int flags, i;
2427   gnutls_datum_t key_id;
2428   unsigned char _key_id[20];
2429   int indx;
2430   size_t ncrts;
2431
2432   fprintf (stderr, "Generating a PKCS #12 structure...\n");
2433
2434   key = load_x509_private_key (0, cinfo);
2435   crts = load_cert_list (0, &ncrts, cinfo);
2436
2437   name = get_pkcs12_key_name ();
2438
2439   result = gnutls_pkcs12_init (&pkcs12);
2440   if (result < 0)
2441     error (EXIT_FAILURE, 0, "pkcs12_init: %s", gnutls_strerror (result));
2442
2443   if (info.pass)
2444     pass = info.pass;
2445   else
2446     pass = get_pass ();
2447     
2448   if (pass == NULL)
2449     {
2450       fprintf(stderr, "No password given for PKCS #12. Assuming null password...\n");
2451       pass = "";
2452     }
2453     
2454
2455   for (i = 0; i < ncrts; i++)
2456     {
2457       gnutls_pkcs12_bag_t bag;
2458
2459       result = gnutls_pkcs12_bag_init (&bag);
2460       if (result < 0)
2461         error (EXIT_FAILURE, 0, "bag_init: %s", gnutls_strerror (result));
2462
2463       result = gnutls_pkcs12_bag_set_crt (bag, crts[i]);
2464       if (result < 0)
2465         error (EXIT_FAILURE, 0, "set_crt[%d]: %s", i,
2466                gnutls_strerror (result));
2467
2468       indx = result;
2469
2470       result = gnutls_pkcs12_bag_set_friendly_name (bag, indx, name);
2471       if (result < 0)
2472         error (EXIT_FAILURE, 0, "bag_set_friendly_name: %s",
2473                gnutls_strerror (result));
2474
2475       size = sizeof (_key_id);
2476       result = gnutls_x509_crt_get_key_id (crts[i], 0, _key_id, &size);
2477       if (result < 0)
2478         error (EXIT_FAILURE, 0, "key_id[%d]: %s", i,
2479                gnutls_strerror (result));
2480
2481       key_id.data = _key_id;
2482       key_id.size = size;
2483
2484       result = gnutls_pkcs12_bag_set_key_id (bag, indx, &key_id);
2485       if (result < 0)
2486         error (EXIT_FAILURE, 0, "bag_set_key_id: %s",
2487                gnutls_strerror (result));
2488
2489       if (info.export)
2490         flags = GNUTLS_PKCS_USE_PKCS12_RC2_40;
2491       else
2492         flags = cipher_to_flags (info.pkcs_cipher);
2493
2494       result = gnutls_pkcs12_bag_encrypt (bag, pass, flags);
2495       if (result < 0)
2496         error (EXIT_FAILURE, 0, "bag_encrypt: %s", gnutls_strerror (result));
2497
2498       result = gnutls_pkcs12_set_bag (pkcs12, bag);
2499       if (result < 0)
2500         error (EXIT_FAILURE, 0, "set_bag: %s", gnutls_strerror (result));
2501     }
2502
2503   if (key)
2504     {
2505       gnutls_pkcs12_bag_t kbag;
2506
2507       result = gnutls_pkcs12_bag_init (&kbag);
2508       if (result < 0)
2509         error (EXIT_FAILURE, 0, "bag_init: %s", gnutls_strerror (result));
2510
2511       if (info.export)
2512         flags = GNUTLS_PKCS_USE_PKCS12_RC2_40;
2513       else
2514         flags = cipher_to_flags (info.pkcs_cipher);
2515
2516       size = buffer_size;
2517       result =
2518         gnutls_x509_privkey_export_pkcs8 (key, GNUTLS_X509_FMT_DER,
2519                                           pass, flags, buffer, &size);
2520       if (result < 0)
2521         error (EXIT_FAILURE, 0, "key_export: %s", gnutls_strerror (result));
2522
2523       data.data = buffer;
2524       data.size = size;
2525       result =
2526         gnutls_pkcs12_bag_set_data (kbag,
2527                                     GNUTLS_BAG_PKCS8_ENCRYPTED_KEY, &data);
2528       if (result < 0)
2529         error (EXIT_FAILURE, 0, "bag_set_data: %s", gnutls_strerror (result));
2530
2531       indx = result;
2532
2533       result = gnutls_pkcs12_bag_set_friendly_name (kbag, indx, name);
2534       if (result < 0)
2535         error (EXIT_FAILURE, 0, "bag_set_friendly_name: %s",
2536                gnutls_strerror (result));
2537
2538       size = sizeof (_key_id);
2539       result = gnutls_x509_privkey_get_key_id (key, 0, _key_id, &size);
2540       if (result < 0)
2541         error (EXIT_FAILURE, 0, "key_id: %s", gnutls_strerror (result));
2542
2543       key_id.data = _key_id;
2544       key_id.size = size;
2545
2546       result = gnutls_pkcs12_bag_set_key_id (kbag, indx, &key_id);
2547       if (result < 0)
2548         error (EXIT_FAILURE, 0, "bag_set_key_id: %s",
2549                gnutls_strerror (result));
2550
2551       result = gnutls_pkcs12_set_bag (pkcs12, kbag);
2552       if (result < 0)
2553         error (EXIT_FAILURE, 0, "set_bag: %s", gnutls_strerror (result));
2554     }
2555
2556   result = gnutls_pkcs12_generate_mac (pkcs12, pass);
2557   if (result < 0)
2558     error (EXIT_FAILURE, 0, "generate_mac: %s", gnutls_strerror (result));
2559
2560   size = buffer_size;
2561   result = gnutls_pkcs12_export (pkcs12, info.outcert_format, buffer, &size);
2562   if (result < 0)
2563     error (EXIT_FAILURE, 0, "pkcs12_export: %s", gnutls_strerror (result));
2564
2565   fwrite (buffer, 1, size, outfile);
2566
2567 }
2568
2569 static const char *
2570 BAGTYPE (gnutls_pkcs12_bag_type_t x)
2571 {
2572   switch (x)
2573     {
2574     case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
2575       return "PKCS #8 Encrypted key";
2576     case GNUTLS_BAG_EMPTY:
2577       return "Empty";
2578     case GNUTLS_BAG_PKCS8_KEY:
2579       return "PKCS #8 Key";
2580     case GNUTLS_BAG_CERTIFICATE:
2581       return "Certificate";
2582     case GNUTLS_BAG_ENCRYPTED:
2583       return "Encrypted";
2584     case GNUTLS_BAG_CRL:
2585       return "CRL";
2586     case GNUTLS_BAG_SECRET:
2587       return "Secret";
2588     default:
2589       return "Unknown";
2590     }
2591 }
2592
2593 static void
2594 print_bag_data (gnutls_pkcs12_bag_t bag)
2595 {
2596   int result;
2597   int count, i, type;
2598   gnutls_datum_t cdata, id;
2599   const char *str, *name;
2600   gnutls_datum_t out;
2601
2602   count = gnutls_pkcs12_bag_get_count (bag);
2603   if (count < 0)
2604     error (EXIT_FAILURE, 0, "get_count: %s", gnutls_strerror (count));
2605
2606   fprintf (outfile, "\tElements: %d\n", count);
2607
2608   for (i = 0; i < count; i++)
2609     {
2610       type = gnutls_pkcs12_bag_get_type (bag, i);
2611       if (type < 0)
2612         error (EXIT_FAILURE, 0, "get_type: %s", gnutls_strerror (type));
2613
2614       fprintf (stderr, "\tType: %s\n", BAGTYPE (type));
2615
2616       name = NULL;
2617       result = gnutls_pkcs12_bag_get_friendly_name (bag, i, (char **) &name);
2618       if (result < 0)
2619         error (EXIT_FAILURE, 0, "get_friendly_name: %s",
2620                gnutls_strerror (type));
2621       if (name)
2622         fprintf (outfile, "\tFriendly name: %s\n", name);
2623
2624       id.data = NULL;
2625       id.size = 0;
2626       result = gnutls_pkcs12_bag_get_key_id (bag, i, &id);
2627       if (result < 0)
2628         error (EXIT_FAILURE, 0, "get_key_id: %s", gnutls_strerror (type));
2629       fprintf (outfile, "\tKey ID: %s\n", raw_to_string (id.data, id.size));
2630
2631       result = gnutls_pkcs12_bag_get_data (bag, i, &cdata);
2632       if (result < 0)
2633         error (EXIT_FAILURE, 0, "get_data: %s", gnutls_strerror (result));
2634
2635       switch (type)
2636         {
2637         case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
2638           str = "ENCRYPTED PRIVATE KEY";
2639           break;
2640         case GNUTLS_BAG_PKCS8_KEY:
2641           str = "PRIVATE KEY";
2642           break;
2643         case GNUTLS_BAG_CERTIFICATE:
2644           str = "CERTIFICATE";
2645           break;
2646         case GNUTLS_BAG_CRL:
2647           str = "CRL";
2648           break;
2649         case GNUTLS_BAG_ENCRYPTED:
2650         case GNUTLS_BAG_EMPTY:
2651         default:
2652           str = NULL;
2653         }
2654
2655       if (str != NULL)
2656         {
2657           gnutls_pem_base64_encode_alloc (str, &cdata, &out);
2658           fprintf (outfile, "%s\n", out.data);
2659
2660           gnutls_free (out.data);
2661         }
2662
2663     }
2664 }
2665
2666 void
2667 pkcs12_info (void)
2668 {
2669   gnutls_pkcs12_t pkcs12;
2670   gnutls_pkcs12_bag_t bag;
2671   int result;
2672   size_t size;
2673   gnutls_datum_t data;
2674   const char *pass;
2675   int indx;
2676
2677   result = gnutls_pkcs12_init (&pkcs12);
2678   if (result < 0)
2679     error (EXIT_FAILURE, 0, "p12_init: %s", gnutls_strerror (result));
2680
2681   data.data = fread_file (infile, &size);
2682   data.size = size;
2683
2684   result = gnutls_pkcs12_import (pkcs12, &data, info.incert_format, 0);
2685   free (data.data);
2686   if (result < 0)
2687     error (EXIT_FAILURE, 0, "p12_import: %s", gnutls_strerror (result));
2688
2689   if (info.pass)
2690     pass = info.pass;
2691   else
2692     pass = get_pass ();
2693
2694   result = gnutls_pkcs12_verify_mac (pkcs12, pass);
2695   if (result < 0)
2696     error (0, 0, "verify_mac: %s", gnutls_strerror (result));
2697
2698   for (indx = 0;; indx++)
2699     {
2700       result = gnutls_pkcs12_bag_init (&bag);
2701       if (result < 0)
2702         error (EXIT_FAILURE, 0, "bag_init: %s", gnutls_strerror (result));
2703
2704       result = gnutls_pkcs12_get_bag (pkcs12, indx, bag);
2705       if (result < 0)
2706         break;
2707
2708       result = gnutls_pkcs12_bag_get_count (bag);
2709       if (result < 0)
2710         error (EXIT_FAILURE, 0, "bag_count: %s", gnutls_strerror (result));
2711
2712       fprintf (outfile, "BAG #%d\n", indx);
2713
2714       result = gnutls_pkcs12_bag_get_type (bag, 0);
2715       if (result < 0)
2716         error (EXIT_FAILURE, 0, "bag_init: %s", gnutls_strerror (result));
2717
2718       if (result == GNUTLS_BAG_ENCRYPTED)
2719         {
2720           fprintf (stderr, "\tType: %s\n", BAGTYPE (result));
2721           fprintf (stderr, "\n\tDecrypting...\n");
2722
2723           result = gnutls_pkcs12_bag_decrypt (bag, pass);
2724
2725           if (result < 0)
2726             {
2727               error (0, 0, "bag_decrypt: %s", gnutls_strerror (result));
2728               continue;
2729             }
2730
2731           result = gnutls_pkcs12_bag_get_count (bag);
2732           if (result < 0)
2733             error (EXIT_FAILURE, 0, "encrypted bag_count: %s",
2734                    gnutls_strerror (result));
2735         }
2736
2737       print_bag_data (bag);
2738
2739       gnutls_pkcs12_bag_deinit (bag);
2740     }
2741 }
2742
2743 void
2744 pkcs7_info (void)
2745 {
2746   gnutls_pkcs7_t pkcs7;
2747   int result;
2748   size_t size;
2749   gnutls_datum_t data, b64;
2750   int indx, count;
2751
2752   result = gnutls_pkcs7_init (&pkcs7);
2753   if (result < 0)
2754     error (EXIT_FAILURE, 0, "p7_init: %s", gnutls_strerror (result));
2755
2756   data.data = fread_file (infile, &size);
2757   data.size = size;
2758
2759   result = gnutls_pkcs7_import (pkcs7, &data, info.incert_format);
2760   free (data.data);
2761   if (result < 0)
2762     error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (result));
2763
2764   /* Read and print the certificates.
2765    */
2766   result = gnutls_pkcs7_get_crt_count (pkcs7);
2767   if (result < 0)
2768     error (EXIT_FAILURE, 0, "p7_crt_count: %s", gnutls_strerror (result));
2769
2770   count = result;
2771
2772   if (count > 0)
2773     fprintf (outfile, "Number of certificates: %u\n", count);
2774
2775   for (indx = 0; indx < count; indx++)
2776     {
2777       fputs ("\n", outfile);
2778
2779       size = buffer_size;
2780       result = gnutls_pkcs7_get_crt_raw (pkcs7, indx, buffer, &size);
2781       if (result < 0)
2782         break;
2783
2784       data.data = buffer;
2785       data.size = size;
2786
2787       result = gnutls_pem_base64_encode_alloc ("CERTIFICATE", &data, &b64);
2788       if (result < 0)
2789         error (EXIT_FAILURE, 0, "encoding: %s", gnutls_strerror (result));
2790
2791       fputs (b64.data, outfile);
2792       gnutls_free (b64.data);
2793     }
2794
2795   /* Read the CRLs now.
2796    */
2797   result = gnutls_pkcs7_get_crl_count (pkcs7);
2798   if (result < 0)
2799     error (EXIT_FAILURE, 0, "p7_crl_count: %s", gnutls_strerror (result));
2800
2801   count = result;
2802
2803   if (count > 0)
2804     fprintf (outfile, "\nNumber of CRLs: %u\n", count);
2805
2806   for (indx = 0; indx < count; indx++)
2807     {
2808       fputs ("\n", outfile);
2809
2810       size = buffer_size;
2811       result = gnutls_pkcs7_get_crl_raw (pkcs7, indx, buffer, &size);
2812       if (result < 0)
2813         break;
2814
2815       data.data = buffer;
2816       data.size = size;
2817
2818       result = gnutls_pem_base64_encode_alloc ("X509 CRL", &data, &b64);
2819       if (result < 0)
2820         error (EXIT_FAILURE, 0, "encoding: %s", gnutls_strerror (result));
2821
2822       fputs (b64.data, outfile);
2823       gnutls_free (b64.data);
2824     }
2825 }
2826
2827 void
2828 smime_to_pkcs7 (void)
2829 {
2830   size_t linesize = 0;
2831   char *lineptr = NULL;
2832   ssize_t len;
2833
2834   /* Find body.  FIXME: Handle non-b64 Content-Transfer-Encoding.
2835      Reject non-S/MIME tagged Content-Type's? */
2836   do
2837     {
2838       len = getline (&lineptr, &linesize, infile);
2839       if (len == -1)
2840         error (EXIT_FAILURE, 0, "cannot find RFC 2822 header/body separator");
2841     }
2842   while (strcmp (lineptr, "\r\n") != 0 && strcmp (lineptr, "\n") != 0);
2843
2844   do
2845     {
2846       len = getline (&lineptr, &linesize, infile);
2847       if (len == -1)
2848         error (EXIT_FAILURE, 0, "message has RFC 2822 header but no body");
2849     }
2850   while (strcmp (lineptr, "\r\n") == 0 && strcmp (lineptr, "\n") == 0);
2851
2852   fprintf (outfile, "%s", "-----BEGIN PKCS7-----\n");
2853
2854   do
2855     {
2856       while (len > 0
2857              && (lineptr[len - 1] == '\r' || lineptr[len - 1] == '\n'))
2858         lineptr[--len] = '\0';
2859       if (strcmp (lineptr, "") != 0)
2860         fprintf (outfile, "%s\n", lineptr);
2861       len = getline (&lineptr, &linesize, infile);
2862     }
2863   while (len != -1);
2864
2865   fprintf (outfile, "%s", "-----END PKCS7-----\n");
2866
2867   free (lineptr);
2868 }
2869
2870 void
2871 certtool_version (void)
2872 {
2873   const char *p = PACKAGE_NAME;
2874   if (strcmp (gnutls_check_version (NULL), PACKAGE_VERSION) != 0)
2875     p = PACKAGE_STRING;
2876   version_etc (stdout, program_name, p, gnutls_check_version (NULL),
2877                "Nikos Mavrogiannopoulos", "Simon Josefsson", (char *) NULL);
2878 }
2879
2880 static void
2881 print_key_usage (FILE * outfile, unsigned int usage)
2882 {
2883   if (usage & GNUTLS_KEY_DIGITAL_SIGNATURE)
2884     {
2885       fprintf (outfile, "\tDigital signature.\n");
2886     }
2887
2888   if (usage & GNUTLS_KEY_NON_REPUDIATION)
2889     {
2890       fprintf (outfile, "\tNon repudiation.\n");
2891     }
2892
2893   if (usage & GNUTLS_KEY_KEY_ENCIPHERMENT)
2894     {
2895       fprintf (outfile, "\tKey encipherment.\n");
2896     }
2897
2898   if (usage & GNUTLS_KEY_DATA_ENCIPHERMENT)
2899     {
2900       fprintf (outfile, "\tData encipherment.\n");
2901     }
2902
2903   if (usage & GNUTLS_KEY_KEY_AGREEMENT)
2904     {
2905       fprintf (outfile, "\tKey agreement.\n");
2906     }
2907
2908   if (usage & GNUTLS_KEY_KEY_CERT_SIGN)
2909     {
2910       fprintf (outfile, "\tCertificate signing.\n");
2911     }
2912
2913   if (usage & GNUTLS_KEY_NON_REPUDIATION)
2914     {
2915       fprintf (outfile, "\tCRL signing.\n");
2916     }
2917
2918   if (usage & GNUTLS_KEY_ENCIPHER_ONLY)
2919     {
2920       fprintf (outfile, "\tKey encipher only.\n");
2921     }
2922
2923   if (usage & GNUTLS_KEY_DECIPHER_ONLY)
2924     {
2925       fprintf (outfile, "\tKey decipher only.\n");
2926     }
2927 }
2928
2929 void
2930 pubkey_info (gnutls_x509_crt crt, common_info_st * cinfo)
2931 {
2932   gnutls_pubkey_t pubkey;
2933   unsigned int bits, usage;
2934   int ret;
2935   size_t size;
2936   const char *cprint;
2937
2938   ret = gnutls_pubkey_init (&pubkey);
2939   if (ret < 0)
2940     {
2941       error (EXIT_FAILURE, 0, "pubkey_init: %s", gnutls_strerror (ret));
2942     }
2943
2944   if (crt == NULL)
2945     {
2946       crt = load_cert (0, cinfo);
2947     }
2948
2949   if (crt != NULL)
2950     {
2951       ret = gnutls_pubkey_import_x509 (pubkey, crt, 0);
2952       if (ret < 0)
2953         {
2954           error (EXIT_FAILURE, 0, "pubkey_import_x509: %s",
2955                  gnutls_strerror (ret));
2956         }
2957     }
2958   else
2959     {
2960       pubkey = load_pubkey (1, cinfo);
2961     }
2962
2963   fprintf (outfile, "Public Key Info:\n\n");
2964   ret = gnutls_pubkey_get_pk_algorithm (pubkey, &bits);
2965   fprintf (outfile, "Public Key Algorithm: ");
2966
2967   cprint = gnutls_pk_algorithm_get_name (ret);
2968   fprintf (outfile, "%s (%u bits)\n", cprint ? cprint : "Unknown", bits);
2969
2970
2971   /* Print the raw public and private keys
2972    */
2973   if (ret == GNUTLS_PK_RSA)
2974     {
2975       gnutls_datum_t m, e;
2976
2977       ret = gnutls_pubkey_get_pk_rsa_raw (pubkey, &m, &e);
2978       if (ret < 0)
2979         fprintf (stderr, "Error in key RSA data export: %s\n",
2980                  gnutls_strerror (ret));
2981       else
2982         {
2983           print_rsa_pkey (&m, &e, NULL, NULL, NULL, NULL, NULL, NULL);
2984           gnutls_free (m.data);
2985           gnutls_free (e.data);
2986         }
2987     }
2988   else if (ret == GNUTLS_PK_DSA)
2989     {
2990       gnutls_datum_t p, q, g, y;
2991
2992       ret = gnutls_pubkey_get_pk_dsa_raw (pubkey, &p, &q, &g, &y);
2993       if (ret < 0)
2994         fprintf (stderr, "Error in key DSA data export: %s\n",
2995                  gnutls_strerror (ret));
2996       else
2997         {
2998           print_dsa_pkey (NULL, &y, &p, &q, &g);
2999           gnutls_free (y.data);
3000           gnutls_free (p.data);
3001           gnutls_free (q.data);
3002           gnutls_free (g.data);
3003         }
3004     }
3005
3006   ret = gnutls_pubkey_get_key_usage (pubkey, &usage);
3007   if (ret < 0)
3008     {
3009       error (EXIT_FAILURE, 0, "pubkey_get_key_usage: %s",
3010              gnutls_strerror (ret));
3011     }
3012
3013   fprintf (outfile, "Public Key Usage:\n");
3014   print_key_usage (outfile, usage);
3015
3016   fprintf (outfile, "\n");
3017
3018   size = buffer_size;
3019   if ((ret = gnutls_pubkey_get_key_id (pubkey, 0, buffer, &size)) < 0)
3020     {
3021       fprintf (stderr, "Error in key id calculation: %s\n",
3022                gnutls_strerror (ret));
3023     }
3024   else
3025     {
3026       fprintf (outfile, "Public Key ID: %s\n", raw_to_string (buffer, size));
3027     }
3028
3029   size = buffer_size;
3030   ret = gnutls_pubkey_export (pubkey, GNUTLS_X509_FMT_PEM, buffer, &size);
3031   if (ret < 0)
3032     error (EXIT_FAILURE, 0, "export error: %s", gnutls_strerror (ret));
3033
3034   fprintf (outfile, "\n%s\n", buffer);
3035
3036   gnutls_pubkey_deinit (pubkey);
3037 }