Update.
[gnutls.git] / src / certtool.c
blob24c2e5f9e278209c56880c1a904eb865ebea7568
1 /*
2 * Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation
4 * This file is part of GNUTLS.
6 * GNUTLS is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * GNUTLS is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <config.h>
22 #include <gnutls/gnutls.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include <gnutls/x509.h>
29 #include <time.h>
30 #include "certtool-gaa.h"
31 #include <gnutls/pkcs12.h>
32 #include <unistd.h>
33 #include <certtool-cfg.h>
35 #include <errno.h>
37 /* Gnulib portability files. */
38 #include <getline.h>
39 #include <read-file.h>
40 #include <error.h>
41 #include <progname.h>
42 #include <version-etc.h>
44 static void print_crl_info (gnutls_x509_crl crl, FILE *out);
45 int generate_prime (int bits, int how);
46 void pkcs7_info (void);
47 void smime_to_pkcs7 (void);
48 void pkcs12_info (void);
49 void generate_pkcs12 (void);
50 void verify_chain (void);
51 void verify_crl (void);
52 gnutls_x509_privkey load_private_key (int mand);
53 gnutls_x509_crq load_request (void);
54 gnutls_x509_privkey load_ca_private_key (void);
55 gnutls_x509_crt load_ca_cert (void);
56 gnutls_x509_crt load_cert (int mand);
57 void certificate_info (void);
58 void crl_info (void);
59 void privkey_info (void);
60 static void print_certificate_info (gnutls_x509_crt crt, FILE *out,
61 unsigned int);
62 static void gaa_parser (int argc, char **argv);
63 void generate_self_signed (void);
64 void generate_request (void);
65 gnutls_x509_crt *load_cert_list (int mand, int *size);
67 static gaainfo info;
68 FILE *outfile;
69 FILE *infile;
70 gnutls_digest_algorithm_t dig = GNUTLS_DIG_SHA1;
72 #define UNKNOWN "Unknown"
74 /* non interactive operation if set
76 int batch;
78 unsigned char buffer[64 * 1024];
79 const int buffer_size = sizeof (buffer);
81 static void
82 tls_log_func (int level, const char *str)
84 fprintf (stderr, "|<%d>| %s", level, str);
87 int
88 main (int argc, char **argv)
90 set_program_name (argv[0]);
91 cfg_init ();
92 gaa_parser (argc, argv);
94 return 0;
97 const char *
98 raw_to_string (const unsigned char *raw, size_t raw_size)
100 static char buf[1024];
101 size_t i;
102 if (raw_size == 0)
103 return NULL;
105 if (raw_size * 3 + 1 >= sizeof (buf))
106 return NULL;
108 for (i = 0; i < raw_size; i++)
110 sprintf (&(buf[i * 3]), "%02X%s", raw[i],
111 (i == raw_size - 1) ? "" : ":");
113 buf[sizeof (buf) - 1] = '\0';
115 return buf;
118 static gnutls_x509_privkey
119 generate_private_key_int (void)
121 gnutls_x509_privkey key;
122 int ret, key_type;
124 if (info.dsa)
126 key_type = GNUTLS_PK_DSA;
128 if (info.bits > 1024)
129 error (EXIT_FAILURE, 0, "--dsa is incompatible with --bits > 1024");
131 else
132 key_type = GNUTLS_PK_RSA;
134 ret = gnutls_x509_privkey_init (&key);
135 if (ret < 0)
136 error (EXIT_FAILURE, 0, "privkey_init: %s", gnutls_strerror (ret));
138 fprintf (stderr, "Generating a %d bit %s private key...\n", info.bits,
139 gnutls_pk_algorithm_get_name (key_type));
141 ret = gnutls_x509_privkey_generate (key, key_type, info.bits, 0);
142 if (ret < 0)
143 error (EXIT_FAILURE, 0, "privkey_generate: %s", gnutls_strerror (ret));
145 return key;
148 static void
149 print_private_key (gnutls_x509_privkey key)
151 int ret;
152 size_t size;
154 if (!key)
155 return;
157 if (!info.pkcs8)
159 size = sizeof (buffer);
160 ret = gnutls_x509_privkey_export (key, info.outcert_format,
161 buffer, &size);
162 if (ret < 0)
163 error (EXIT_FAILURE, 0, "privkey_export: %s", gnutls_strerror (ret));
165 else
167 unsigned int flags;
168 const char *pass;
170 if (info.export)
171 flags = GNUTLS_PKCS_USE_PKCS12_RC2_40;
172 else
173 flags = GNUTLS_PKCS_USE_PKCS12_3DES;
175 if ((pass = get_pass ()) == NULL || *pass == '\0')
176 flags = GNUTLS_PKCS_PLAIN;
178 size = sizeof (buffer);
179 ret =
180 gnutls_x509_privkey_export_pkcs8 (key, info.outcert_format, pass,
181 flags, buffer, &size);
182 if (ret < 0)
183 error (EXIT_FAILURE, 0, "privkey_export_pkcs8: %s",
184 gnutls_strerror (ret));
187 fwrite (buffer, 1, size, outfile);
190 void
191 generate_private_key (void)
193 gnutls_x509_privkey key;
195 key = generate_private_key_int ();
197 print_private_key (key);
199 gnutls_x509_privkey_deinit (key);
203 gnutls_x509_crt
204 generate_certificate (gnutls_x509_privkey * ret_key,
205 gnutls_x509_crt ca_crt,
206 int proxy)
208 gnutls_x509_crt crt;
209 gnutls_x509_privkey key = NULL;
210 size_t size;
211 int ret;
212 int serial, client;
213 int days, result, ca_status = 0, path_len;
214 const char *str;
215 int vers = 3; /* the default version in the certificate
217 unsigned int usage = 0, server;
218 gnutls_x509_crq crq; /* request */
220 ret = gnutls_x509_crt_init (&crt);
221 if (ret < 0)
222 error (EXIT_FAILURE, 0, "crt_init: %s", gnutls_strerror (ret));
224 crq = load_request ();
226 if (crq == NULL)
229 key = load_private_key (1);
231 if (!batch)
232 fprintf (stderr,
233 "Please enter the details of the certificate's distinguished name. "
234 "Just press enter to ignore a field.\n");
236 /* set the DN.
238 if (proxy)
240 result = gnutls_x509_crt_set_proxy_dn (crt, ca_crt, 0, NULL, 0);
241 if (result < 0)
242 error (EXIT_FAILURE, 0, "set_proxy_dn: %s",
243 gnutls_strerror (result));
245 get_cn_crt_set (crt);
247 else
249 get_country_crt_set (crt);
250 get_organization_crt_set (crt);
251 get_unit_crt_set (crt);
252 get_locality_crt_set (crt);
253 get_state_crt_set (crt);
254 get_cn_crt_set (crt);
255 get_uid_crt_set (crt);
256 get_oid_crt_set (crt);
258 if (!batch)
259 fprintf (stderr,
260 "This field should not be used in new certificates.\n");
262 get_pkcs9_email_crt_set (crt);
265 result = gnutls_x509_crt_set_key (crt, key);
266 if (result < 0)
267 error (EXIT_FAILURE, 0, "set_key: %s", gnutls_strerror (result));
269 else
271 result = gnutls_x509_crt_set_crq (crt, crq);
272 if (result < 0)
273 error (EXIT_FAILURE, 0, "set_crq: %s", gnutls_strerror (result));
277 serial = get_serial ();
278 buffer[4] = serial & 0xff;
279 buffer[3] = (serial >> 8) & 0xff;
280 buffer[2] = (serial >> 16) & 0xff;
281 buffer[1] = (serial >> 24) & 0xff;
282 buffer[0] = 0;
284 result = gnutls_x509_crt_set_serial (crt, buffer, 5);
285 if (result < 0)
286 error (EXIT_FAILURE, 0, "serial: %s", gnutls_strerror (result));
288 if (!batch)
289 fprintf (stderr, "\n\nActivation/Expiration time.\n");
291 gnutls_x509_crt_set_activation_time (crt, time (NULL));
293 days = get_days ();
295 result =
296 gnutls_x509_crt_set_expiration_time (crt,
297 time (NULL) + days * 24 * 60 * 60);
298 if (result < 0)
299 error (EXIT_FAILURE, 0, "set_expiration: %s", gnutls_strerror (result));
301 if (!batch)
302 fprintf (stderr, "\n\nExtensions.\n");
304 if (proxy)
306 const char *policylanguage;
307 char *policy;
308 size_t policylen;
309 int proxypathlen = get_path_len ();
311 if (!batch)
313 printf ("1.3.6.1.5.5.7.21.1 ::= id-ppl-inheritALL\n");
314 printf ("1.3.6.1.5.5.7.21.2 ::= id-ppl-independent\n");
317 policylanguage = get_proxy_policy (&policy, &policylen);
319 result = gnutls_x509_crt_set_proxy (crt, proxypathlen, policylanguage,
320 policy, policylen);
321 if (result < 0)
322 error (EXIT_FAILURE, 0, "set_proxy: %s", gnutls_strerror (result));
325 if (!proxy)
326 ca_status = get_ca_status ();
327 if (ca_status)
328 path_len = get_path_len ();
329 else
330 path_len = -1;
332 result = gnutls_x509_crt_set_basic_constraints (crt, ca_status, path_len);
333 if (result < 0)
334 error (EXIT_FAILURE, 0, "basic_constraints: %s", gnutls_strerror (result));
336 client = get_tls_client_status ();
337 if (client != 0)
339 result = gnutls_x509_crt_set_key_purpose_oid (crt,
340 GNUTLS_KP_TLS_WWW_CLIENT,
342 if (result < 0)
343 error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (result));
346 server = get_tls_server_status ();
347 if (server != 0)
349 result = 0;
351 if (!proxy)
353 str = get_dns_name ();
354 if (str != NULL)
356 result = gnutls_x509_crt_set_subject_alternative_name
357 (crt, GNUTLS_SAN_DNSNAME, str);
359 else
361 str = get_ip_addr ();
362 if (str != NULL)
364 result = gnutls_x509_crt_set_subject_alternative_name
365 (crt, GNUTLS_SAN_IPADDRESS, str);
369 if (result < 0)
370 error (EXIT_FAILURE, 0, "subject_alt_name: %s",
371 gnutls_strerror (result));
374 result =
375 gnutls_x509_crt_set_key_purpose_oid (crt,
376 GNUTLS_KP_TLS_WWW_SERVER, 0);
377 if (result < 0)
378 error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (result));
380 else if (!proxy)
382 str = get_email ();
384 if (str != NULL)
386 result = gnutls_x509_crt_set_subject_alternative_name
387 (crt, GNUTLS_SAN_RFC822NAME, str);
388 if (result < 0)
389 error (EXIT_FAILURE, 0, "subject_alt_name: %s",
390 gnutls_strerror (result));
395 if (!ca_status || server)
397 int pk;
400 pk = gnutls_x509_crt_get_pk_algorithm (crt, NULL);
402 if (pk != GNUTLS_PK_DSA)
403 { /* DSA keys can only sign.
405 result = get_sign_status (server);
406 if (result)
407 usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
409 result = get_encrypt_status (server);
410 if (result)
411 usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
413 else
414 usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
418 if (ca_status)
420 result = get_cert_sign_status ();
421 if (result)
422 usage |= GNUTLS_KEY_KEY_CERT_SIGN;
424 result = get_crl_sign_status ();
425 if (result)
426 usage |= GNUTLS_KEY_CRL_SIGN;
428 result = get_code_sign_status ();
429 if (result)
431 result =
432 gnutls_x509_crt_set_key_purpose_oid (crt,
433 GNUTLS_KP_CODE_SIGNING, 0);
434 if (result < 0)
435 error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (result));
438 result = get_ocsp_sign_status ();
439 if (result)
441 result =
442 gnutls_x509_crt_set_key_purpose_oid (crt,
443 GNUTLS_KP_OCSP_SIGNING, 0);
444 if (result < 0)
445 error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (result));
448 result = get_time_stamp_status ();
449 if (result)
451 result =
452 gnutls_x509_crt_set_key_purpose_oid (crt,
453 GNUTLS_KP_TIME_STAMPING, 0);
454 if (result < 0)
455 error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (result));
459 if (usage != 0)
461 result = gnutls_x509_crt_set_key_usage (crt, usage);
462 if (result < 0)
463 error (EXIT_FAILURE, 0, "key_usage: %s", gnutls_strerror (result));
466 /* Version.
468 result = gnutls_x509_crt_set_version (crt, vers);
469 if (result < 0)
470 error (EXIT_FAILURE, 0, "set_version: %s", gnutls_strerror (result));
472 /* Subject Key ID.
474 size = sizeof (buffer);
475 result = gnutls_x509_crt_get_key_id (crt, 0, buffer, &size);
476 if (result >= 0)
478 result = gnutls_x509_crt_set_subject_key_id (crt, buffer, size);
479 if (result < 0)
480 error (EXIT_FAILURE, 0, "set_subject_key_id: %s",
481 gnutls_strerror (result));
484 /* Authority Key ID.
486 if (ca_crt != NULL)
488 size = sizeof (buffer);
489 result = gnutls_x509_crt_get_subject_key_id (ca_crt, buffer,
490 &size, NULL);
491 if (result < 0)
493 size = sizeof (buffer);
494 result = gnutls_x509_crt_get_key_id (ca_crt, 0, buffer, &size);
496 if (result >= 0)
498 result = gnutls_x509_crt_set_authority_key_id (crt, buffer, size);
499 if (result < 0)
500 error (EXIT_FAILURE, 0, "set_authority_key_id: %s",
501 gnutls_strerror (result));
505 *ret_key = key;
506 return crt;
510 gnutls_x509_crl
511 generate_crl (void)
513 gnutls_x509_crl crl;
514 gnutls_x509_crt *crts;
515 int size;
516 int days, result, i;
517 time_t now = time (NULL);
519 result = gnutls_x509_crl_init (&crl);
520 if (result < 0)
521 error (EXIT_FAILURE, 0, "crl_init: %s", gnutls_strerror (result));
523 crts = load_cert_list (0, &size);
525 for (i = 0; i < size; i++)
527 result = gnutls_x509_crl_set_crt (crl, crts[i], now);
528 if (result < 0)
529 error (EXIT_FAILURE, 0, "crl_set_crt: %s", gnutls_strerror (result));
532 result = gnutls_x509_crl_set_this_update (crl, now);
533 if (result < 0)
534 error (EXIT_FAILURE, 0, "this_update: %s", gnutls_strerror (result));
536 fprintf (stderr, "Update times.\n");
537 days = get_crl_next_update ();
539 result = gnutls_x509_crl_set_next_update (crl, now + days * 24 * 60 * 60);
540 if (result < 0)
541 error (EXIT_FAILURE, 0, "next_update: %s", gnutls_strerror (result));
543 result = gnutls_x509_crl_set_version (crl, 2);
544 if (result < 0)
545 error (EXIT_FAILURE, 0, "set_version: %s", gnutls_strerror (result));
547 return crl;
550 void
551 generate_self_signed (void)
553 gnutls_x509_crt crt;
554 gnutls_x509_privkey key;
555 size_t size;
556 int result;
557 const char *uri;
559 fprintf (stderr, "Generating a self signed certificate...\n");
561 crt = generate_certificate (&key, NULL, 0);
563 if (!key)
564 key = load_private_key (1);
566 uri = get_crl_dist_point_url ();
567 if (uri)
569 result = gnutls_x509_crt_set_crl_dist_points (crt, GNUTLS_SAN_URI,
570 uri,
571 0 /* all reasons */ );
572 if (result < 0)
573 error (EXIT_FAILURE, 0, "crl_dist_points: %s",
574 gnutls_strerror (result));
577 print_certificate_info (crt, stderr, 0);
579 fprintf (stderr, "\n\nSigning certificate...\n");
581 result = gnutls_x509_crt_sign2 (crt, crt, key, dig, 0);
582 if (result < 0)
583 error (EXIT_FAILURE, 0, "crt_sign: %s", gnutls_strerror (result));
585 size = sizeof (buffer);
586 result = gnutls_x509_crt_export (crt, info.outcert_format, buffer, &size);
587 if (result < 0)
588 error (EXIT_FAILURE, 0, "crt_export: %s", gnutls_strerror (result));
590 fwrite (buffer, 1, size, outfile);
592 gnutls_x509_crt_deinit (crt);
593 gnutls_x509_privkey_deinit (key);
596 void
597 generate_signed_certificate (void)
599 gnutls_x509_crt crt;
600 gnutls_x509_privkey key;
601 size_t size;
602 int result;
603 gnutls_x509_privkey ca_key;
604 gnutls_x509_crt ca_crt;
606 fprintf (stderr, "Generating a signed certificate...\n");
608 ca_key = load_ca_private_key ();
609 ca_crt = load_ca_cert ();
611 crt = generate_certificate (&key, ca_crt, 0);
613 /* Copy the CRL distribution points.
615 gnutls_x509_crt_cpy_crl_dist_points (crt, ca_crt);
616 /* it doesn't matter if we couldn't copy the CRL dist points.
619 print_certificate_info (crt, stderr, 0);
621 fprintf (stderr, "\n\nSigning certificate...\n");
623 result = gnutls_x509_crt_sign2 (crt, ca_crt, ca_key, dig, 0);
624 if (result < 0)
625 error (EXIT_FAILURE, 0, "crt_sign: %s", gnutls_strerror (result));
627 size = sizeof (buffer);
628 result = gnutls_x509_crt_export (crt, info.outcert_format, buffer, &size);
629 if (result < 0)
630 error (EXIT_FAILURE, 0, "crt_export: %s", gnutls_strerror (result));
632 fwrite (buffer, 1, size, outfile);
634 gnutls_x509_crt_deinit (crt);
635 gnutls_x509_privkey_deinit (key);
638 void
639 generate_proxy_certificate (void)
641 gnutls_x509_crt crt, eecrt;
642 gnutls_x509_privkey key, eekey;
643 size_t size;
644 int result;
646 fprintf (stderr, "Generating a proxy certificate...\n");
648 eekey = load_ca_private_key ();
649 eecrt = load_cert (1);
651 crt = generate_certificate (&key, eecrt, 1);
653 print_certificate_info (crt, stderr, 0);
655 fprintf (stderr, "\n\nSigning certificate...\n");
657 result = gnutls_x509_crt_sign2 (crt, eecrt, eekey, dig, 0);
658 if (result < 0)
659 error (EXIT_FAILURE, 0, "crt_sign: %s", gnutls_strerror (result));
661 size = sizeof (buffer);
662 result = gnutls_x509_crt_export (crt, info.outcert_format, buffer, &size);
663 if (result < 0)
664 error (EXIT_FAILURE, 0, "crt_export: %s", gnutls_strerror (result));
666 fwrite (buffer, 1, size, outfile);
668 gnutls_x509_crt_deinit (crt);
669 gnutls_x509_privkey_deinit (key);
672 void
673 generate_signed_crl (void)
675 gnutls_x509_crl crl;
676 int result;
677 gnutls_x509_privkey ca_key;
678 gnutls_x509_crt ca_crt;
680 fprintf (stderr, "Generating a signed CRL...\n");
682 ca_key = load_ca_private_key ();
683 ca_crt = load_ca_cert ();
684 crl = generate_crl ();
686 fprintf (stderr, "\n");
688 result = gnutls_x509_crl_sign (crl, ca_crt, ca_key);
689 if (result < 0)
690 error (EXIT_FAILURE, 0, "crl_sign: %s", gnutls_strerror (result));
692 print_crl_info (crl, stderr);
694 gnutls_x509_crl_deinit (crl);
697 void
698 update_signed_certificate (void)
700 gnutls_x509_crt crt;
701 size_t size;
702 int result;
703 gnutls_x509_privkey ca_key;
704 gnutls_x509_crt ca_crt;
705 int days;
706 time_t tim = time (NULL);
708 fprintf (stderr, "Generating a signed certificate...\n");
710 ca_key = load_ca_private_key ();
711 ca_crt = load_ca_cert ();
712 crt = load_cert (1);
714 fprintf (stderr, "Activation/Expiration time.\n");
715 gnutls_x509_crt_set_activation_time (crt, tim);
717 days = get_days ();
719 result = gnutls_x509_crt_set_expiration_time (crt, tim + days * 24 * 60 * 60);
720 if (result < 0)
721 error (EXIT_FAILURE, 0, "set_expiration: %s", gnutls_strerror (result));
723 fprintf (stderr, "\n\nSigning certificate...\n");
725 result = gnutls_x509_crt_sign2 (crt, ca_crt, ca_key, dig, 0);
726 if (result < 0)
727 error (EXIT_FAILURE, 0, "crt_sign: %s", gnutls_strerror (result));
729 size = sizeof (buffer);
730 result = gnutls_x509_crt_export (crt, info.outcert_format, buffer, &size);
731 if (result < 0)
732 error (EXIT_FAILURE, 0, "crt_export: %s", gnutls_strerror (result));
734 fwrite (buffer, 1, size, outfile);
736 gnutls_x509_crt_deinit (crt);
739 void
740 gaa_parser (int argc, char **argv)
742 int ret;
744 if (gaa (argc, argv, &info) != -1)
746 fprintf (stderr, "Try `%s --help' for more information.\n",
747 program_name);
748 exit (1);
751 if (info.outfile)
753 outfile = fopen (info.outfile, "wb");
754 if (outfile == NULL)
755 error (EXIT_FAILURE, errno, "%s", info.outfile);
757 else
758 outfile = stdout;
760 if (info.infile)
762 infile = fopen (info.infile, "rb");
763 if (infile == NULL)
764 error (EXIT_FAILURE, errno, "%s", info.infile);
766 else
767 infile = stdin;
769 if (info.incert_format)
770 info.incert_format = GNUTLS_X509_FMT_DER;
771 else
772 info.incert_format = GNUTLS_X509_FMT_PEM;
774 if (info.outcert_format)
775 info.outcert_format = GNUTLS_X509_FMT_DER;
776 else
777 info.outcert_format = GNUTLS_X509_FMT_PEM;
779 if (info.hash != NULL)
781 if (strcasecmp (info.hash, "md5") == 0)
783 fprintf (stderr,
784 "Warning: MD5 is broken, and should not be used any more for digital signatures.\n");
785 dig = GNUTLS_DIG_MD5;
787 else if (strcasecmp (info.hash, "sha1") == 0)
788 dig = GNUTLS_DIG_SHA1;
789 else if (strcasecmp (info.hash, "sha256") == 0)
790 dig = GNUTLS_DIG_SHA256;
791 else if (strcasecmp (info.hash, "sha384") == 0)
792 dig = GNUTLS_DIG_SHA384;
793 else if (strcasecmp (info.hash, "sha512") == 0)
794 dig = GNUTLS_DIG_SHA512;
795 else if (strcasecmp (info.hash, "rmd160") == 0)
796 dig = GNUTLS_DIG_RMD160;
797 else
798 error (EXIT_FAILURE, 0, "invalid hash: %s", info.hash);
801 batch = 0;
802 if (info.template)
804 batch = 1;
805 template_parse (info.template);
808 gnutls_global_set_log_function (tls_log_func);
809 gnutls_global_set_log_level (info.debug);
811 if ((ret = gnutls_global_init ()) < 0)
812 error (EXIT_FAILURE, 0, "global_init: %s", gnutls_strerror (ret));
814 switch (info.action)
816 case 0:
817 generate_self_signed ();
818 break;
819 case 1:
820 generate_private_key ();
821 break;
822 case 2:
823 certificate_info ();
824 break;
825 case 3:
826 generate_request ();
827 break;
828 case 4:
829 generate_signed_certificate ();
830 break;
831 case 5:
832 verify_chain ();
833 break;
834 case 6:
835 privkey_info ();
836 break;
837 case 7:
838 update_signed_certificate ();
839 break;
840 case 8:
841 generate_pkcs12 ();
842 break;
843 case 9:
844 pkcs12_info ();
845 break;
846 case 10:
847 generate_prime (info.bits, 1);
848 break;
849 case 16:
850 generate_prime (info.bits, 0);
851 break;
852 case 11:
853 crl_info ();
854 break;
855 case 12:
856 pkcs7_info ();
857 break;
858 case 13:
859 generate_signed_crl ();
860 break;
861 case 14:
862 verify_crl ();
863 break;
864 case 15:
865 smime_to_pkcs7 ();
866 break;
867 case 17:
868 generate_proxy_certificate ();
869 break;
870 default:
871 gaa_help ();
872 exit (0);
874 fclose (outfile);
877 #define MAX_CRTS 500
878 void
879 certificate_info (void)
881 gnutls_x509_crt crt[MAX_CRTS];
882 size_t size;
883 int ret, i, count;
884 gnutls_datum pem;
885 unsigned int crt_num;
887 pem.data = fread_file (infile, &size);
888 pem.size = size;
890 crt_num = MAX_CRTS;
891 ret = gnutls_x509_crt_list_import (crt, &crt_num, &pem, info.incert_format,
892 GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);
893 if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
895 error (0, 0, "Too many certificates (%d), will only read the first %d.",
896 crt_num, MAX_CRTS);
897 crt_num = MAX_CRTS;
898 ret = gnutls_x509_crt_list_import (crt, &crt_num, &pem,
899 info.incert_format, 0);
901 if (ret < 0)
902 error (EXIT_FAILURE, 0, "Import error: %s", gnutls_strerror (ret));
904 free (pem.data);
906 count = ret;
908 if (count > 1 && info.outcert_format == GNUTLS_X509_FMT_DER)
910 error(0, 0, "Cannot output multiple certificates in DER format, using PEM instead.");
911 info.outcert_format = GNUTLS_X509_FMT_PEM;
914 for (i = 0; i < count; i++)
916 if (i > 0)
917 fprintf (outfile, "\n");
919 if (info.outcert_format == GNUTLS_X509_FMT_PEM)
920 print_certificate_info (crt[i], outfile, 1);
922 if (!info.xml)
924 size = sizeof (buffer);
925 ret = gnutls_x509_crt_export (crt[i], info.outcert_format, buffer,
926 &size);
927 if (ret < 0)
928 error (EXIT_FAILURE, 0, "Export error: %s",
929 gnutls_strerror (ret));
930 fprintf (outfile, "%s", buffer);
932 else
934 gnutls_datum xml;
936 ret = gnutls_x509_crt_to_xml (crt[i], &xml, GNUTLS_XML_SHOW_ALL);
937 if (ret < 0)
938 error (EXIT_FAILURE, 0, "XML encoding error: %s",
939 gnutls_strerror (ret));
941 fprintf (outfile, "\n%s\n", xml.data);
942 gnutls_free (xml.data);
947 static void
948 print_hex_datum (gnutls_datum * dat)
950 unsigned int j;
951 #define SPACE "\t"
952 fprintf (outfile, "\n" SPACE);
953 for (j = 0; j < dat->size; j++)
955 fprintf (outfile, "%.2x:", (unsigned char) dat->data[j]);
956 if ((j + 1) % 15 == 0)
957 fprintf (outfile, "\n" SPACE);
959 fprintf (outfile, "\n");
963 static void
964 print_certificate_info (gnutls_x509_crt crt, FILE *out, unsigned int all)
966 gnutls_datum_t info;
967 int ret;
969 if (all)
970 ret = gnutls_x509_crt_print (crt, GNUTLS_X509_CRT_FULL, &info);
971 else
972 ret = gnutls_x509_crt_print (crt, GNUTLS_X509_CRT_UNSIGNED_FULL, &info);
973 if (ret == 0)
975 fprintf (out, "%s\n", info.data);
976 gnutls_free (info.data);
979 if (out == stderr && batch == 0) /* interactive */
980 if (read_yesno ("Is the above information ok? (Y/N): ") == 0)
982 exit (1);
986 static void
987 print_crl_info (gnutls_x509_crl crl, FILE *out)
989 gnutls_datum_t info;
990 int ret;
991 size_t size;
993 ret = gnutls_x509_crl_print (crl, GNUTLS_X509_CRT_FULL, &info);
994 if (ret < 0)
995 error (EXIT_FAILURE, 0, "crl_print: %s", gnutls_strerror (ret));
997 fprintf (out, "%s\n", info.data);
999 gnutls_free (info.data);
1001 size = sizeof (buffer);
1002 ret = gnutls_x509_crl_export (crl, GNUTLS_X509_FMT_PEM, buffer, &size);
1003 if (ret < 0)
1004 error (EXIT_FAILURE, 0, "crl_export: %s", gnutls_strerror (ret));
1006 fprintf (outfile, "%s", buffer);
1009 void
1010 crl_info (void)
1012 gnutls_x509_crl crl;
1013 int ret;
1014 size_t size;
1015 gnutls_datum_t pem;
1017 ret = gnutls_x509_crl_init (&crl);
1018 if (ret < 0)
1019 error (EXIT_FAILURE, 0, "crl_init: %s", gnutls_strerror (ret));
1021 pem.data = fread_file (infile, &size);
1022 pem.size = size;
1024 if (!pem.data)
1025 error (EXIT_FAILURE, errno, "%s", info.infile ? info.infile :
1026 "standard input");
1028 ret = gnutls_x509_crl_import (crl, &pem, info.incert_format);
1029 free (pem.data);
1030 if (ret < 0)
1031 error (EXIT_FAILURE, 0, "Import error: %s", gnutls_strerror (ret));
1033 print_crl_info (crl, outfile);
1036 void
1037 privkey_info (void)
1039 gnutls_x509_privkey key;
1040 size_t size;
1041 int ret;
1042 gnutls_datum pem;
1043 const char *cprint;
1044 const char *pass;
1046 size = fread (buffer, 1, sizeof (buffer) - 1, infile);
1047 buffer[size] = 0;
1049 gnutls_x509_privkey_init (&key);
1051 pem.data = buffer;
1052 pem.size = size;
1055 if (!info.pkcs8)
1057 ret = gnutls_x509_privkey_import (key, &pem, info.incert_format);
1059 else
1061 if (info.pass)
1062 pass = info.pass;
1063 else
1064 pass = get_pass ();
1065 ret = gnutls_x509_privkey_import_pkcs8 (key, &pem, info.incert_format,
1066 pass, 0);
1068 if (ret < 0)
1069 error (EXIT_FAILURE, 0, "Import error: %s", gnutls_strerror (ret));
1071 /* Public key algorithm
1073 fprintf (outfile, "Public Key Info:\n");
1074 ret = gnutls_x509_privkey_get_pk_algorithm (key);
1075 fprintf (outfile, "\tPublic Key Algorithm: ");
1077 cprint = gnutls_pk_algorithm_get_name (ret);
1078 if (cprint == NULL)
1079 cprint = UNKNOWN;
1080 fprintf (outfile, "%s\n", cprint);
1082 /* Print the raw public and private keys
1084 if (ret == GNUTLS_PK_RSA)
1086 gnutls_datum m, e, d, p, q, u;
1088 ret = gnutls_x509_privkey_export_rsa_raw (key, &m, &e, &d, &p, &q, &u);
1089 if (ret < 0)
1091 fprintf (stderr, "Error in key RSA data export: %s\n",
1092 gnutls_strerror (ret));
1095 fprintf (outfile, "modulus:");
1096 print_hex_datum (&m);
1097 fprintf (outfile, "public exponent:");
1098 print_hex_datum (&e);
1099 fprintf (outfile, "private exponent:");
1100 print_hex_datum (&d);
1101 fprintf (outfile, "prime1:");
1102 print_hex_datum (&p);
1103 fprintf (outfile, "prime2:");
1104 print_hex_datum (&q);
1105 fprintf (outfile, "coefficient:");
1106 print_hex_datum (&u);
1109 else if (ret == GNUTLS_PK_DSA)
1111 gnutls_datum p, q, g, y, x;
1113 ret = gnutls_x509_privkey_export_dsa_raw (key, &p, &q, &g, &y, &x);
1114 if (ret < 0)
1116 fprintf (stderr, "Error in key DSA data export: %s\n",
1117 gnutls_strerror (ret));
1120 fprintf (outfile, "private key:");
1121 print_hex_datum (&x);
1122 fprintf (outfile, "public key:");
1123 print_hex_datum (&y);
1124 fprintf (outfile, "p:");
1125 print_hex_datum (&p);
1126 fprintf (outfile, "q:");
1127 print_hex_datum (&q);
1128 fprintf (outfile, "g:");
1129 print_hex_datum (&g);
1132 fprintf (outfile, "\n");
1134 size = sizeof (buffer);
1135 if ((ret = gnutls_x509_privkey_get_key_id (key, 0, buffer, &size)) < 0)
1137 fprintf (stderr, "Error in key id calculation: %s\n",
1138 gnutls_strerror (ret));
1140 else
1142 fprintf (outfile, "Public Key ID: %s\n", raw_to_string (buffer, size));
1145 if (info.fix_key != 0)
1147 ret = gnutls_x509_privkey_fix (key);
1148 if (ret < 0)
1149 error (EXIT_FAILURE, 0, "privkey_fix: %s", gnutls_strerror (ret));
1152 size = sizeof (buffer);
1153 ret = gnutls_x509_privkey_export (key, GNUTLS_X509_FMT_PEM, buffer, &size);
1154 if (ret < 0)
1155 error (EXIT_FAILURE, 0, "Export error: %s", gnutls_strerror (ret));
1157 fprintf (outfile, "\n%s\n", buffer);
1160 /* Load the private key.
1161 * @mand should be non zero if it is required to read a private key.
1163 gnutls_x509_privkey
1164 load_private_key (int mand)
1166 gnutls_x509_privkey key;
1167 int ret;
1168 gnutls_datum dat;
1169 size_t size;
1171 if (!info.privkey && !mand)
1172 return NULL;
1174 if (info.privkey == NULL)
1175 error (EXIT_FAILURE, 0, "missing --load-privkey");
1177 ret = gnutls_x509_privkey_init (&key);
1178 if (ret < 0)
1179 error (EXIT_FAILURE, 0, "privkey_init: %s", gnutls_strerror (ret));
1181 dat.data = read_binary_file (info.privkey, &size);
1182 dat.size = size;
1184 if (!dat.data)
1185 error (EXIT_FAILURE, errno, "reading --load-privkey: %s",
1186 info.privkey);
1188 if (info.pkcs8)
1190 const char *pass = get_pass ();
1191 ret = gnutls_x509_privkey_import_pkcs8 (key, &dat, info.incert_format,
1192 pass, 0);
1194 else
1195 ret = gnutls_x509_privkey_import (key, &dat, info.incert_format);
1196 free (dat.data);
1197 if (ret < 0)
1198 error (EXIT_FAILURE, 0, "importing --load-privkey: %s: %s",
1199 info.privkey, gnutls_strerror (ret));
1201 return key;
1204 /* Load the Certificate Request.
1206 gnutls_x509_crq
1207 load_request (void)
1209 gnutls_x509_crq crq;
1210 int ret;
1211 gnutls_datum dat;
1212 size_t size;
1214 if (!info.request)
1215 return NULL;
1217 ret = gnutls_x509_crq_init (&crq);
1218 if (ret < 0)
1219 error (EXIT_FAILURE, 0, "crq_init: %s", gnutls_strerror (ret));
1221 dat.data = read_binary_file (info.request, &size);
1222 dat.size = size;
1224 if (!dat.data)
1225 error (EXIT_FAILURE, errno, "reading --load-request: %s",
1226 info.request);
1228 ret = gnutls_x509_crq_import (crq, &dat, info.incert_format);
1229 free (dat.data);
1230 if (ret < 0)
1231 error (EXIT_FAILURE, 0, "importing --load-request: %s: %s",
1232 info.request, gnutls_strerror (ret));
1234 return crq;
1237 /* Load the CA's private key.
1239 gnutls_x509_privkey
1240 load_ca_private_key (void)
1242 gnutls_x509_privkey key;
1243 int ret;
1244 gnutls_datum dat;
1245 size_t size;
1247 if (info.ca_privkey == NULL)
1248 error (EXIT_FAILURE, 0, "missing --load-ca-privkey");
1250 ret = gnutls_x509_privkey_init (&key);
1251 if (ret < 0)
1252 error (EXIT_FAILURE, 0, "privkey_init: %s", gnutls_strerror (ret));
1254 dat.data = read_binary_file (info.ca_privkey, &size);
1255 dat.size = size;
1257 if (!dat.data)
1258 error (EXIT_FAILURE, errno, "reading --load-ca-privkey: %s",
1259 info.ca_privkey);
1261 if (info.pkcs8)
1263 const char *pass = get_pass ();
1264 ret = gnutls_x509_privkey_import_pkcs8 (key, &dat, info.incert_format,
1265 pass, 0);
1267 else
1268 ret = gnutls_x509_privkey_import (key, &dat, info.incert_format);
1269 free (dat.data);
1270 if (ret < 0)
1271 error (EXIT_FAILURE, 0, "importing --load-ca-privkey: %s: %s",
1272 info.ca_privkey, gnutls_strerror (ret));
1274 return key;
1277 /* Loads the CA's certificate
1279 gnutls_x509_crt
1280 load_ca_cert (void)
1282 gnutls_x509_crt crt;
1283 int ret;
1284 gnutls_datum dat;
1285 size_t size;
1287 if (info.ca == NULL)
1288 error (EXIT_FAILURE, 0, "missing --load-ca-certificate");
1290 ret = gnutls_x509_crt_init (&crt);
1291 if (ret < 0)
1292 error (EXIT_FAILURE, 0, "crt_init: %s", gnutls_strerror (ret));
1294 dat.data = read_binary_file (info.ca, &size);
1295 dat.size = size;
1297 if (!dat.data)
1298 error (EXIT_FAILURE, errno, "reading --load-ca-certificate: %s",
1299 info.ca);
1301 ret = gnutls_x509_crt_import (crt, &dat, info.incert_format);
1302 free (dat.data);
1303 if (ret < 0)
1304 error (EXIT_FAILURE, 0, "importing --load-ca-certificate: %s: %s",
1305 info.ca, gnutls_strerror (ret));
1307 return crt;
1310 /* Loads the certificate
1311 * If mand is non zero then a certificate is mandatory. Otherwise
1312 * null will be returned if the certificate loading fails.
1314 gnutls_x509_crt
1315 load_cert (int mand)
1317 gnutls_x509_crt *crt;
1318 int size;
1320 crt = load_cert_list (mand, &size);
1322 return crt ? crt[0] : NULL;
1325 #define MAX_CERTS 256
1327 /* Loads a certificate list
1329 gnutls_x509_crt *
1330 load_cert_list (int mand, int *crt_size)
1332 FILE *fd;
1333 static gnutls_x509_crt crt[MAX_CERTS];
1334 char *ptr;
1335 int ret, i;
1336 gnutls_datum dat;
1337 size_t size;
1338 int ptr_size;
1340 *crt_size = 0;
1341 fprintf (stderr, "Loading certificate list...\n");
1343 if (info.cert == NULL)
1345 if (mand)
1346 error (EXIT_FAILURE, 0, "missing --load-certificate");
1347 else
1348 return NULL;
1351 fd = fopen (info.cert, "r");
1352 if (fd == NULL)
1353 error (EXIT_FAILURE, 0, "File %s does not exist", info.cert);
1355 size = fread (buffer, 1, sizeof (buffer) - 1, fd);
1356 buffer[size] = 0;
1358 fclose (fd);
1360 ptr = buffer;
1361 ptr_size = size;
1363 for (i = 0; i < MAX_CERTS; i++)
1365 ret = gnutls_x509_crt_init (&crt[i]);
1366 if (ret < 0)
1367 error (EXIT_FAILURE, 0, "crt_init: %s", gnutls_strerror (ret));
1369 dat.data = ptr;
1370 dat.size = ptr_size;
1372 ret = gnutls_x509_crt_import (crt[i], &dat, info.incert_format);
1373 if (ret < 0 && *crt_size > 0)
1374 break;
1375 if (ret < 0)
1376 error (EXIT_FAILURE, 0, "crt_import: %s", gnutls_strerror (ret));
1378 ptr = strstr (ptr, "---END");
1379 if (ptr == NULL)
1380 break;
1381 ptr++;
1383 ptr_size = size;
1384 ptr_size -=
1385 (unsigned int) ((unsigned char *) ptr - (unsigned char *) buffer);
1387 if (ptr_size < 0)
1388 break;
1390 (*crt_size)++;
1392 fprintf (stderr, "Loaded %d certificates.\n", *crt_size);
1394 return crt;
1398 /* Generate a PKCS #10 certificate request.
1400 void
1401 generate_request (void)
1403 gnutls_x509_crq crq;
1404 gnutls_x509_privkey key;
1405 int ret;
1406 const char *pass;
1407 size_t size;
1409 fprintf (stderr, "Generating a PKCS #10 certificate request...\n");
1411 ret = gnutls_x509_crq_init (&crq);
1412 if (ret < 0)
1413 error (EXIT_FAILURE, 0, "crq_init: %s", gnutls_strerror (ret));
1415 /* Load the private key.
1417 key = load_private_key (0);
1418 if (!key)
1419 key = generate_private_key_int ();
1421 /* Set the DN.
1423 get_country_crq_set (crq);
1424 get_organization_crq_set (crq);
1425 get_unit_crq_set (crq);
1426 get_locality_crq_set (crq);
1427 get_state_crq_set (crq);
1428 get_cn_crq_set (crq);
1429 get_uid_crq_set (crq);
1430 get_oid_crq_set (crq);
1432 ret = gnutls_x509_crq_set_version (crq, 1);
1433 if (ret < 0)
1434 error (EXIT_FAILURE, 0, "set_version: %s", gnutls_strerror (ret));
1436 pass = get_challenge_pass ();
1438 if (pass != NULL)
1440 ret = gnutls_x509_crq_set_challenge_password (crq, pass);
1441 if (ret < 0)
1442 error (EXIT_FAILURE, 0, "set_pass: %s", gnutls_strerror (ret));
1445 ret = gnutls_x509_crq_set_key (crq, key);
1446 if (ret < 0)
1447 error (EXIT_FAILURE, 0, "set_key: %s", gnutls_strerror (ret));
1449 ret = gnutls_x509_crq_sign (crq, key);
1450 if (ret < 0)
1451 error (EXIT_FAILURE, 0, "sign: %s", gnutls_strerror (ret));
1453 size = sizeof (buffer);
1454 ret = gnutls_x509_crq_export (crq, info.outcert_format, buffer, &size);
1455 if (ret < 0)
1456 error (EXIT_FAILURE, 0, "export: %s", gnutls_strerror (ret));
1458 fwrite (buffer, 1, size, outfile);
1460 gnutls_x509_crq_deinit (crq);
1461 gnutls_x509_privkey_deinit (key);
1465 static void print_verification_res (gnutls_x509_crt crt,
1466 gnutls_x509_crt issuer,
1467 gnutls_x509_crl * crl_list,
1468 int crl_list_size);
1470 #define CERT_SEP "-----BEGIN CERT"
1471 #define CRL_SEP "-----BEGIN X509 CRL"
1473 _verify_x509_mem (const void *cert, int cert_size)
1475 int siz, i;
1476 const char *ptr;
1477 int ret;
1478 char name[256];
1479 char issuer_name[256];
1480 size_t name_size;
1481 size_t issuer_name_size;
1482 gnutls_datum tmp;
1483 gnutls_x509_crt *x509_cert_list = NULL;
1484 gnutls_x509_crl *x509_crl_list = NULL;
1485 int x509_ncerts, x509_ncrls;
1488 /* Decode the CA certificate
1491 /* Decode the CRL list
1493 siz = cert_size;
1494 ptr = cert;
1496 i = 1;
1498 if (strstr (ptr, CRL_SEP) != NULL) /* if CRLs exist */
1501 x509_crl_list =
1502 (gnutls_x509_crl *) realloc (x509_crl_list,
1503 i * sizeof (gnutls_x509_crl));
1504 if (x509_crl_list == NULL)
1505 error (EXIT_FAILURE, 0, "memory error");
1507 tmp.data = (char *) ptr;
1508 tmp.size = siz;
1510 ret = gnutls_x509_crl_init (&x509_crl_list[i - 1]);
1511 if (ret < 0)
1512 error (EXIT_FAILURE, 0, "Error parsing the CRL[%d]: %s", i,
1513 gnutls_strerror (ret));
1515 ret = gnutls_x509_crl_import (x509_crl_list[i - 1], &tmp,
1516 GNUTLS_X509_FMT_PEM);
1517 if (ret < 0)
1518 error (EXIT_FAILURE, 0, "Error parsing the CRL[%d]: %s", i,
1519 gnutls_strerror (ret));
1521 /* now we move ptr after the pem header */
1522 ptr = strstr (ptr, CRL_SEP);
1523 if (ptr != NULL)
1524 ptr++;
1526 i++;
1528 while ((ptr = strstr (ptr, CRL_SEP)) != NULL);
1530 x509_ncrls = i - 1;
1533 /* Decode the certificate chain.
1535 siz = cert_size;
1536 ptr = cert;
1538 i = 1;
1542 x509_cert_list =
1543 (gnutls_x509_crt *) realloc (x509_cert_list,
1544 i * sizeof (gnutls_x509_crt));
1545 if (x509_cert_list == NULL)
1546 error (EXIT_FAILURE, 0, "memory error");
1548 tmp.data = (char *) ptr;
1549 tmp.size = siz;
1551 ret = gnutls_x509_crt_init (&x509_cert_list[i - 1]);
1552 if (ret < 0)
1553 error (EXIT_FAILURE, 0, "Error parsing the certificate[%d]: %s", i,
1554 gnutls_strerror (ret));
1556 ret =
1557 gnutls_x509_crt_import (x509_cert_list[i - 1], &tmp,
1558 GNUTLS_X509_FMT_PEM);
1559 if (ret < 0)
1560 error (EXIT_FAILURE, 0, "Error parsing the certificate[%d]: %s", i,
1561 gnutls_strerror (ret));
1564 if (i - 1 != 0)
1566 /* verify the previous certificate using this one
1567 * as CA.
1570 name_size = sizeof (name);
1571 ret =
1572 gnutls_x509_crt_get_dn (x509_cert_list[i - 2], name, &name_size);
1573 if (ret < 0)
1574 error (EXIT_FAILURE, 0, "get_dn: %s", gnutls_strerror (ret));
1576 fprintf (outfile, "Certificate[%d]: %s\n", i - 2, name);
1578 /* print issuer
1580 issuer_name_size = sizeof (issuer_name);
1581 ret =
1582 gnutls_x509_crt_get_issuer_dn (x509_cert_list[i - 2],
1583 issuer_name, &issuer_name_size);
1584 if (ret < 0)
1585 error (EXIT_FAILURE, 0, "get_issuer_dn: %s", gnutls_strerror (ret));
1587 fprintf (outfile, "\tIssued by: %s\n", issuer_name);
1589 /* Get the Issuer's name
1591 name_size = sizeof (name);
1592 ret =
1593 gnutls_x509_crt_get_dn (x509_cert_list[i - 1], name, &name_size);
1594 if (ret < 0)
1595 error (EXIT_FAILURE, 0, "get_dn: %s", gnutls_strerror (ret));
1597 fprintf (outfile, "\tVerifying against certificate[%d].\n", i - 1);
1599 if (strcmp (issuer_name, name) != 0)
1601 fprintf (stderr, "Error: Issuer's name: %s\n", name);
1602 error (EXIT_FAILURE, 0,
1603 "Issuer's name does not match the next certificate");
1606 fprintf (outfile, "\tVerification output: ");
1607 print_verification_res (x509_cert_list[i - 2],
1608 x509_cert_list[i - 1], x509_crl_list,
1609 x509_ncrls);
1610 fprintf (outfile, ".\n\n");
1615 /* now we move ptr after the pem header
1617 ptr = strstr (ptr, CERT_SEP);
1618 if (ptr != NULL)
1619 ptr++;
1621 i++;
1623 while ((ptr = strstr (ptr, CERT_SEP)) != NULL);
1625 x509_ncerts = i - 1;
1627 /* The last certificate in the list will be used as
1628 * a CA (should be self signed).
1630 name_size = sizeof (name);
1631 ret = gnutls_x509_crt_get_dn (x509_cert_list[x509_ncerts - 1], name,
1632 &name_size);
1633 if (ret < 0)
1634 error (EXIT_FAILURE, 0, "get_dn: %s", gnutls_strerror (ret));
1636 fprintf (outfile, "Certificate[%d]: %s\n", x509_ncerts - 1, name);
1638 /* print issuer
1640 issuer_name_size = sizeof (issuer_name);
1641 ret =
1642 gnutls_x509_crt_get_issuer_dn (x509_cert_list[x509_ncerts - 1],
1643 issuer_name, &issuer_name_size);
1644 if (ret < 0)
1645 error (EXIT_FAILURE, 0, "get_issuer_dn: %s", gnutls_strerror (ret));
1647 fprintf (outfile, "\tIssued by: %s\n", name);
1649 if (strcmp (issuer_name, name) != 0)
1650 error (EXIT_FAILURE, 0, "Error: The last certificate is not self signed.");
1652 fprintf (outfile, "\tVerification output: ");
1653 print_verification_res (x509_cert_list[x509_ncerts - 1],
1654 x509_cert_list[x509_ncerts - 1], x509_crl_list,
1655 x509_ncrls);
1657 fprintf (outfile, ".\n\n");
1659 for (i = 0; i < x509_ncerts; i++)
1660 gnutls_x509_crt_deinit (x509_cert_list[i]);
1662 for (i = 0; i < x509_ncrls; i++)
1663 gnutls_x509_crl_deinit (x509_crl_list[i]);
1665 free (x509_cert_list);
1666 free (x509_crl_list);
1668 if (ret < 0)
1669 error (EXIT_FAILURE, 0, "Error in verification: %s", gnutls_strerror (ret));
1671 return 0;
1674 static void
1675 print_verification_res (gnutls_x509_crt crt,
1676 gnutls_x509_crt issuer,
1677 gnutls_x509_crl * crl_list, int crl_list_size)
1679 unsigned int output;
1680 int comma = 0;
1681 int ret;
1682 time_t now = time (0);
1684 ret = gnutls_x509_crt_verify (crt, &issuer, 1, 0, &output);
1685 if (ret < 0)
1686 error (EXIT_FAILURE, 0, "Error in verification: %s",
1687 gnutls_strerror (ret));
1689 if (output & GNUTLS_CERT_INVALID)
1691 fprintf (outfile, "Not verified");
1692 comma = 1;
1694 else
1696 fprintf (outfile, "Verified");
1697 comma = 1;
1700 if (output & GNUTLS_CERT_SIGNER_NOT_CA)
1702 if (comma)
1703 fprintf (outfile, ", ");
1704 fprintf (outfile, "Issuer is not a CA");
1705 comma = 1;
1708 if (output & GNUTLS_CERT_INSECURE_ALGORITHM)
1710 if (comma)
1711 fprintf (outfile, ", ");
1712 fprintf (outfile, "Insecure algorithm");
1713 comma = 1;
1716 /* Check expiration dates.
1719 if (gnutls_x509_crt_get_activation_time (crt) > now)
1721 if (comma)
1722 fprintf (outfile, ", ");
1723 comma = 1;
1724 fprintf (outfile, "Not activated");
1727 if (gnutls_x509_crt_get_expiration_time (crt) < now)
1729 if (comma)
1730 fprintf (outfile, ", ");
1731 comma = 1;
1732 fprintf (outfile, "Expired");
1735 ret = gnutls_x509_crt_check_revocation (crt, crl_list, crl_list_size);
1736 if (ret < 0)
1737 error (EXIT_FAILURE, 0, "Revocation check: %s", gnutls_strerror (ret));
1739 if (ret == 1)
1740 { /* revoked */
1741 if (comma)
1742 fprintf (outfile, ", ");
1743 comma = 1;
1744 fprintf (outfile, "Revoked");
1748 void
1749 verify_chain (void)
1751 size_t size;
1753 size = fread (buffer, 1, sizeof (buffer) - 1, infile);
1754 buffer[size] = 0;
1756 _verify_x509_mem (buffer, size);
1760 void
1761 verify_crl (void)
1763 size_t size, dn_size;
1764 char dn[128];
1765 unsigned int output;
1766 int comma = 0;
1767 int ret;
1768 gnutls_datum pem;
1769 gnutls_x509_crl crl;
1770 time_t now = time (0);
1771 gnutls_x509_crt issuer;
1773 issuer = load_ca_cert ();
1775 fprintf (outfile, "\nCA certificate:\n");
1777 dn_size = sizeof (dn);
1778 ret = gnutls_x509_crt_get_dn (issuer, dn, &dn_size);
1779 if (ret < 0)
1780 error (EXIT_FAILURE, 0, "crt_get_dn: %s", gnutls_strerror (ret));
1782 fprintf (outfile, "\tSubject: %s\n\n", dn);
1784 ret = gnutls_x509_crl_init (&crl);
1785 if (ret < 0)
1786 error (EXIT_FAILURE, 0, "crl_init: %s", gnutls_strerror (ret));
1788 pem.data = fread_file (infile, &size);
1789 pem.size = size;
1791 ret = gnutls_x509_crl_import (crl, &pem, info.incert_format);
1792 free (pem.data);
1793 if (ret < 0)
1794 error (EXIT_FAILURE, 0, "Import error: %s", gnutls_strerror (ret));
1796 print_crl_info (crl, outfile);
1798 fprintf (outfile, "Verification output: ");
1799 ret = gnutls_x509_crl_verify (crl, &issuer, 1, 0, &output);
1800 if (ret < 0)
1801 error (EXIT_FAILURE, 0, "Verification error: %s", gnutls_strerror (ret));
1803 if (output & GNUTLS_CERT_INVALID)
1805 fprintf (outfile, "Not verified");
1806 comma = 1;
1808 else
1810 fprintf (outfile, "Verified");
1811 comma = 1;
1814 if (output & GNUTLS_CERT_SIGNER_NOT_CA)
1816 if (comma)
1817 fprintf (outfile, ", ");
1818 fprintf (outfile, "Issuer is not a CA");
1819 comma = 1;
1822 if (output & GNUTLS_CERT_INSECURE_ALGORITHM)
1824 if (comma)
1825 fprintf (outfile, ", ");
1826 fprintf (outfile, "Insecure algorithm");
1827 comma = 1;
1830 /* Check expiration dates.
1833 if (gnutls_x509_crl_get_this_update (crl) > now)
1835 if (comma)
1836 fprintf (outfile, ", ");
1837 comma = 1;
1838 fprintf (outfile, "Issued in the future!");
1841 if (gnutls_x509_crl_get_next_update (crl) < now)
1843 if (comma)
1844 fprintf (outfile, ", ");
1845 comma = 1;
1846 fprintf (outfile, "CRL is not up to date");
1849 fprintf (outfile, "\n");
1852 #include <gnutls/pkcs12.h>
1853 #include <unistd.h>
1855 void
1856 generate_pkcs12 (void)
1858 gnutls_pkcs12 pkcs12;
1859 gnutls_x509_crt *crts;
1860 gnutls_x509_privkey key;
1861 int result;
1862 size_t size;
1863 gnutls_datum data;
1864 const char *password;
1865 const char *name;
1866 unsigned int flags;
1867 gnutls_datum key_id;
1868 unsigned char _key_id[20];
1869 int index;
1870 int ncrts;
1871 int i;
1873 fprintf (stderr, "Generating a PKCS #12 structure...\n");
1875 key = load_private_key (0);
1876 crts = load_cert_list (0, &ncrts);
1878 name = get_pkcs12_key_name ();
1880 result = gnutls_pkcs12_init (&pkcs12);
1881 if (result < 0)
1882 error (EXIT_FAILURE, 0, "pkcs12_init: %s", gnutls_strerror (result));
1884 if (info.pass)
1885 password = info.pass;
1886 else
1887 password = get_pass ();
1889 for (i = 0; i < ncrts; i++)
1891 gnutls_pkcs12_bag bag;
1893 result = gnutls_pkcs12_bag_init (&bag);
1894 if (result < 0)
1895 error (EXIT_FAILURE, 0, "bag_init: %s", gnutls_strerror (result));
1897 result = gnutls_pkcs12_bag_set_crt (bag, crts[i]);
1898 if (result < 0)
1899 error (EXIT_FAILURE, 0, "set_crt[%d]: %s", i, gnutls_strerror (result));
1901 index = result;
1903 result = gnutls_pkcs12_bag_set_friendly_name (bag, index, name);
1904 if (result < 0)
1905 error (EXIT_FAILURE, 0, "bag_set_friendly_name: %s",
1906 gnutls_strerror (result));
1908 size = sizeof (_key_id);
1909 result = gnutls_x509_crt_get_key_id (crts[i], 0, _key_id, &size);
1910 if (result < 0)
1911 error (EXIT_FAILURE, 0, "key_id[%d]: %s", i, gnutls_strerror (result));
1913 key_id.data = _key_id;
1914 key_id.size = size;
1916 result = gnutls_pkcs12_bag_set_key_id (bag, index, &key_id);
1917 if (result < 0)
1918 error (EXIT_FAILURE, 0, "bag_set_key_id: %s", gnutls_strerror (result));
1920 if (info.export)
1921 flags = GNUTLS_PKCS_USE_PKCS12_RC2_40;
1922 else
1923 flags = GNUTLS_PKCS8_USE_PKCS12_3DES;
1925 result = gnutls_pkcs12_bag_encrypt (bag, password, flags);
1926 if (result < 0)
1927 error (EXIT_FAILURE, 0, "bag_encrypt: %s", gnutls_strerror (result));
1929 result = gnutls_pkcs12_set_bag (pkcs12, bag);
1930 if (result < 0)
1931 error (EXIT_FAILURE, 0, "set_bag: %s", gnutls_strerror (result));
1934 if (key)
1936 gnutls_pkcs12_bag kbag;
1938 result = gnutls_pkcs12_bag_init (&kbag);
1939 if (result < 0)
1940 error (EXIT_FAILURE, 0, "bag_init: %s", gnutls_strerror (result));
1942 if (info.export)
1943 flags = GNUTLS_PKCS_USE_PKCS12_RC2_40;
1944 else
1945 flags = GNUTLS_PKCS_USE_PKCS12_3DES;
1947 size = sizeof (buffer);
1948 result =
1949 gnutls_x509_privkey_export_pkcs8 (key, GNUTLS_X509_FMT_DER,
1950 password, flags, buffer, &size);
1951 if (result < 0)
1952 error (EXIT_FAILURE, 0, "key_export: %s", gnutls_strerror (result));
1954 data.data = buffer;
1955 data.size = size;
1956 result =
1957 gnutls_pkcs12_bag_set_data (kbag,
1958 GNUTLS_BAG_PKCS8_ENCRYPTED_KEY, &data);
1959 if (result < 0)
1960 error (EXIT_FAILURE, 0, "bag_set_data: %s", gnutls_strerror (result));
1962 index = result;
1964 result = gnutls_pkcs12_bag_set_friendly_name (kbag, index, name);
1965 if (result < 0)
1966 error (EXIT_FAILURE, 0, "bag_set_friendly_name: %s",
1967 gnutls_strerror (result));
1969 size = sizeof (_key_id);
1970 result = gnutls_x509_privkey_get_key_id (key, 0, _key_id, &size);
1971 if (result < 0)
1972 error (EXIT_FAILURE, 0, "key_id: %s", gnutls_strerror (result));
1974 key_id.data = _key_id;
1975 key_id.size = size;
1977 result = gnutls_pkcs12_bag_set_key_id (kbag, index, &key_id);
1978 if (result < 0)
1979 error (EXIT_FAILURE, 0, "bag_set_key_id: %s", gnutls_strerror (result));
1981 result = gnutls_pkcs12_set_bag (pkcs12, kbag);
1982 if (result < 0)
1983 error (EXIT_FAILURE, 0, "set_bag: %s", gnutls_strerror (result));
1986 result = gnutls_pkcs12_generate_mac (pkcs12, password);
1987 if (result < 0)
1988 error (EXIT_FAILURE, 0, "generate_mac: %s", gnutls_strerror (result));
1990 size = sizeof (buffer);
1991 result = gnutls_pkcs12_export (pkcs12, info.outcert_format, buffer, &size);
1992 if (result < 0)
1993 error (EXIT_FAILURE, 0, "pkcs12_export: %s", gnutls_strerror (result));
1995 fwrite (buffer, 1, size, outfile);
1999 const char *
2000 BAGTYPE (gnutls_pkcs12_bag_type x)
2002 switch (x)
2004 case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
2005 return "PKCS #8 Encrypted key";
2006 case GNUTLS_BAG_EMPTY:
2007 return "Empty";
2008 case GNUTLS_BAG_PKCS8_KEY:
2009 return "PKCS #8 Key";
2010 case GNUTLS_BAG_CERTIFICATE:
2011 return "Certificate";
2012 case GNUTLS_BAG_ENCRYPTED:
2013 return "Encrypted";
2014 case GNUTLS_BAG_CRL:
2015 return "CRL";
2016 default:
2017 return "Unknown";
2021 void
2022 print_bag_data (gnutls_pkcs12_bag bag)
2024 int result;
2025 int count, i, type;
2026 gnutls_datum cdata, id;
2027 const char *str, *name;
2028 gnutls_datum out;
2030 count = gnutls_pkcs12_bag_get_count (bag);
2031 if (count < 0)
2032 error (EXIT_FAILURE, 0, "get_count: %s", gnutls_strerror (count));
2034 fprintf (outfile, "\tElements: %d\n", count);
2036 for (i = 0; i < count; i++)
2038 type = gnutls_pkcs12_bag_get_type (bag, i);
2039 if (type < 0)
2040 error (EXIT_FAILURE, 0, "get_type: %s", gnutls_strerror (type));
2042 fprintf (stderr, "\tType: %s\n", BAGTYPE (type));
2044 name = NULL;
2045 result = gnutls_pkcs12_bag_get_friendly_name (bag, i, (char **) &name);
2046 if (result < 0)
2047 error (EXIT_FAILURE, 0, "get_friendly_name: %s",
2048 gnutls_strerror (type));
2049 if (name)
2050 fprintf (outfile, "\tFriendly name: %s\n", name);
2052 id.data = NULL;
2053 id.size = 0;
2054 result = gnutls_pkcs12_bag_get_key_id (bag, i, &id);
2055 if (result < 0)
2056 error (EXIT_FAILURE, 0, "get_key_id: %s", gnutls_strerror (type));
2057 fprintf (outfile, "\tKey ID: %s\n", raw_to_string (id.data, id.size));
2059 result = gnutls_pkcs12_bag_get_data (bag, i, &cdata);
2060 if (result < 0)
2061 error (EXIT_FAILURE, 0, "get_data: %s", gnutls_strerror (result));
2063 switch (type)
2065 case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
2066 str = "ENCRYPTED PRIVATE KEY";
2067 break;
2068 case GNUTLS_BAG_PKCS8_KEY:
2069 str = "PRIVATE KEY";
2070 break;
2071 case GNUTLS_BAG_CERTIFICATE:
2072 str = "CERTIFICATE";
2073 break;
2074 case GNUTLS_BAG_CRL:
2075 str = "CRL";
2076 break;
2077 case GNUTLS_BAG_ENCRYPTED:
2078 case GNUTLS_BAG_EMPTY:
2079 default:
2080 str = NULL;
2083 if (str != NULL)
2085 gnutls_pem_base64_encode_alloc (str, &cdata, &out);
2086 fprintf (outfile, "%s\n", out.data);
2088 gnutls_free (out.data);
2094 void
2095 pkcs12_info (void)
2097 gnutls_pkcs12 pkcs12;
2098 gnutls_pkcs12_bag bag;
2099 int result;
2100 size_t size;
2101 gnutls_datum data;
2102 const char *password;
2103 int index;
2105 result = gnutls_pkcs12_init (&pkcs12);
2106 if (result < 0)
2107 error (EXIT_FAILURE, 0, "p12_init: %s", gnutls_strerror (result));
2109 data.data = fread_file (infile, &size);
2110 data.size = size;
2112 result = gnutls_pkcs12_import (pkcs12, &data, info.incert_format, 0);
2113 free (data.data);
2114 if (result < 0)
2115 error (EXIT_FAILURE, 0, "p12_import: %s", gnutls_strerror (result));
2117 if (info.pass)
2118 password = info.pass;
2119 else
2120 password = get_pass ();
2122 result = gnutls_pkcs12_verify_mac (pkcs12, password);
2123 if (result < 0)
2124 error (EXIT_FAILURE, 0, "verify_mac: %s", gnutls_strerror (result));
2126 index = 0;
2128 for (index = 0; ; index++)
2130 result = gnutls_pkcs12_bag_init (&bag);
2131 if (result < 0)
2132 error (EXIT_FAILURE, 0, "bag_init: %s", gnutls_strerror (result));
2134 result = gnutls_pkcs12_get_bag (pkcs12, index, bag);
2135 if (result < 0)
2136 break;
2138 result = gnutls_pkcs12_bag_get_count (bag);
2139 if (result < 0)
2140 error (EXIT_FAILURE, 0, "bag_count: %s", gnutls_strerror (result));
2142 fprintf (outfile, "BAG #%d\n", index);
2144 result = gnutls_pkcs12_bag_get_type (bag, 0);
2145 if (result < 0)
2146 error (EXIT_FAILURE, 0, "bag_init: %s", gnutls_strerror (result));
2148 if (result == GNUTLS_BAG_ENCRYPTED)
2150 fprintf (stderr, "\tType: %s\n", BAGTYPE (result));
2151 fprintf (stderr, "\n\tDecrypting...\n");
2153 result = gnutls_pkcs12_bag_decrypt (bag, password);
2155 if (result < 0)
2156 error (EXIT_FAILURE, 0, "bag_decrypt: %s",
2157 gnutls_strerror (result));
2159 result = gnutls_pkcs12_bag_get_count (bag);
2160 if (result < 0)
2161 error (EXIT_FAILURE, 0, "encrypted bag_count: %s",
2162 gnutls_strerror (result));
2165 print_bag_data (bag);
2167 gnutls_pkcs12_bag_deinit (bag);
2171 void
2172 pkcs7_info (void)
2174 gnutls_pkcs7 pkcs7;
2175 int result;
2176 size_t size;
2177 gnutls_datum data, b64;
2178 int index, count;
2180 result = gnutls_pkcs7_init (&pkcs7);
2181 if (result < 0)
2182 error (EXIT_FAILURE, 0, "p7_init: %s", gnutls_strerror (result));
2184 data.data = fread_file (infile, &size);
2185 data.size = size;
2187 result = gnutls_pkcs7_import (pkcs7, &data, info.incert_format);
2188 free (data.data);
2189 if (result < 0)
2190 error (EXIT_FAILURE, 0, "Import error: %s", gnutls_strerror (result));
2192 /* Read and print the certificates.
2194 result = gnutls_pkcs7_get_crt_count (pkcs7);
2195 if (result < 0)
2196 error (EXIT_FAILURE, 0, "p7_crt_count: %s", gnutls_strerror (result));
2198 count = result;
2200 if (count > 0)
2201 fprintf (outfile, "Number of certificates: %u\n", count);
2203 for (index = 0; index < count; index++)
2205 fputs ("\n", outfile);
2207 size = sizeof (buffer);
2208 result = gnutls_pkcs7_get_crt_raw (pkcs7, index, buffer, &size);
2209 if (result < 0)
2210 break;
2212 data.data = buffer;
2213 data.size = size;
2215 result = gnutls_pem_base64_encode_alloc ("CERTIFICATE", &data, &b64);
2216 if (result < 0)
2217 error (EXIT_FAILURE, 0, "encoding: %s", gnutls_strerror (result));
2219 fputs (b64.data, outfile);
2220 gnutls_free (b64.data);
2223 /* Read the CRLs now.
2225 result = gnutls_pkcs7_get_crl_count (pkcs7);
2226 if (result < 0)
2227 error (EXIT_FAILURE, 0, "p7_crl_count: %s", gnutls_strerror (result));
2229 count = result;
2231 if (count > 0)
2232 fprintf (outfile, "\nNumber of CRLs: %u\n", count);
2234 for (index = 0; index < count; index++)
2236 fputs ("\n", outfile);
2238 size = sizeof (buffer);
2239 result = gnutls_pkcs7_get_crl_raw (pkcs7, index, buffer, &size);
2240 if (result < 0)
2241 break;
2243 data.data = buffer;
2244 data.size = size;
2246 result = gnutls_pem_base64_encode_alloc ("X509 CRL", &data, &b64);
2247 if (result < 0)
2248 error (EXIT_FAILURE, 0, "encoding: %s", gnutls_strerror (result));
2250 fputs (b64.data, outfile);
2251 gnutls_free (b64.data);
2255 void
2256 smime_to_pkcs7 (void)
2258 size_t linesize = 0;
2259 char *lineptr = NULL;
2260 ssize_t len;
2262 /* Find body. FIXME: Handle non-b64 Content-Transfer-Encoding.
2263 Reject non-S/MIME tagged Content-Type's? */
2266 len = getline (&lineptr, &linesize, infile);
2267 if (len == -1)
2268 error (EXIT_FAILURE, 0, "Cannot find RFC 2822 header/body separator");
2270 while (strcmp (lineptr, "\r\n") != 0 && strcmp (lineptr, "\n") != 0);
2274 len = getline (&lineptr, &linesize, infile);
2275 if (len == -1)
2276 error (EXIT_FAILURE, 0, "Message has RFC 2822 header but no body");
2278 while (strcmp (lineptr, "\r\n") == 0 && strcmp (lineptr, "\n") == 0);
2280 printf ("-----BEGIN PKCS7-----\n");
2284 while (len > 0
2285 && (lineptr[len - 1] == '\r' || lineptr[len - 1] == '\n'))
2286 lineptr[--len] = '\0';
2287 if (strcmp (lineptr, "") != 0)
2288 printf ("%s\n", lineptr);
2289 len = getline (&lineptr, &linesize, infile);
2291 while (len != -1);
2293 printf ("-----END PKCS7-----\n");
2295 free (lineptr);
2298 void
2299 certtool_version (void)
2301 version_etc (stdout, program_name, PACKAGE_STRING,
2302 gnutls_check_version (NULL), "Nikos Mavroyanopoulos",
2303 "Simon Josefsson", (char*) NULL);