Update gnulib files.
[gnutls.git] / src / certtool.c
blob96e2642c41d09ffd30bd5af22e28041c5301d520
1 /*
2 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
4 * This file is part of GNUTLS.
6 * GNUTLS is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GNUTLS is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see
18 * <http://www.gnu.org/licenses/>.
21 #include <config.h>
23 #include <gnutls/gnutls.h>
24 #include <gnutls/extra.h>
25 #include <gnutls/x509.h>
26 #include <gnutls/openpgp.h>
27 #include <gnutls/pkcs12.h>
29 #include <gcrypt.h>
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>
43 /* Gnulib portability files. */
44 #include <read-file.h>
45 #include <progname.h>
46 #include <version-etc.h>
48 #include <certtool-cfg.h>
49 #include "certtool-gaa.h"
50 #include "certtool-common.h"
52 static void print_crl_info (gnutls_x509_crl_t crl, FILE * out);
53 int generate_prime (int bits, int how);
54 void pkcs7_info (void);
55 void crq_info (void);
56 void smime_to_pkcs7 (void);
57 void pkcs12_info (void);
58 void generate_pkcs12 (void);
59 void generate_pkcs8 (void);
60 void verify_chain (void);
61 void verify_crl (void);
62 void pgp_privkey_info (void);
63 void pgp_ring_info (void);
64 gnutls_x509_privkey_t load_private_key (int mand);
65 gnutls_x509_crq_t load_request (void);
66 gnutls_x509_privkey_t load_ca_private_key (void);
67 gnutls_x509_crt_t load_ca_cert (void);
68 gnutls_x509_crt_t load_cert (int mand);
69 void certificate_info (void);
70 void pgp_certificate_info (void);
71 void crl_info (void);
72 void privkey_info (void);
73 static void print_certificate_info (gnutls_x509_crt_t crt, FILE * out,
74 unsigned int);
75 static void gaa_parser (int argc, char **argv);
76 void generate_self_signed (void);
77 void generate_request (void);
78 gnutls_x509_crt_t *load_cert_list (int mand, size_t * size);
80 static void print_hex_datum (gnutls_datum_t * dat);
83 static gaainfo info;
84 FILE *outfile;
85 FILE *infile;
86 gnutls_digest_algorithm_t dig = GNUTLS_DIG_SHA1;
88 /* non interactive operation if set
90 int batch;
92 unsigned char buffer[64 * 1024];
93 const int buffer_size = sizeof (buffer);
95 static void
96 tls_log_func (int level, const char *str)
98 fprintf (stderr, "|<%d>| %s", level, str);
102 main (int argc, char **argv)
104 set_program_name (argv[0]);
105 cfg_init ();
106 gaa_parser (argc, argv);
108 return 0;
111 static const char *
112 raw_to_string (const unsigned char *raw, size_t raw_size)
114 static char buf[1024];
115 size_t i;
116 if (raw_size == 0)
117 return NULL;
119 if (raw_size * 3 + 1 >= sizeof (buf))
120 return NULL;
122 for (i = 0; i < raw_size; i++)
124 sprintf (&(buf[i * 3]), "%02X%s", raw[i],
125 (i == raw_size - 1) ? "" : ":");
127 buf[sizeof (buf) - 1] = '\0';
129 return buf;
132 static void
133 print_dsa_pkey (gnutls_datum_t * x, gnutls_datum_t * y, gnutls_datum_t * p,
134 gnutls_datum_t * q, gnutls_datum_t * g)
136 fprintf (outfile, "private key:");
137 print_hex_datum (x);
138 fprintf (outfile, "public key:");
139 print_hex_datum (y);
140 fprintf (outfile, "p:");
141 print_hex_datum (p);
142 fprintf (outfile, "q:");
143 print_hex_datum (q);
144 fprintf (outfile, "g:");
145 print_hex_datum (g);
148 static void
149 print_rsa_pkey (gnutls_datum_t * m, gnutls_datum_t * e, gnutls_datum_t * d,
150 gnutls_datum_t * p, gnutls_datum_t * q, gnutls_datum_t * u)
152 fprintf (outfile, "modulus:");
153 print_hex_datum (m);
154 fprintf (outfile, "public exponent:");
155 print_hex_datum (e);
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);
166 static gnutls_x509_privkey_t
167 generate_private_key_int (void)
169 gnutls_x509_privkey_t key;
170 int ret, key_type;
172 if (info.dsa)
174 key_type = GNUTLS_PK_DSA;
175 /* FIXME: Remove me once we depend on 1.3.x */
176 if (info.bits > 1024 && gcry_check_version ("1.3.1") == NULL)
177 info.bits = 1024;
179 else
180 key_type = GNUTLS_PK_RSA;
182 ret = gnutls_x509_privkey_init (&key);
183 if (ret < 0)
184 error (EXIT_FAILURE, 0, "privkey_init: %s", gnutls_strerror (ret));
186 fprintf (stderr, "Generating a %d bit %s private key...\n", info.bits,
187 gnutls_pk_algorithm_get_name (key_type));
189 if (info.quick_random == 0)
190 fprintf (stderr,
191 "This might take several minutes depending on availability of randomness"
192 " in /dev/random.\n");
194 ret = gnutls_x509_privkey_generate (key, key_type, info.bits, 0);
195 if (ret < 0)
196 error (EXIT_FAILURE, 0, "privkey_generate: %s", gnutls_strerror (ret));
198 return key;
201 static void
202 print_private_key (gnutls_x509_privkey_t key)
204 int ret;
205 size_t size;
207 if (!key)
208 return;
210 if (!info.pkcs8)
212 size = sizeof (buffer);
213 ret = gnutls_x509_privkey_export (key, info.outcert_format,
214 buffer, &size);
215 if (ret < 0)
216 error (EXIT_FAILURE, 0, "privkey_export: %s", gnutls_strerror (ret));
218 else
220 unsigned int flags;
221 const char *pass;
223 if (info.export)
224 flags = GNUTLS_PKCS_USE_PKCS12_RC2_40;
225 else
226 flags = GNUTLS_PKCS_USE_PKCS12_3DES;
228 if ((pass = get_confirmed_pass (true)) == NULL || *pass == '\0')
229 flags = GNUTLS_PKCS_PLAIN;
231 size = sizeof (buffer);
232 ret =
233 gnutls_x509_privkey_export_pkcs8 (key, info.outcert_format, pass,
234 flags, buffer, &size);
235 if (ret < 0)
236 error (EXIT_FAILURE, 0, "privkey_export_pkcs8: %s",
237 gnutls_strerror (ret));
240 fwrite (buffer, 1, size, outfile);
243 static void
244 generate_private_key (void)
246 gnutls_x509_privkey_t key;
248 key = generate_private_key_int ();
250 print_private_key (key);
252 gnutls_x509_privkey_deinit (key);
256 static gnutls_x509_crt_t
257 generate_certificate (gnutls_x509_privkey_t * ret_key,
258 gnutls_x509_crt_t ca_crt, int proxy)
260 gnutls_x509_crt_t crt;
261 gnutls_x509_privkey_t key = NULL;
262 size_t size;
263 int ret;
264 int client;
265 int days, result, ca_status = 0, path_len;
266 int vers;
267 unsigned int usage = 0, server;
268 gnutls_x509_crq_t crq; /* request */
270 ret = gnutls_x509_crt_init (&crt);
271 if (ret < 0)
272 error (EXIT_FAILURE, 0, "crt_init: %s", gnutls_strerror (ret));
274 crq = load_request ();
276 if (crq == NULL)
279 key = load_private_key (1);
281 if (!batch)
282 fprintf (stderr,
283 "Please enter the details of the certificate's distinguished name. "
284 "Just press enter to ignore a field.\n");
286 /* set the DN.
288 if (proxy)
290 result = gnutls_x509_crt_set_proxy_dn (crt, ca_crt, 0, NULL, 0);
291 if (result < 0)
292 error (EXIT_FAILURE, 0, "set_proxy_dn: %s",
293 gnutls_strerror (result));
295 get_cn_crt_set (crt);
297 else
299 get_country_crt_set (crt);
300 get_organization_crt_set (crt);
301 get_unit_crt_set (crt);
302 get_locality_crt_set (crt);
303 get_state_crt_set (crt);
304 get_cn_crt_set (crt);
305 get_uid_crt_set (crt);
306 get_oid_crt_set (crt);
307 get_key_purpose_set (crt);
309 if (!batch)
310 fprintf (stderr,
311 "This field should not be used in new certificates.\n");
313 get_pkcs9_email_crt_set (crt);
316 result = gnutls_x509_crt_set_key (crt, key);
317 if (result < 0)
318 error (EXIT_FAILURE, 0, "set_key: %s", gnutls_strerror (result));
320 else
322 result = gnutls_x509_crt_set_crq (crt, crq);
323 if (result < 0)
324 error (EXIT_FAILURE, 0, "set_crq: %s", gnutls_strerror (result));
329 int serial = get_serial ();
330 char bin_serial[5];
332 bin_serial[4] = serial & 0xff;
333 bin_serial[3] = (serial >> 8) & 0xff;
334 bin_serial[2] = (serial >> 16) & 0xff;
335 bin_serial[1] = (serial >> 24) & 0xff;
336 bin_serial[0] = 0;
338 result = gnutls_x509_crt_set_serial (crt, bin_serial, 5);
339 if (result < 0)
340 error (EXIT_FAILURE, 0, "serial: %s", gnutls_strerror (result));
343 if (!batch)
344 fprintf (stderr, "\n\nActivation/Expiration time.\n");
346 gnutls_x509_crt_set_activation_time (crt, time (NULL));
348 days = get_days ();
350 result =
351 gnutls_x509_crt_set_expiration_time (crt,
352 time (NULL) + days * 24 * 60 * 60);
353 if (result < 0)
354 error (EXIT_FAILURE, 0, "set_expiration: %s", gnutls_strerror (result));
356 if (!batch)
357 fprintf (stderr, "\n\nExtensions.\n");
359 /* do not allow extensions on a v1 certificate */
360 if (crq && get_crq_extensions_status () != 0)
362 result = gnutls_x509_crt_set_crq_extensions (crt, crq);
363 if (result < 0)
364 error (EXIT_FAILURE, 0, "set_crq: %s", gnutls_strerror (result));
367 /* append additional extensions */
368 if (info.v1_cert == 0)
371 if (proxy)
373 const char *policylanguage;
374 char *policy;
375 size_t policylen;
376 int proxypathlen = get_path_len ();
378 if (!batch)
380 printf ("1.3.6.1.5.5.7.21.1 ::= id-ppl-inheritALL\n");
381 printf ("1.3.6.1.5.5.7.21.2 ::= id-ppl-independent\n");
384 policylanguage = get_proxy_policy (&policy, &policylen);
386 result =
387 gnutls_x509_crt_set_proxy (crt, proxypathlen, policylanguage,
388 policy, policylen);
389 if (result < 0)
390 error (EXIT_FAILURE, 0, "set_proxy: %s",
391 gnutls_strerror (result));
394 if (!proxy)
395 ca_status = get_ca_status ();
396 if (ca_status)
397 path_len = get_path_len ();
398 else
399 path_len = -1;
401 result =
402 gnutls_x509_crt_set_basic_constraints (crt, ca_status, path_len);
403 if (result < 0)
404 error (EXIT_FAILURE, 0, "basic_constraints: %s",
405 gnutls_strerror (result));
407 client = get_tls_client_status ();
408 if (client != 0)
410 result = gnutls_x509_crt_set_key_purpose_oid (crt,
411 GNUTLS_KP_TLS_WWW_CLIENT,
413 if (result < 0)
414 error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (result));
417 server = get_tls_server_status ();
418 if (server != 0)
420 result = 0;
422 if (!proxy)
424 get_dns_name_set (TYPE_CRT, crt);
425 get_ip_addr_set (TYPE_CRT, crt);
428 result =
429 gnutls_x509_crt_set_key_purpose_oid (crt,
430 GNUTLS_KP_TLS_WWW_SERVER, 0);
431 if (result < 0)
432 error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (result));
434 else if (!proxy)
436 get_email_set (TYPE_CRT, crt);
439 if (!ca_status || server)
441 int pk;
444 pk = gnutls_x509_crt_get_pk_algorithm (crt, NULL);
446 if (pk != GNUTLS_PK_DSA)
447 { /* DSA keys can only sign.
449 result = get_sign_status (server);
450 if (result)
451 usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
453 result = get_encrypt_status (server);
454 if (result)
455 usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
457 else
458 usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
462 if (ca_status)
464 result = get_cert_sign_status ();
465 if (result)
466 usage |= GNUTLS_KEY_KEY_CERT_SIGN;
468 result = get_crl_sign_status ();
469 if (result)
470 usage |= GNUTLS_KEY_CRL_SIGN;
472 result = get_code_sign_status ();
473 if (result)
475 result =
476 gnutls_x509_crt_set_key_purpose_oid (crt,
477 GNUTLS_KP_CODE_SIGNING,
479 if (result < 0)
480 error (EXIT_FAILURE, 0, "key_kp: %s",
481 gnutls_strerror (result));
484 result = get_ocsp_sign_status ();
485 if (result)
487 result =
488 gnutls_x509_crt_set_key_purpose_oid (crt,
489 GNUTLS_KP_OCSP_SIGNING,
491 if (result < 0)
492 error (EXIT_FAILURE, 0, "key_kp: %s",
493 gnutls_strerror (result));
496 result = get_time_stamp_status ();
497 if (result)
499 result =
500 gnutls_x509_crt_set_key_purpose_oid (crt,
501 GNUTLS_KP_TIME_STAMPING,
503 if (result < 0)
504 error (EXIT_FAILURE, 0, "key_kp: %s",
505 gnutls_strerror (result));
509 if (usage != 0)
511 result = gnutls_x509_crt_set_key_usage (crt, usage);
512 if (result < 0)
513 error (EXIT_FAILURE, 0, "key_usage: %s",
514 gnutls_strerror (result));
517 /* Subject Key ID.
519 size = sizeof (buffer);
520 result = gnutls_x509_crt_get_key_id (crt, 0, buffer, &size);
521 if (result >= 0)
523 result = gnutls_x509_crt_set_subject_key_id (crt, buffer, size);
524 if (result < 0)
525 error (EXIT_FAILURE, 0, "set_subject_key_id: %s",
526 gnutls_strerror (result));
529 /* Authority Key ID.
531 if (ca_crt != NULL)
533 size = sizeof (buffer);
534 result = gnutls_x509_crt_get_subject_key_id (ca_crt, buffer,
535 &size, NULL);
536 if (result < 0)
538 size = sizeof (buffer);
539 result = gnutls_x509_crt_get_key_id (ca_crt, 0, buffer, &size);
541 if (result >= 0)
543 result =
544 gnutls_x509_crt_set_authority_key_id (crt, buffer, size);
545 if (result < 0)
546 error (EXIT_FAILURE, 0, "set_authority_key_id: %s",
547 gnutls_strerror (result));
552 /* Version.
554 if (info.v1_cert != 0)
555 vers = 1;
556 else
557 vers = 3;
558 result = gnutls_x509_crt_set_version (crt, vers);
559 if (result < 0)
560 error (EXIT_FAILURE, 0, "set_version: %s", gnutls_strerror (result));
562 *ret_key = key;
563 return crt;
567 static gnutls_x509_crl_t
568 generate_crl (gnutls_x509_crt_t ca_crt)
570 gnutls_x509_crl_t crl;
571 gnutls_x509_crt_t *crts;
572 size_t size;
573 int days, result;
574 unsigned int i;
575 time_t now = time (NULL);
577 result = gnutls_x509_crl_init (&crl);
578 if (result < 0)
579 error (EXIT_FAILURE, 0, "crl_init: %s", gnutls_strerror (result));
581 crts = load_cert_list (0, &size);
583 for (i = 0; i < size; i++)
585 result = gnutls_x509_crl_set_crt (crl, crts[i], now);
586 if (result < 0)
587 error (EXIT_FAILURE, 0, "crl_set_crt: %s", gnutls_strerror (result));
590 result = gnutls_x509_crl_set_this_update (crl, now);
591 if (result < 0)
592 error (EXIT_FAILURE, 0, "this_update: %s", gnutls_strerror (result));
594 fprintf (stderr, "Update times.\n");
595 days = get_crl_next_update ();
597 result = gnutls_x509_crl_set_next_update (crl, now + days * 24 * 60 * 60);
598 if (result < 0)
599 error (EXIT_FAILURE, 0, "next_update: %s", gnutls_strerror (result));
601 result = gnutls_x509_crl_set_version (crl, 2);
602 if (result < 0)
603 error (EXIT_FAILURE, 0, "set_version: %s", gnutls_strerror (result));
605 /* Authority Key ID.
607 if (ca_crt != NULL)
609 size = sizeof (buffer);
610 result = gnutls_x509_crt_get_subject_key_id (ca_crt, buffer,
611 &size, NULL);
612 if (result < 0)
614 size = sizeof (buffer);
615 result = gnutls_x509_crt_get_key_id (ca_crt, 0, buffer, &size);
617 if (result >= 0)
619 result = gnutls_x509_crl_set_authority_key_id (crl, buffer, size);
620 if (result < 0)
621 error (EXIT_FAILURE, 0, "set_authority_key_id: %s",
622 gnutls_strerror (result));
627 unsigned int number = get_crl_number ();
628 char bin_number[5];
630 bin_number[4] = number & 0xff;
631 bin_number[3] = (number >> 8) & 0xff;
632 bin_number[2] = (number >> 16) & 0xff;
633 bin_number[1] = (number >> 24) & 0xff;
634 bin_number[0] = 0;
636 result = gnutls_x509_crl_set_number (crl, bin_number, 5);
637 if (result < 0)
638 error (EXIT_FAILURE, 0, "set_number: %s", gnutls_strerror (result));
641 return crl;
644 void
645 generate_self_signed (void)
647 gnutls_x509_crt_t crt;
648 gnutls_x509_privkey_t key;
649 size_t size;
650 int result;
651 const char *uri;
653 fprintf (stderr, "Generating a self signed certificate...\n");
655 crt = generate_certificate (&key, NULL, 0);
657 if (!key)
658 key = load_private_key (1);
660 uri = get_crl_dist_point_url ();
661 if (uri)
663 result = gnutls_x509_crt_set_crl_dist_points (crt, GNUTLS_SAN_URI,
664 uri,
665 0 /* all reasons */ );
666 if (result < 0)
667 error (EXIT_FAILURE, 0, "crl_dist_points: %s",
668 gnutls_strerror (result));
671 print_certificate_info (crt, stderr, 0);
673 fprintf (stderr, "\n\nSigning certificate...\n");
675 result = gnutls_x509_crt_sign2 (crt, crt, key, dig, 0);
676 if (result < 0)
677 error (EXIT_FAILURE, 0, "crt_sign: %s", gnutls_strerror (result));
679 size = sizeof (buffer);
680 result = gnutls_x509_crt_export (crt, info.outcert_format, buffer, &size);
681 if (result < 0)
682 error (EXIT_FAILURE, 0, "crt_export: %s", gnutls_strerror (result));
684 fwrite (buffer, 1, size, outfile);
686 gnutls_x509_crt_deinit (crt);
687 gnutls_x509_privkey_deinit (key);
690 static void
691 generate_signed_certificate (void)
693 gnutls_x509_crt_t crt;
694 gnutls_x509_privkey_t key;
695 size_t size;
696 int result;
697 gnutls_x509_privkey_t ca_key;
698 gnutls_x509_crt_t ca_crt;
700 fprintf (stderr, "Generating a signed certificate...\n");
702 ca_key = load_ca_private_key ();
703 ca_crt = load_ca_cert ();
705 crt = generate_certificate (&key, ca_crt, 0);
707 /* Copy the CRL distribution points.
709 gnutls_x509_crt_cpy_crl_dist_points (crt, ca_crt);
710 /* it doesn't matter if we couldn't copy the CRL dist points.
713 print_certificate_info (crt, stderr, 0);
715 fprintf (stderr, "\n\nSigning certificate...\n");
717 result = gnutls_x509_crt_sign2 (crt, ca_crt, ca_key, dig, 0);
718 if (result < 0)
719 error (EXIT_FAILURE, 0, "crt_sign: %s", gnutls_strerror (result));
721 size = sizeof (buffer);
722 result = gnutls_x509_crt_export (crt, info.outcert_format, buffer, &size);
723 if (result < 0)
724 error (EXIT_FAILURE, 0, "crt_export: %s", gnutls_strerror (result));
726 fwrite (buffer, 1, size, outfile);
728 gnutls_x509_crt_deinit (crt);
729 gnutls_x509_privkey_deinit (key);
732 static void
733 generate_proxy_certificate (void)
735 gnutls_x509_crt_t crt, eecrt;
736 gnutls_x509_privkey_t key, eekey;
737 size_t size;
738 int result;
740 fprintf (stderr, "Generating a proxy certificate...\n");
742 eekey = load_ca_private_key ();
743 eecrt = load_cert (1);
745 crt = generate_certificate (&key, eecrt, 1);
747 print_certificate_info (crt, stderr, 0);
749 fprintf (stderr, "\n\nSigning certificate...\n");
751 result = gnutls_x509_crt_sign2 (crt, eecrt, eekey, dig, 0);
752 if (result < 0)
753 error (EXIT_FAILURE, 0, "crt_sign: %s", gnutls_strerror (result));
755 size = sizeof (buffer);
756 result = gnutls_x509_crt_export (crt, info.outcert_format, buffer, &size);
757 if (result < 0)
758 error (EXIT_FAILURE, 0, "crt_export: %s", gnutls_strerror (result));
760 fwrite (buffer, 1, size, outfile);
762 gnutls_x509_crt_deinit (crt);
763 gnutls_x509_privkey_deinit (key);
766 static void
767 generate_signed_crl (void)
769 gnutls_x509_crl_t crl;
770 int result;
771 gnutls_x509_privkey_t ca_key;
772 gnutls_x509_crt_t ca_crt;
774 fprintf (stderr, "Generating a signed CRL...\n");
776 ca_key = load_ca_private_key ();
777 ca_crt = load_ca_cert ();
778 crl = generate_crl (ca_crt);
780 fprintf (stderr, "\n");
782 result = gnutls_x509_crl_sign (crl, ca_crt, ca_key);
783 if (result < 0)
784 error (EXIT_FAILURE, 0, "crl_sign: %s", gnutls_strerror (result));
786 print_crl_info (crl, stderr);
788 gnutls_x509_crl_deinit (crl);
791 static void
792 update_signed_certificate (void)
794 gnutls_x509_crt_t crt;
795 size_t size;
796 int result;
797 gnutls_x509_privkey_t ca_key;
798 gnutls_x509_crt_t ca_crt;
799 int days;
800 time_t tim = time (NULL);
802 fprintf (stderr, "Generating a signed certificate...\n");
804 ca_key = load_ca_private_key ();
805 ca_crt = load_ca_cert ();
806 crt = load_cert (1);
808 fprintf (stderr, "Activation/Expiration time.\n");
809 gnutls_x509_crt_set_activation_time (crt, tim);
811 days = get_days ();
813 result =
814 gnutls_x509_crt_set_expiration_time (crt, tim + days * 24 * 60 * 60);
815 if (result < 0)
816 error (EXIT_FAILURE, 0, "set_expiration: %s", gnutls_strerror (result));
818 fprintf (stderr, "\n\nSigning certificate...\n");
820 result = gnutls_x509_crt_sign2 (crt, ca_crt, ca_key, dig, 0);
821 if (result < 0)
822 error (EXIT_FAILURE, 0, "crt_sign: %s", gnutls_strerror (result));
824 size = sizeof (buffer);
825 result = gnutls_x509_crt_export (crt, info.outcert_format, buffer, &size);
826 if (result < 0)
827 error (EXIT_FAILURE, 0, "crt_export: %s", gnutls_strerror (result));
829 fwrite (buffer, 1, size, outfile);
831 gnutls_x509_crt_deinit (crt);
834 static FILE *
835 safe_open_rw (const char *file)
837 mode_t omask = 0;
838 FILE *fh;
840 if (info.privkey_op != 0)
842 omask = umask (S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
845 fh = fopen (file, "wb");
847 if (info.privkey_op != 0)
849 umask (omask);
852 return fh;
855 void
856 gaa_parser (int argc, char **argv)
858 int ret;
860 if (gaa (argc, argv, &info) != -1)
862 fprintf (stderr, "Try `%s --help' for more information.\n",
863 program_name);
864 exit (1);
867 if (info.outfile)
869 outfile = safe_open_rw (info.outfile);
870 if (outfile == NULL)
871 error (EXIT_FAILURE, errno, "%s", info.outfile);
873 else
874 outfile = stdout;
876 if (info.infile)
878 infile = fopen (info.infile, "rb");
879 if (infile == NULL)
880 error (EXIT_FAILURE, errno, "%s", info.infile);
882 else
883 infile = stdin;
885 if (info.incert_format)
886 info.incert_format = GNUTLS_X509_FMT_DER;
887 else
888 info.incert_format = GNUTLS_X509_FMT_PEM;
890 if (info.outcert_format)
891 info.outcert_format = GNUTLS_X509_FMT_DER;
892 else
893 info.outcert_format = GNUTLS_X509_FMT_PEM;
895 if (info.hash != NULL)
897 if (strcasecmp (info.hash, "md5") == 0)
899 fprintf (stderr,
900 "Warning: MD5 is broken, and should not be used any more for digital signatures.\n");
901 dig = GNUTLS_DIG_MD5;
903 else if (strcasecmp (info.hash, "sha1") == 0)
904 dig = GNUTLS_DIG_SHA1;
905 else if (strcasecmp (info.hash, "sha256") == 0)
906 dig = GNUTLS_DIG_SHA256;
907 else if (strcasecmp (info.hash, "sha384") == 0)
908 dig = GNUTLS_DIG_SHA384;
909 else if (strcasecmp (info.hash, "sha512") == 0)
910 dig = GNUTLS_DIG_SHA512;
911 else if (strcasecmp (info.hash, "rmd160") == 0)
912 dig = GNUTLS_DIG_RMD160;
913 else
914 error (EXIT_FAILURE, 0, "invalid hash: %s", info.hash);
917 batch = 0;
918 if (info.template)
920 batch = 1;
921 template_parse (info.template);
924 #ifdef gcry_fips_mode_active
925 /* Libgcrypt manual says that gcry_version_check must be called
926 before calling gcry_fips_mode_active. */
927 gcry_check_version (NULL);
928 if (gcry_fips_mode_active ())
930 ret = gnutls_register_md5_handler ();
931 if (ret)
932 fprintf (stderr, "gnutls_register_md5_handler: %s\n",
933 gnutls_strerror (ret));
935 #endif
937 gnutls_global_set_log_function (tls_log_func);
938 gnutls_global_set_log_level (info.debug);
939 if (info.debug > 1)
940 printf ("Setting log level to %d\n", info.debug);
942 if ((ret = gnutls_global_init ()) < 0)
943 error (EXIT_FAILURE, 0, "global_init: %s", gnutls_strerror (ret));
945 if ((ret = gnutls_global_init_extra ()) < 0)
946 error (EXIT_FAILURE, 0, "global_init_extra: %s", gnutls_strerror (ret));
948 if (info.quick_random != 0)
949 gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
951 switch (info.action)
953 case ACTION_SELF_SIGNED:
954 generate_self_signed ();
955 break;
956 case ACTION_GENERATE_PRIVKEY:
957 generate_private_key ();
958 break;
959 case ACTION_CERT_INFO:
960 certificate_info ();
961 break;
962 case ACTION_GENERATE_REQUEST:
963 generate_request ();
964 break;
965 case ACTION_GENERATE_CERTIFICATE:
966 generate_signed_certificate ();
967 break;
968 case ACTION_VERIFY_CHAIN:
969 verify_chain ();
970 break;
971 case ACTION_PRIVKEY_INFO:
972 privkey_info ();
973 break;
974 case ACTION_UPDATE_CERTIFICATE:
975 update_signed_certificate ();
976 break;
977 case ACTION_TO_PKCS12:
978 generate_pkcs12 ();
979 break;
980 case ACTION_PKCS12_INFO:
981 pkcs12_info ();
982 break;
983 case ACTION_GENERATE_DH:
984 generate_prime (info.bits, 1);
985 break;
986 case ACTION_GET_DH:
987 generate_prime (info.bits, 0);
988 break;
989 case ACTION_CRL_INFO:
990 crl_info ();
991 break;
992 case ACTION_P7_INFO:
993 pkcs7_info ();
994 break;
995 case ACTION_GENERATE_CRL:
996 generate_signed_crl ();
997 break;
998 case ACTION_VERIFY_CRL:
999 verify_crl ();
1000 break;
1001 case ACTION_SMIME_TO_P7:
1002 smime_to_pkcs7 ();
1003 break;
1004 case ACTION_GENERATE_PROXY:
1005 generate_proxy_certificate ();
1006 break;
1007 case ACTION_GENERATE_PKCS8:
1008 generate_pkcs8 ();
1009 break;
1010 #ifdef ENABLE_OPENPGP
1011 case ACTION_PGP_INFO:
1012 pgp_certificate_info ();
1013 break;
1014 case ACTION_PGP_PRIVKEY_INFO:
1015 pgp_privkey_info ();
1016 break;
1017 case ACTION_RING_INFO:
1018 pgp_ring_info ();
1019 break;
1020 #endif
1021 case ACTION_REQUEST:
1022 crq_info ();
1023 break;
1024 default:
1025 gaa_help ();
1026 exit (0);
1028 fclose (outfile);
1031 #define MAX_CRTS 500
1032 void
1033 certificate_info (void)
1035 gnutls_x509_crt_t crt[MAX_CRTS];
1036 size_t size;
1037 int ret, i, count;
1038 gnutls_datum_t pem;
1039 unsigned int crt_num;
1041 pem.data = fread_file (infile, &size);
1042 pem.size = size;
1044 crt_num = MAX_CRTS;
1045 ret =
1046 gnutls_x509_crt_list_import (crt, &crt_num, &pem, info.incert_format,
1047 GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);
1048 if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
1050 error (0, 0, "too many certificates (%d); "
1051 "will only read the first %d", crt_num, MAX_CRTS);
1052 crt_num = MAX_CRTS;
1053 ret = gnutls_x509_crt_list_import (crt, &crt_num, &pem,
1054 info.incert_format, 0);
1056 if (ret < 0)
1057 error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));
1059 free (pem.data);
1061 count = ret;
1063 if (count > 1 && info.outcert_format == GNUTLS_X509_FMT_DER)
1065 error (0, 0, "cannot output multiple certificates in DER format; "
1066 "using PEM instead");
1067 info.outcert_format = GNUTLS_X509_FMT_PEM;
1070 for (i = 0; i < count; i++)
1072 if (i > 0)
1073 fprintf (outfile, "\n");
1075 if (info.outcert_format == GNUTLS_X509_FMT_PEM)
1076 print_certificate_info (crt[i], outfile, 1);
1078 size = sizeof (buffer);
1079 ret = gnutls_x509_crt_export (crt[i], info.outcert_format, buffer,
1080 &size);
1081 if (ret < 0)
1082 error (EXIT_FAILURE, 0, "export error: %s", gnutls_strerror (ret));
1083 fwrite (buffer, 1, size, outfile);
1085 gnutls_x509_crt_deinit (crt[i]);
1089 #ifdef ENABLE_OPENPGP
1091 void
1092 pgp_certificate_info (void)
1094 gnutls_openpgp_crt_t crt;
1095 size_t size;
1096 int ret;
1097 gnutls_datum_t pem, out_data;
1098 unsigned int verify_status;
1100 pem.data = fread_file (infile, &size);
1101 pem.size = size;
1103 ret = gnutls_openpgp_crt_init (&crt);
1104 if (ret < 0)
1105 error (EXIT_FAILURE, 0, "openpgp_crt_init: %s", gnutls_strerror (ret));
1107 ret = gnutls_openpgp_crt_import (crt, &pem, info.incert_format);
1109 if (ret < 0)
1110 error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));
1112 free (pem.data);
1114 if (info.outcert_format == GNUTLS_OPENPGP_FMT_BASE64)
1116 ret = gnutls_openpgp_crt_print (crt, 0, &out_data);
1118 if (ret == 0)
1120 fprintf (outfile, "%s\n", out_data.data);
1121 gnutls_free (out_data.data);
1126 ret = gnutls_openpgp_crt_verify_self(crt, 0, &verify_status);
1127 if (ret < 0)
1129 error (EXIT_FAILURE, 0, "verify signature error: %s", gnutls_strerror (ret));
1132 if (verify_status & GNUTLS_CERT_INVALID)
1134 fprintf (outfile, "Self Signature verification: failed\n\n");
1136 else
1138 fprintf (outfile, "Self Signature verification: ok (%x)\n\n", verify_status);
1141 size = sizeof (buffer);
1142 ret = gnutls_openpgp_crt_export (crt, info.outcert_format, buffer, &size);
1143 if (ret < 0)
1145 error (EXIT_FAILURE, 0, "export error: %s", gnutls_strerror (ret));
1146 fwrite (buffer, 1, size, outfile);
1149 fprintf (outfile, "%s\n", buffer);
1150 gnutls_openpgp_crt_deinit (crt);
1153 void
1154 pgp_privkey_info (void)
1156 gnutls_openpgp_privkey_t key;
1157 gnutls_openpgp_keyid_t keyid;
1158 size_t size;
1159 int ret, i, subkeys;
1160 gnutls_datum_t pem;
1161 const char *cprint;
1163 size = fread (buffer, 1, sizeof (buffer) - 1, infile);
1164 buffer[size] = 0;
1166 gnutls_openpgp_privkey_init (&key);
1168 pem.data = buffer;
1169 pem.size = size;
1171 ret = gnutls_openpgp_privkey_import (key, &pem, info.incert_format,
1172 NULL, 0);
1174 if (ret < 0)
1175 error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));
1177 /* Public key algorithm
1179 subkeys = gnutls_openpgp_privkey_get_subkey_count (key);
1180 if (subkeys < 0)
1181 error (EXIT_FAILURE, 0, "privkey_get_subkey_count: %s",
1182 gnutls_strerror (subkeys));
1184 for (i = -1; i < subkeys; i++)
1187 if (i != -1)
1188 fprintf (outfile, "Subkey[%d]:\n", i);
1190 fprintf (outfile, "Public Key Info:\n");
1192 if (i == -1)
1193 ret = gnutls_openpgp_privkey_get_pk_algorithm (key, NULL);
1194 else
1195 ret = gnutls_openpgp_privkey_get_subkey_pk_algorithm (key, i, NULL);
1197 fprintf (outfile, "\tPublic Key Algorithm: ");
1198 cprint = gnutls_pk_algorithm_get_name (ret);
1199 fprintf (outfile, "%s\n", cprint ? cprint : "Unknown");
1201 /* Print the raw public and private keys
1204 if (ret == GNUTLS_PK_RSA)
1206 gnutls_datum_t m, e, d, p, q, u;
1208 if (i == -1)
1209 ret =
1210 gnutls_openpgp_privkey_export_rsa_raw (key, &m, &e, &d, &p,
1211 &q, &u);
1212 else
1213 ret =
1214 gnutls_openpgp_privkey_export_subkey_rsa_raw (key, i, &m,
1215 &e, &d, &p,
1216 &q, &u);
1217 if (ret < 0)
1218 fprintf (stderr, "Error in key RSA data export: %s\n",
1219 gnutls_strerror (ret));
1220 else
1221 print_rsa_pkey (&m, &e, &d, &p, &q, &u);
1224 else if (ret == GNUTLS_PK_DSA)
1226 gnutls_datum_t p, q, g, y, x;
1228 if (i == -1)
1229 ret =
1230 gnutls_openpgp_privkey_export_dsa_raw (key, &p, &q, &g, &y, &x);
1231 else
1232 ret =
1233 gnutls_openpgp_privkey_export_subkey_dsa_raw (key, i, &p,
1234 &q, &g, &y, &x);
1235 if (ret < 0)
1236 fprintf (stderr, "Error in key DSA data export: %s\n",
1237 gnutls_strerror (ret));
1238 else
1239 print_dsa_pkey (&x, &y, &p, &q, &g);
1242 fprintf (outfile, "\n");
1244 size = sizeof (buffer);
1245 if (i == -1)
1246 ret = gnutls_openpgp_privkey_get_key_id (key, keyid);
1247 else
1248 ret = gnutls_openpgp_privkey_get_subkey_id (key, i, keyid);
1250 if (ret < 0)
1252 fprintf (stderr, "Error in key id calculation: %s\n",
1253 gnutls_strerror (ret));
1255 else
1257 fprintf (outfile, "Public Key ID: %s\n", raw_to_string (keyid, 8));
1262 size = sizeof (buffer);
1263 ret = gnutls_openpgp_privkey_export (key, GNUTLS_OPENPGP_FMT_BASE64,
1264 NULL, 0, buffer, &size);
1265 if (ret < 0)
1266 error (EXIT_FAILURE, 0, "export error: %s", gnutls_strerror (ret));
1268 fprintf (outfile, "\n%s\n", buffer);
1270 gnutls_openpgp_privkey_deinit (key);
1273 void
1274 pgp_ring_info (void)
1276 gnutls_openpgp_keyring_t ring;
1277 gnutls_openpgp_crt_t crt;
1278 size_t size;
1279 int ret, i, count;
1280 gnutls_datum_t pem;
1282 pem.data = fread_file (infile, &size);
1283 pem.size = size;
1285 ret = gnutls_openpgp_keyring_init (&ring);
1286 if (ret < 0)
1287 error (EXIT_FAILURE, 0, "openpgp_keyring_init: %s",
1288 gnutls_strerror (ret));
1290 ret = gnutls_openpgp_keyring_import (ring, &pem, info.incert_format);
1292 if (ret < 0)
1293 error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));
1295 free (pem.data);
1297 count = gnutls_openpgp_keyring_get_crt_count (ring);
1298 if (count > 0)
1299 fprintf (outfile, "Keyring contains %d OpenPGP certificates\n\n", count);
1300 else
1301 error (EXIT_FAILURE, 0, "keyring error: %s", gnutls_strerror (count));
1303 for (i = 0; i < count; i++)
1305 ret = gnutls_openpgp_keyring_get_crt (ring, i, &crt);
1306 if (ret < 0)
1307 error (EXIT_FAILURE, 0, "export error: %s", gnutls_strerror (ret));
1309 size = sizeof (buffer);
1310 ret = gnutls_openpgp_crt_export (crt, info.outcert_format,
1311 buffer, &size);
1312 if (ret < 0)
1313 error (EXIT_FAILURE, 0, "export error: %s", gnutls_strerror (ret));
1315 fwrite (buffer, 1, size, outfile);
1316 fprintf (outfile, "\n\n");
1318 gnutls_openpgp_crt_deinit (crt);
1323 gnutls_openpgp_keyring_deinit (ring);
1327 #endif
1329 static void
1330 print_hex_datum (gnutls_datum_t * dat)
1332 unsigned int j;
1333 #define SPACE "\t"
1334 fprintf (outfile, "\n" SPACE);
1335 for (j = 0; j < dat->size; j++)
1337 fprintf (outfile, "%.2x:", (unsigned char) dat->data[j]);
1338 if ((j + 1) % 15 == 0)
1339 fprintf (outfile, "\n" SPACE);
1341 fprintf (outfile, "\n");
1345 static void
1346 print_certificate_info (gnutls_x509_crt_t crt, FILE * out, unsigned int all)
1348 gnutls_datum_t cinfo;
1349 int ret;
1351 if (all)
1352 ret = gnutls_x509_crt_print (crt, GNUTLS_CRT_PRINT_FULL, &cinfo);
1353 else
1354 ret = gnutls_x509_crt_print (crt, GNUTLS_CRT_PRINT_UNSIGNED_FULL, &cinfo);
1355 if (ret == 0)
1357 fprintf (out, "%s\n", cinfo.data);
1358 gnutls_free (cinfo.data);
1361 if (out == stderr && batch == 0) /* interactive */
1362 if (read_yesno ("Is the above information ok? (Y/N): ") == 0)
1364 exit (1);
1368 static void
1369 print_crl_info (gnutls_x509_crl_t crl, FILE * out)
1371 gnutls_datum_t cinfo;
1372 int ret;
1373 size_t size;
1375 ret = gnutls_x509_crl_print (crl, GNUTLS_CRT_PRINT_FULL, &cinfo);
1376 if (ret < 0)
1377 error (EXIT_FAILURE, 0, "crl_print: %s", gnutls_strerror (ret));
1379 fprintf (out, "%s\n", cinfo.data);
1381 gnutls_free (cinfo.data);
1383 size = sizeof (buffer);
1384 ret = gnutls_x509_crl_export (crl, GNUTLS_X509_FMT_PEM, buffer, &size);
1385 if (ret < 0)
1386 error (EXIT_FAILURE, 0, "crl_export: %s", gnutls_strerror (ret));
1388 fwrite (buffer, 1, size, outfile);
1391 void
1392 crl_info (void)
1394 gnutls_x509_crl_t crl;
1395 int ret;
1396 size_t size;
1397 gnutls_datum_t pem;
1399 ret = gnutls_x509_crl_init (&crl);
1400 if (ret < 0)
1401 error (EXIT_FAILURE, 0, "crl_init: %s", gnutls_strerror (ret));
1403 pem.data = fread_file (infile, &size);
1404 pem.size = size;
1406 if (!pem.data)
1407 error (EXIT_FAILURE, errno, "%s", info.infile ? info.infile :
1408 "standard input");
1410 ret = gnutls_x509_crl_import (crl, &pem, info.incert_format);
1412 free (pem.data);
1413 if (ret < 0)
1414 error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));
1416 print_crl_info (crl, outfile);
1418 gnutls_x509_crl_deinit (crl);
1421 static void
1422 print_crq_info (gnutls_x509_crq_t crq, FILE * out)
1424 gnutls_datum_t cinfo;
1425 int ret;
1426 size_t size;
1428 if (info.outcert_format == GNUTLS_X509_FMT_PEM)
1430 ret = gnutls_x509_crq_print (crq, GNUTLS_CRT_PRINT_FULL, &cinfo);
1431 if (ret < 0)
1432 error (EXIT_FAILURE, 0, "crq_print: %s", gnutls_strerror (ret));
1434 fprintf (out, "%s\n", cinfo.data);
1436 gnutls_free (cinfo.data);
1439 size = sizeof (buffer);
1440 ret = gnutls_x509_crq_export (crq, info.outcert_format, buffer, &size);
1441 if (ret < 0)
1442 error (EXIT_FAILURE, 0, "crq_export: %s", gnutls_strerror (ret));
1444 fwrite (buffer, 1, size, outfile);
1447 void
1448 crq_info (void)
1450 gnutls_x509_crq_t crq;
1451 int ret;
1452 size_t size;
1453 gnutls_datum_t pem;
1455 ret = gnutls_x509_crq_init (&crq);
1456 if (ret < 0)
1457 error (EXIT_FAILURE, 0, "crq_init: %s", gnutls_strerror (ret));
1459 pem.data = fread_file (infile, &size);
1460 pem.size = size;
1462 if (!pem.data)
1463 error (EXIT_FAILURE, errno, "%s", info.infile ? info.infile :
1464 "standard input");
1466 ret = gnutls_x509_crq_import (crq, &pem, info.incert_format);
1468 free (pem.data);
1469 if (ret < 0)
1470 error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));
1472 print_crq_info (crq, outfile);
1474 gnutls_x509_crq_deinit (crq);
1477 void
1478 privkey_info (void)
1480 gnutls_x509_privkey_t key;
1481 size_t size;
1482 int ret;
1483 gnutls_datum_t pem;
1484 const char *cprint;
1485 const char *pass;
1487 size = fread (buffer, 1, sizeof (buffer) - 1, infile);
1488 buffer[size] = 0;
1490 gnutls_x509_privkey_init (&key);
1492 pem.data = buffer;
1493 pem.size = size;
1495 ret = 0;
1496 if (!info.pkcs8)
1497 ret = gnutls_x509_privkey_import (key, &pem, info.incert_format);
1499 /* If we failed to import the certificate previously try PKCS #8 */
1500 if (info.pkcs8 || ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
1502 /* first try to import the key without asking any password */
1503 ret = gnutls_x509_privkey_import_pkcs8 (key, &pem,
1504 info.incert_format,
1505 NULL, GNUTLS_PKCS_PLAIN);
1506 if (ret < 0)
1508 if (info.pass)
1509 pass = info.pass;
1510 else
1511 pass = get_pass ();
1512 ret = gnutls_x509_privkey_import_pkcs8 (key, &pem,
1513 info.incert_format,
1514 pass, 0);
1517 if (ret < 0)
1518 error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));
1520 /* Public key algorithm
1522 fprintf (outfile, "Public Key Info:\n");
1523 ret = gnutls_x509_privkey_get_pk_algorithm (key);
1524 fprintf (outfile, "\tPublic Key Algorithm: ");
1526 cprint = gnutls_pk_algorithm_get_name (ret);
1527 fprintf (outfile, "%s\n", cprint ? cprint : "Unknown");
1529 /* Print the raw public and private keys
1531 if (ret == GNUTLS_PK_RSA)
1533 gnutls_datum_t m, e, d, p, q, u;
1535 ret = gnutls_x509_privkey_export_rsa_raw (key, &m, &e, &d, &p, &q, &u);
1536 if (ret < 0)
1537 fprintf (stderr, "Error in key RSA data export: %s\n",
1538 gnutls_strerror (ret));
1539 else
1541 print_rsa_pkey (&m, &e, &d, &p, &q, &u);
1542 gnutls_free (m.data);
1543 gnutls_free (e.data);
1544 gnutls_free (d.data);
1545 gnutls_free (p.data);
1546 gnutls_free (q.data);
1547 gnutls_free (u.data);
1550 else if (ret == GNUTLS_PK_DSA)
1552 gnutls_datum_t p, q, g, y, x;
1554 ret = gnutls_x509_privkey_export_dsa_raw (key, &p, &q, &g, &y, &x);
1555 if (ret < 0)
1556 fprintf (stderr, "Error in key DSA data export: %s\n",
1557 gnutls_strerror (ret));
1558 else
1560 print_dsa_pkey (&x, &y, &p, &q, &g);
1561 gnutls_free (x.data);
1562 gnutls_free (y.data);
1563 gnutls_free (p.data);
1564 gnutls_free (q.data);
1565 gnutls_free (g.data);
1569 fprintf (outfile, "\n");
1571 size = sizeof (buffer);
1572 if ((ret = gnutls_x509_privkey_get_key_id (key, 0, buffer, &size)) < 0)
1574 fprintf (stderr, "Error in key id calculation: %s\n",
1575 gnutls_strerror (ret));
1577 else
1579 fprintf (outfile, "Public Key ID: %s\n", raw_to_string (buffer, size));
1582 if (info.fix_key != 0)
1584 ret = gnutls_x509_privkey_fix (key);
1585 if (ret < 0)
1586 error (EXIT_FAILURE, 0, "privkey_fix: %s", gnutls_strerror (ret));
1589 size = sizeof (buffer);
1590 ret = gnutls_x509_privkey_export (key, GNUTLS_X509_FMT_PEM, buffer, &size);
1591 if (ret < 0)
1592 error (EXIT_FAILURE, 0, "export error: %s", gnutls_strerror (ret));
1594 fprintf (outfile, "\n%s\n", buffer);
1596 gnutls_x509_privkey_deinit (key);
1600 /* Load the private key.
1601 * @mand should be non zero if it is required to read a private key.
1603 gnutls_x509_privkey_t
1604 load_private_key (int mand)
1606 gnutls_x509_privkey_t key;
1607 int ret;
1608 gnutls_datum_t dat;
1609 size_t size;
1611 if (!info.privkey && !mand)
1612 return NULL;
1614 if (info.privkey == NULL)
1615 error (EXIT_FAILURE, 0, "missing --load-privkey");
1617 ret = gnutls_x509_privkey_init (&key);
1618 if (ret < 0)
1619 error (EXIT_FAILURE, 0, "privkey_init: %s", gnutls_strerror (ret));
1621 dat.data = read_binary_file (info.privkey, &size);
1622 dat.size = size;
1624 if (!dat.data)
1625 error (EXIT_FAILURE, errno, "reading --load-privkey: %s", info.privkey);
1627 if (info.pkcs8)
1629 const char *pass = get_pass ();
1630 ret =
1631 gnutls_x509_privkey_import_pkcs8 (key, &dat, info.incert_format,
1632 pass, 0);
1634 else
1635 ret = gnutls_x509_privkey_import (key, &dat, info.incert_format);
1637 free (dat.data);
1639 if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
1641 error (EXIT_FAILURE, 0,
1642 "import error: could not find a valid PEM header; "
1643 "check if your key is PKCS #8 or PKCS #12 encoded");
1646 if (ret < 0)
1647 error (EXIT_FAILURE, 0, "importing --load-privkey: %s: %s",
1648 info.privkey, gnutls_strerror (ret));
1650 return key;
1653 /* Load the Certificate Request.
1655 gnutls_x509_crq_t
1656 load_request (void)
1658 gnutls_x509_crq_t crq;
1659 int ret;
1660 gnutls_datum_t dat;
1661 size_t size;
1663 if (!info.request)
1664 return NULL;
1666 ret = gnutls_x509_crq_init (&crq);
1667 if (ret < 0)
1668 error (EXIT_FAILURE, 0, "crq_init: %s", gnutls_strerror (ret));
1670 dat.data = read_binary_file (info.request, &size);
1671 dat.size = size;
1673 if (!dat.data)
1674 error (EXIT_FAILURE, errno, "reading --load-request: %s", info.request);
1676 ret = gnutls_x509_crq_import (crq, &dat, info.incert_format);
1677 if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
1679 error (EXIT_FAILURE, 0,
1680 "import error: could not find a valid PEM header");
1683 free (dat.data);
1684 if (ret < 0)
1685 error (EXIT_FAILURE, 0, "importing --load-request: %s: %s",
1686 info.request, gnutls_strerror (ret));
1688 return crq;
1691 /* Load the CA's private key.
1693 gnutls_x509_privkey_t
1694 load_ca_private_key (void)
1696 gnutls_x509_privkey_t key;
1697 int ret;
1698 gnutls_datum_t dat;
1699 size_t size;
1701 if (info.ca_privkey == NULL)
1702 error (EXIT_FAILURE, 0, "missing --load-ca-privkey");
1704 ret = gnutls_x509_privkey_init (&key);
1705 if (ret < 0)
1706 error (EXIT_FAILURE, 0, "privkey_init: %s", gnutls_strerror (ret));
1708 dat.data = read_binary_file (info.ca_privkey, &size);
1709 dat.size = size;
1711 if (!dat.data)
1712 error (EXIT_FAILURE, errno, "reading --load-ca-privkey: %s",
1713 info.ca_privkey);
1715 if (info.pkcs8)
1717 const char *pass = get_pass ();
1718 ret =
1719 gnutls_x509_privkey_import_pkcs8 (key, &dat, info.incert_format,
1720 pass, 0);
1722 else
1723 ret = gnutls_x509_privkey_import (key, &dat, info.incert_format);
1724 free (dat.data);
1725 if (ret < 0)
1726 error (EXIT_FAILURE, 0, "importing --load-ca-privkey: %s: %s",
1727 info.ca_privkey, gnutls_strerror (ret));
1729 return key;
1732 /* Loads the CA's certificate
1734 gnutls_x509_crt_t
1735 load_ca_cert (void)
1737 gnutls_x509_crt_t crt;
1738 int ret;
1739 gnutls_datum_t dat;
1740 size_t size;
1742 if (info.ca == NULL)
1743 error (EXIT_FAILURE, 0, "missing --load-ca-certificate");
1745 ret = gnutls_x509_crt_init (&crt);
1746 if (ret < 0)
1747 error (EXIT_FAILURE, 0, "crt_init: %s", gnutls_strerror (ret));
1749 dat.data = read_binary_file (info.ca, &size);
1750 dat.size = size;
1752 if (!dat.data)
1753 error (EXIT_FAILURE, errno, "reading --load-ca-certificate: %s", info.ca);
1755 ret = gnutls_x509_crt_import (crt, &dat, info.incert_format);
1756 free (dat.data);
1757 if (ret < 0)
1758 error (EXIT_FAILURE, 0, "importing --load-ca-certificate: %s: %s",
1759 info.ca, gnutls_strerror (ret));
1761 return crt;
1764 /* Loads the certificate
1765 * If mand is non zero then a certificate is mandatory. Otherwise
1766 * null will be returned if the certificate loading fails.
1768 gnutls_x509_crt_t
1769 load_cert (int mand)
1771 gnutls_x509_crt_t *crt;
1772 size_t size;
1774 crt = load_cert_list (mand, &size);
1776 return crt ? crt[0] : NULL;
1779 #define MAX_CERTS 256
1781 /* Loads a certificate list
1783 gnutls_x509_crt_t *
1784 load_cert_list (int mand, size_t * crt_size)
1786 FILE *fd;
1787 static gnutls_x509_crt_t crt[MAX_CERTS];
1788 char *ptr;
1789 int ret, i;
1790 gnutls_datum_t dat;
1791 size_t size;
1792 int ptr_size;
1794 *crt_size = 0;
1795 fprintf (stderr, "Loading certificate list...\n");
1797 if (info.cert == NULL)
1799 if (mand)
1800 error (EXIT_FAILURE, 0, "missing --load-certificate");
1801 else
1802 return NULL;
1805 fd = fopen (info.cert, "r");
1806 if (fd == NULL)
1807 error (EXIT_FAILURE, errno, "%s", info.cert);
1809 size = fread (buffer, 1, sizeof (buffer) - 1, fd);
1810 buffer[size] = 0;
1812 fclose (fd);
1814 ptr = buffer;
1815 ptr_size = size;
1817 for (i = 0; i < MAX_CERTS; i++)
1819 ret = gnutls_x509_crt_init (&crt[i]);
1820 if (ret < 0)
1821 error (EXIT_FAILURE, 0, "crt_init: %s", gnutls_strerror (ret));
1823 dat.data = ptr;
1824 dat.size = ptr_size;
1826 ret = gnutls_x509_crt_import (crt[i], &dat, info.incert_format);
1827 if (ret < 0 && *crt_size > 0)
1828 break;
1829 if (ret < 0)
1830 error (EXIT_FAILURE, 0, "crt_import: %s", gnutls_strerror (ret));
1832 ptr = strstr (ptr, "---END");
1833 if (ptr == NULL)
1834 break;
1835 ptr++;
1837 ptr_size = size;
1838 ptr_size -=
1839 (unsigned int) ((unsigned char *) ptr - (unsigned char *) buffer);
1841 if (ptr_size < 0)
1842 break;
1844 (*crt_size)++;
1846 fprintf (stderr, "Loaded %d certificates.\n", (int) *crt_size);
1848 return crt;
1852 /* Generate a PKCS #10 certificate request.
1854 void
1855 generate_request (void)
1857 gnutls_x509_crq_t crq;
1858 gnutls_x509_privkey_t key;
1859 int ret, ca_status, path_len;
1860 const char *pass;
1861 unsigned int usage = 0;
1863 fprintf (stderr, "Generating a PKCS #10 certificate request...\n");
1865 ret = gnutls_x509_crq_init (&crq);
1866 if (ret < 0)
1867 error (EXIT_FAILURE, 0, "crq_init: %s", gnutls_strerror (ret));
1869 /* Load the private key.
1871 key = load_private_key (0);
1872 if (!key)
1874 key = generate_private_key_int ();
1876 print_private_key (key);
1879 /* Set the DN.
1881 get_country_crq_set (crq);
1882 get_organization_crq_set (crq);
1883 get_unit_crq_set (crq);
1884 get_locality_crq_set (crq);
1885 get_state_crq_set (crq);
1886 get_cn_crq_set (crq);
1887 get_uid_crq_set (crq);
1888 get_oid_crq_set (crq);
1890 get_dns_name_set (TYPE_CRQ, crq);
1891 get_ip_addr_set (TYPE_CRQ, crq);
1892 get_email_set (TYPE_CRQ, crq);
1894 pass = get_challenge_pass ();
1896 if (pass != NULL && pass[0] != 0)
1898 ret = gnutls_x509_crq_set_challenge_password (crq, pass);
1899 if (ret < 0)
1900 error (EXIT_FAILURE, 0, "set_pass: %s", gnutls_strerror (ret));
1903 if (info.crq_extensions != 0)
1905 ca_status = get_ca_status ();
1906 if (ca_status)
1907 path_len = get_path_len ();
1908 else
1909 path_len = -1;
1911 ret = gnutls_x509_crq_set_basic_constraints (crq, ca_status, path_len);
1912 if (ret < 0)
1913 error (EXIT_FAILURE, 0, "set_basic_constraints: %s",
1914 gnutls_strerror (ret));
1917 ret = get_sign_status (1);
1918 if (ret)
1919 usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
1921 ret = get_encrypt_status (1);
1922 if (ret)
1923 usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
1924 else
1925 usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
1927 if (ca_status)
1929 ret = get_cert_sign_status ();
1930 if (ret)
1931 usage |= GNUTLS_KEY_KEY_CERT_SIGN;
1933 ret = get_crl_sign_status ();
1934 if (ret)
1935 usage |= GNUTLS_KEY_CRL_SIGN;
1937 ret = get_code_sign_status ();
1938 if (ret)
1940 ret =
1941 gnutls_x509_crq_set_key_purpose_oid (crq,
1942 GNUTLS_KP_CODE_SIGNING, 0);
1943 if (ret < 0)
1944 error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (ret));
1947 ret = get_ocsp_sign_status ();
1948 if (ret)
1950 ret =
1951 gnutls_x509_crq_set_key_purpose_oid (crq,
1952 GNUTLS_KP_OCSP_SIGNING, 0);
1953 if (ret < 0)
1954 error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (ret));
1957 ret = get_time_stamp_status ();
1958 if (ret)
1960 ret =
1961 gnutls_x509_crq_set_key_purpose_oid (crq,
1962 GNUTLS_KP_TIME_STAMPING, 0);
1963 if (ret < 0)
1964 error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (ret));
1969 ret = gnutls_x509_crq_set_key_usage (crq, usage);
1970 if (ret < 0)
1971 error (EXIT_FAILURE, 0, "key_usage: %s", gnutls_strerror (ret));
1973 ret = get_tls_client_status ();
1974 if (ret != 0)
1976 ret = gnutls_x509_crq_set_key_purpose_oid (crq,
1977 GNUTLS_KP_TLS_WWW_CLIENT, 0);
1978 if (ret < 0)
1979 error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (ret));
1982 ret = get_tls_server_status ();
1983 if (ret != 0)
1985 ret = gnutls_x509_crq_set_key_purpose_oid (crq,
1986 GNUTLS_KP_TLS_WWW_SERVER, 0);
1987 if (ret < 0)
1988 error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (ret));
1991 ret = gnutls_x509_crq_set_key (crq, key);
1992 if (ret < 0)
1993 error (EXIT_FAILURE, 0, "set_key: %s", gnutls_strerror (ret));
1995 ret = gnutls_x509_crq_sign (crq, key);
1996 if (ret < 0)
1997 error (EXIT_FAILURE, 0, "sign: %s", gnutls_strerror (ret));
1999 print_crq_info (crq, outfile);
2001 gnutls_x509_crq_deinit (crq);
2002 gnutls_x509_privkey_deinit (key);
2006 static void print_verification_res (gnutls_x509_crt_t crt,
2007 gnutls_x509_crt_t issuer,
2008 gnutls_x509_crl_t * crl_list,
2009 int crl_list_size);
2011 #define CERT_SEP "-----BEGIN CERT"
2012 #define CRL_SEP "-----BEGIN X509 CRL"
2013 static int
2014 _verify_x509_mem (const void *cert, int cert_size)
2016 const char *ptr;
2017 int ret, i;
2018 char name[256];
2019 char issuer_name[256];
2020 size_t name_size;
2021 size_t issuer_name_size;
2022 gnutls_datum_t tmp;
2023 gnutls_x509_crt_t *x509_cert_list = NULL;
2024 gnutls_x509_crl_t *x509_crl_list = NULL;
2025 int x509_ncerts, x509_ncrls;
2028 /* Decode the CA certificate
2031 /* Decode the CRL list
2033 ptr = cert;
2035 i = 1;
2037 if (strstr (ptr, CRL_SEP) != NULL) /* if CRLs exist */
2040 x509_crl_list =
2041 (gnutls_x509_crl_t *) realloc (x509_crl_list,
2042 i * sizeof (gnutls_x509_crl_t));
2043 if (x509_crl_list == NULL)
2044 error (EXIT_FAILURE, 0, "memory error");
2046 tmp.data = (char *) ptr;
2047 tmp.size = cert_size;
2048 tmp.size -=
2049 (unsigned int) ((unsigned char *) ptr - (unsigned char *) cert);
2051 ret = gnutls_x509_crl_init (&x509_crl_list[i - 1]);
2052 if (ret < 0)
2053 error (EXIT_FAILURE, 0, "error parsing CRL[%d]: %s", i,
2054 gnutls_strerror (ret));
2056 ret = gnutls_x509_crl_import (x509_crl_list[i - 1], &tmp,
2057 GNUTLS_X509_FMT_PEM);
2058 if (ret < 0)
2059 error (EXIT_FAILURE, 0, "error parsing CRL[%d]: %s", i,
2060 gnutls_strerror (ret));
2062 /* now we move ptr after the pem header */
2063 ptr = strstr (ptr, CRL_SEP);
2064 if (ptr != NULL)
2065 ptr++;
2067 i++;
2069 while ((ptr = strstr (ptr, CRL_SEP)) != NULL);
2071 x509_ncrls = i - 1;
2074 /* Decode the certificate chain.
2076 ptr = cert;
2078 i = 1;
2082 x509_cert_list =
2083 (gnutls_x509_crt_t *) realloc (x509_cert_list,
2084 i * sizeof (gnutls_x509_crt_t));
2085 if (x509_cert_list == NULL)
2086 error (EXIT_FAILURE, 0, "memory error");
2089 tmp.data = (char *) ptr;
2090 tmp.size = cert_size;
2091 tmp.size -=
2092 (unsigned int) ((unsigned char *) ptr - (unsigned char *) cert);
2094 ret = gnutls_x509_crt_init (&x509_cert_list[i - 1]);
2095 if (ret < 0)
2096 error (EXIT_FAILURE, 0, "error parsing certificate[%d]: %s", i,
2097 gnutls_strerror (ret));
2099 ret =
2100 gnutls_x509_crt_import (x509_cert_list[i - 1], &tmp,
2101 GNUTLS_X509_FMT_PEM);
2102 if (ret < 0)
2103 error (EXIT_FAILURE, 0, "error parsing certificate[%d]: %s", i,
2104 gnutls_strerror (ret));
2107 if (i - 1 != 0)
2109 /* verify the previous certificate using this one
2110 * as CA.
2113 name_size = sizeof (name);
2114 ret =
2115 gnutls_x509_crt_get_dn (x509_cert_list[i - 2], name, &name_size);
2116 if (ret < 0)
2117 error (EXIT_FAILURE, 0, "get_dn: %s", gnutls_strerror (ret));
2119 fprintf (outfile, "Certificate[%d]: %s\n", i - 2, name);
2121 /* print issuer
2123 issuer_name_size = sizeof (issuer_name);
2124 ret =
2125 gnutls_x509_crt_get_issuer_dn (x509_cert_list[i - 2],
2126 issuer_name, &issuer_name_size);
2127 if (ret < 0)
2128 error (EXIT_FAILURE, 0, "get_issuer_dn: %s",
2129 gnutls_strerror (ret));
2131 fprintf (outfile, "\tIssued by: %s\n", issuer_name);
2133 /* Get the Issuer's name
2135 name_size = sizeof (name);
2136 ret =
2137 gnutls_x509_crt_get_dn (x509_cert_list[i - 1], name, &name_size);
2138 if (ret < 0)
2139 error (EXIT_FAILURE, 0, "get_dn: %s", gnutls_strerror (ret));
2141 fprintf (outfile, "\tVerifying against certificate[%d].\n", i - 1);
2143 if (strcmp (issuer_name, name) != 0)
2145 fprintf (stderr, "Error: Issuer's name: %s\n", name);
2146 error (EXIT_FAILURE, 0,
2147 "issuer name does not match the next certificate");
2150 fprintf (outfile, "\tVerification output: ");
2151 print_verification_res (x509_cert_list[i - 2],
2152 x509_cert_list[i - 1], x509_crl_list,
2153 x509_ncrls);
2154 fprintf (outfile, ".\n\n");
2159 /* now we move ptr after the pem header
2161 ptr = strstr (ptr, CERT_SEP);
2162 if (ptr != NULL)
2163 ptr++;
2165 i++;
2167 while ((ptr = strstr (ptr, CERT_SEP)) != NULL);
2169 x509_ncerts = i - 1;
2171 /* The last certificate in the list will be used as
2172 * a CA (should be self signed).
2174 name_size = sizeof (name);
2175 ret = gnutls_x509_crt_get_dn (x509_cert_list[x509_ncerts - 1], name,
2176 &name_size);
2177 if (ret < 0)
2178 error (EXIT_FAILURE, 0, "get_dn: %s", gnutls_strerror (ret));
2180 fprintf (outfile, "Certificate[%d]: %s\n", x509_ncerts - 1, name);
2182 /* print issuer
2184 issuer_name_size = sizeof (issuer_name);
2185 ret =
2186 gnutls_x509_crt_get_issuer_dn (x509_cert_list[x509_ncerts - 1],
2187 issuer_name, &issuer_name_size);
2188 if (ret < 0)
2189 error (EXIT_FAILURE, 0, "get_issuer_dn: %s", gnutls_strerror (ret));
2191 fprintf (outfile, "\tIssued by: %s\n", name);
2193 if (strcmp (issuer_name, name) != 0)
2194 error (EXIT_FAILURE, 0, "the last certificate is not self signed");
2196 fprintf (outfile, "\tVerification output: ");
2197 print_verification_res (x509_cert_list[x509_ncerts - 1],
2198 x509_cert_list[x509_ncerts - 1], x509_crl_list,
2199 x509_ncrls);
2201 fprintf (outfile, ".\n\n");
2203 /* Verify using internal algorithm too. */
2205 int verify_status;
2207 ret = gnutls_x509_crt_list_verify (x509_cert_list, x509_ncerts,
2208 &x509_cert_list[x509_ncerts - 1], 1,
2209 x509_crl_list,
2210 x509_ncrls,
2211 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT,
2212 &verify_status);
2213 if (ret < 0)
2214 error (EXIT_FAILURE, 0, "gnutls_x509_crt_list_verify: %s",
2215 gnutls_strerror (ret));
2217 fprintf (outfile, "Chain verification output: ");
2219 if (verify_status & GNUTLS_CERT_INVALID)
2221 fprintf (outfile, "Not verified");
2223 else
2225 fprintf (outfile, "Verified");
2228 if (verify_status & GNUTLS_CERT_SIGNER_NOT_CA)
2230 fprintf (outfile, ", ");
2231 fprintf (outfile, "Issuer is not a CA");
2234 if (verify_status & GNUTLS_CERT_INSECURE_ALGORITHM)
2236 fprintf (outfile, ", ");
2237 fprintf (outfile, "Insecure algorithm");
2240 fprintf (outfile, ".\n");
2243 for (i = 0; i < x509_ncerts; i++)
2244 gnutls_x509_crt_deinit (x509_cert_list[i]);
2246 for (i = 0; i < x509_ncrls; i++)
2247 gnutls_x509_crl_deinit (x509_crl_list[i]);
2249 free (x509_cert_list);
2250 free (x509_crl_list);
2252 if (ret < 0)
2253 error (EXIT_FAILURE, 0, "verification error: %s", gnutls_strerror (ret));
2255 return 0;
2258 static void
2259 print_verification_res (gnutls_x509_crt_t crt,
2260 gnutls_x509_crt_t issuer,
2261 gnutls_x509_crl_t * crl_list, int crl_list_size)
2263 unsigned int output;
2264 int comma = 0;
2265 int ret;
2266 time_t now = time (0);
2268 ret = gnutls_x509_crt_verify (crt, &issuer, 1, 0, &output);
2269 if (ret < 0)
2270 error (EXIT_FAILURE, 0, "verification error: %s", gnutls_strerror (ret));
2272 if (output & GNUTLS_CERT_INVALID)
2274 fprintf (outfile, "Not verified");
2275 comma = 1;
2277 else
2279 fprintf (outfile, "Verified");
2280 comma = 1;
2283 if (output & GNUTLS_CERT_SIGNER_NOT_CA)
2285 if (comma)
2286 fprintf (outfile, ", ");
2287 fprintf (outfile, "Issuer is not a CA");
2288 comma = 1;
2291 if (output & GNUTLS_CERT_INSECURE_ALGORITHM)
2293 if (comma)
2294 fprintf (outfile, ", ");
2295 fprintf (outfile, "Insecure algorithm");
2296 comma = 1;
2299 /* Check expiration dates.
2302 if (gnutls_x509_crt_get_activation_time (crt) > now)
2304 if (comma)
2305 fprintf (outfile, ", ");
2306 comma = 1;
2307 fprintf (outfile, "Not activated");
2310 if (gnutls_x509_crt_get_expiration_time (crt) < now)
2312 if (comma)
2313 fprintf (outfile, ", ");
2314 comma = 1;
2315 fprintf (outfile, "Expired");
2318 ret = gnutls_x509_crt_check_revocation (crt, crl_list, crl_list_size);
2319 if (ret < 0)
2320 error (EXIT_FAILURE, 0, "revocation check: %s", gnutls_strerror (ret));
2322 if (ret == 1)
2323 { /* revoked */
2324 if (comma)
2325 fprintf (outfile, ", ");
2326 comma = 1;
2327 fprintf (outfile, "Revoked");
2331 void
2332 verify_chain (void)
2334 char *buf;
2335 size_t size;
2337 buf = fread_file (infile, &size);
2338 if (buf == NULL)
2339 error (EXIT_FAILURE, errno, "reading chain");
2341 buf[size] = 0;
2343 _verify_x509_mem (buf, size);
2347 void
2348 verify_crl (void)
2350 size_t size, dn_size;
2351 char dn[128];
2352 unsigned int output;
2353 int comma = 0;
2354 int ret;
2355 gnutls_datum_t pem;
2356 gnutls_x509_crl_t crl;
2357 time_t now = time (0);
2358 gnutls_x509_crt_t issuer;
2360 issuer = load_ca_cert ();
2362 fprintf (outfile, "\nCA certificate:\n");
2364 dn_size = sizeof (dn);
2365 ret = gnutls_x509_crt_get_dn (issuer, dn, &dn_size);
2366 if (ret < 0)
2367 error (EXIT_FAILURE, 0, "crt_get_dn: %s", gnutls_strerror (ret));
2369 fprintf (outfile, "\tSubject: %s\n\n", dn);
2371 ret = gnutls_x509_crl_init (&crl);
2372 if (ret < 0)
2373 error (EXIT_FAILURE, 0, "crl_init: %s", gnutls_strerror (ret));
2375 pem.data = fread_file (infile, &size);
2376 pem.size = size;
2378 ret = gnutls_x509_crl_import (crl, &pem, info.incert_format);
2379 free (pem.data);
2380 if (ret < 0)
2381 error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));
2383 print_crl_info (crl, outfile);
2385 fprintf (outfile, "Verification output: ");
2386 ret = gnutls_x509_crl_verify (crl, &issuer, 1, 0, &output);
2387 if (ret < 0)
2388 error (EXIT_FAILURE, 0, "verification error: %s", gnutls_strerror (ret));
2390 if (output & GNUTLS_CERT_INVALID)
2392 fprintf (outfile, "Not verified");
2393 comma = 1;
2395 else
2397 fprintf (outfile, "Verified");
2398 comma = 1;
2401 if (output & GNUTLS_CERT_SIGNER_NOT_CA)
2403 if (comma)
2404 fprintf (outfile, ", ");
2405 fprintf (outfile, "Issuer is not a CA");
2406 comma = 1;
2409 if (output & GNUTLS_CERT_INSECURE_ALGORITHM)
2411 if (comma)
2412 fprintf (outfile, ", ");
2413 fprintf (outfile, "Insecure algorithm");
2414 comma = 1;
2417 /* Check expiration dates.
2420 if (gnutls_x509_crl_get_this_update (crl) > now)
2422 if (comma)
2423 fprintf (outfile, ", ");
2424 comma = 1;
2425 fprintf (outfile, "Issued in the future!");
2428 if (gnutls_x509_crl_get_next_update (crl) < now)
2430 if (comma)
2431 fprintf (outfile, ", ");
2432 comma = 1;
2433 fprintf (outfile, "CRL is not up to date");
2436 fprintf (outfile, "\n");
2439 static int
2440 cipher_to_flags (const char *cipher)
2442 if (strcasecmp (cipher, "3des") == 0)
2444 return GNUTLS_PKCS_USE_PBES2_3DES;
2446 else if (strcasecmp (cipher, "aes-128") == 0)
2448 return GNUTLS_PKCS_USE_PBES2_AES_128;
2450 else if (strcasecmp (cipher, "aes-192") == 0)
2452 return GNUTLS_PKCS_USE_PBES2_AES_192;
2454 else if (strcasecmp (cipher, "aes-256") == 0)
2456 return GNUTLS_PKCS_USE_PBES2_AES_256;
2458 else if (strcasecmp (cipher, "rc2-40") == 0)
2460 return GNUTLS_PKCS_USE_PKCS12_RC2_40;
2463 error (EXIT_FAILURE, 0, "Unknown cipher %s\n", cipher);
2464 return -1;
2467 void
2468 generate_pkcs8 (void)
2470 gnutls_x509_privkey_t key;
2471 int result;
2472 size_t size;
2473 int flags = 0;
2474 const char *password;
2476 fprintf (stderr, "Generating a PKCS #8 key structure...\n");
2478 key = load_private_key (1);
2480 if (info.pass)
2481 password = info.pass;
2482 else
2483 password = get_pass ();
2485 if (info.export)
2486 flags = GNUTLS_PKCS_USE_PKCS12_RC2_40;
2487 else
2488 flags = cipher_to_flags (info.pkcs_cipher);
2490 if (password == NULL || password[0] == 0)
2492 flags = GNUTLS_PKCS_PLAIN;
2495 size = sizeof (buffer);
2496 result =
2497 gnutls_x509_privkey_export_pkcs8 (key, info.outcert_format,
2498 password, flags, buffer, &size);
2500 if (result < 0)
2501 error (EXIT_FAILURE, 0, "key_export: %s", gnutls_strerror (result));
2503 fwrite (buffer, 1, size, outfile);
2508 #include <gnutls/pkcs12.h>
2509 #include <unistd.h>
2511 void
2512 generate_pkcs12 (void)
2514 gnutls_pkcs12_t pkcs12;
2515 gnutls_x509_crt_t *crts;
2516 gnutls_x509_privkey_t key;
2517 int result;
2518 size_t size;
2519 gnutls_datum_t data;
2520 const char *pass;
2521 const char *name;
2522 unsigned int flags, i;
2523 gnutls_datum_t key_id;
2524 unsigned char _key_id[20];
2525 int indx;
2526 size_t ncrts;
2528 fprintf (stderr, "Generating a PKCS #12 structure...\n");
2530 key = load_private_key (0);
2531 crts = load_cert_list (0, &ncrts);
2533 name = get_pkcs12_key_name ();
2535 result = gnutls_pkcs12_init (&pkcs12);
2536 if (result < 0)
2537 error (EXIT_FAILURE, 0, "pkcs12_init: %s", gnutls_strerror (result));
2539 if (info.pass)
2540 pass = info.pass;
2541 else
2542 pass = get_pass ();
2544 for (i = 0; i < ncrts; i++)
2546 gnutls_pkcs12_bag_t bag;
2548 result = gnutls_pkcs12_bag_init (&bag);
2549 if (result < 0)
2550 error (EXIT_FAILURE, 0, "bag_init: %s", gnutls_strerror (result));
2552 result = gnutls_pkcs12_bag_set_crt (bag, crts[i]);
2553 if (result < 0)
2554 error (EXIT_FAILURE, 0, "set_crt[%d]: %s", i,
2555 gnutls_strerror (result));
2557 indx = result;
2559 result = gnutls_pkcs12_bag_set_friendly_name (bag, indx, name);
2560 if (result < 0)
2561 error (EXIT_FAILURE, 0, "bag_set_friendly_name: %s",
2562 gnutls_strerror (result));
2564 size = sizeof (_key_id);
2565 result = gnutls_x509_crt_get_key_id (crts[i], 0, _key_id, &size);
2566 if (result < 0)
2567 error (EXIT_FAILURE, 0, "key_id[%d]: %s", i,
2568 gnutls_strerror (result));
2570 key_id.data = _key_id;
2571 key_id.size = size;
2573 result = gnutls_pkcs12_bag_set_key_id (bag, indx, &key_id);
2574 if (result < 0)
2575 error (EXIT_FAILURE, 0, "bag_set_key_id: %s",
2576 gnutls_strerror (result));
2578 if (info.export)
2579 flags = GNUTLS_PKCS_USE_PKCS12_RC2_40;
2580 else
2581 flags = cipher_to_flags (info.pkcs_cipher);
2583 result = gnutls_pkcs12_bag_encrypt (bag, pass, flags);
2584 if (result < 0)
2585 error (EXIT_FAILURE, 0, "bag_encrypt: %s", gnutls_strerror (result));
2587 result = gnutls_pkcs12_set_bag (pkcs12, bag);
2588 if (result < 0)
2589 error (EXIT_FAILURE, 0, "set_bag: %s", gnutls_strerror (result));
2592 if (key)
2594 gnutls_pkcs12_bag_t kbag;
2596 result = gnutls_pkcs12_bag_init (&kbag);
2597 if (result < 0)
2598 error (EXIT_FAILURE, 0, "bag_init: %s", gnutls_strerror (result));
2600 if (info.export)
2601 flags = GNUTLS_PKCS_USE_PKCS12_RC2_40;
2602 else
2603 flags = cipher_to_flags (info.pkcs_cipher);
2605 size = sizeof (buffer);
2606 result =
2607 gnutls_x509_privkey_export_pkcs8 (key, GNUTLS_X509_FMT_DER,
2608 pass, flags, buffer, &size);
2609 if (result < 0)
2610 error (EXIT_FAILURE, 0, "key_export: %s", gnutls_strerror (result));
2612 data.data = buffer;
2613 data.size = size;
2614 result =
2615 gnutls_pkcs12_bag_set_data (kbag,
2616 GNUTLS_BAG_PKCS8_ENCRYPTED_KEY, &data);
2617 if (result < 0)
2618 error (EXIT_FAILURE, 0, "bag_set_data: %s", gnutls_strerror (result));
2620 indx = result;
2622 result = gnutls_pkcs12_bag_set_friendly_name (kbag, indx, name);
2623 if (result < 0)
2624 error (EXIT_FAILURE, 0, "bag_set_friendly_name: %s",
2625 gnutls_strerror (result));
2627 size = sizeof (_key_id);
2628 result = gnutls_x509_privkey_get_key_id (key, 0, _key_id, &size);
2629 if (result < 0)
2630 error (EXIT_FAILURE, 0, "key_id: %s", gnutls_strerror (result));
2632 key_id.data = _key_id;
2633 key_id.size = size;
2635 result = gnutls_pkcs12_bag_set_key_id (kbag, indx, &key_id);
2636 if (result < 0)
2637 error (EXIT_FAILURE, 0, "bag_set_key_id: %s",
2638 gnutls_strerror (result));
2640 result = gnutls_pkcs12_set_bag (pkcs12, kbag);
2641 if (result < 0)
2642 error (EXIT_FAILURE, 0, "set_bag: %s", gnutls_strerror (result));
2645 result = gnutls_pkcs12_generate_mac (pkcs12, pass);
2646 if (result < 0)
2647 error (EXIT_FAILURE, 0, "generate_mac: %s", gnutls_strerror (result));
2649 size = sizeof (buffer);
2650 result = gnutls_pkcs12_export (pkcs12, info.outcert_format, buffer, &size);
2651 if (result < 0)
2652 error (EXIT_FAILURE, 0, "pkcs12_export: %s", gnutls_strerror (result));
2654 fwrite (buffer, 1, size, outfile);
2658 static const char *
2659 BAGTYPE (gnutls_pkcs12_bag_type_t x)
2661 switch (x)
2663 case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
2664 return "PKCS #8 Encrypted key";
2665 case GNUTLS_BAG_EMPTY:
2666 return "Empty";
2667 case GNUTLS_BAG_PKCS8_KEY:
2668 return "PKCS #8 Key";
2669 case GNUTLS_BAG_CERTIFICATE:
2670 return "Certificate";
2671 case GNUTLS_BAG_ENCRYPTED:
2672 return "Encrypted";
2673 case GNUTLS_BAG_CRL:
2674 return "CRL";
2675 case GNUTLS_BAG_SECRET:
2676 return "Secret";
2677 default:
2678 return "Unknown";
2682 static void
2683 print_bag_data (gnutls_pkcs12_bag_t bag)
2685 int result;
2686 int count, i, type;
2687 gnutls_datum_t cdata, id;
2688 const char *str, *name;
2689 gnutls_datum_t out;
2691 count = gnutls_pkcs12_bag_get_count (bag);
2692 if (count < 0)
2693 error (EXIT_FAILURE, 0, "get_count: %s", gnutls_strerror (count));
2695 fprintf (outfile, "\tElements: %d\n", count);
2697 for (i = 0; i < count; i++)
2699 type = gnutls_pkcs12_bag_get_type (bag, i);
2700 if (type < 0)
2701 error (EXIT_FAILURE, 0, "get_type: %s", gnutls_strerror (type));
2703 fprintf (stderr, "\tType: %s\n", BAGTYPE (type));
2705 name = NULL;
2706 result = gnutls_pkcs12_bag_get_friendly_name (bag, i, (char **) &name);
2707 if (result < 0)
2708 error (EXIT_FAILURE, 0, "get_friendly_name: %s",
2709 gnutls_strerror (type));
2710 if (name)
2711 fprintf (outfile, "\tFriendly name: %s\n", name);
2713 id.data = NULL;
2714 id.size = 0;
2715 result = gnutls_pkcs12_bag_get_key_id (bag, i, &id);
2716 if (result < 0)
2717 error (EXIT_FAILURE, 0, "get_key_id: %s", gnutls_strerror (type));
2718 fprintf (outfile, "\tKey ID: %s\n", raw_to_string (id.data, id.size));
2720 result = gnutls_pkcs12_bag_get_data (bag, i, &cdata);
2721 if (result < 0)
2722 error (EXIT_FAILURE, 0, "get_data: %s", gnutls_strerror (result));
2724 switch (type)
2726 case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
2727 str = "ENCRYPTED PRIVATE KEY";
2728 break;
2729 case GNUTLS_BAG_PKCS8_KEY:
2730 str = "PRIVATE KEY";
2731 break;
2732 case GNUTLS_BAG_CERTIFICATE:
2733 str = "CERTIFICATE";
2734 break;
2735 case GNUTLS_BAG_CRL:
2736 str = "CRL";
2737 break;
2738 case GNUTLS_BAG_ENCRYPTED:
2739 case GNUTLS_BAG_EMPTY:
2740 default:
2741 str = NULL;
2744 if (str != NULL)
2746 gnutls_pem_base64_encode_alloc (str, &cdata, &out);
2747 fprintf (outfile, "%s\n", out.data);
2749 gnutls_free (out.data);
2755 void
2756 pkcs12_info (void)
2758 gnutls_pkcs12_t pkcs12;
2759 gnutls_pkcs12_bag_t bag;
2760 int result;
2761 size_t size;
2762 gnutls_datum_t data;
2763 const char *pass;
2764 int indx;
2766 result = gnutls_pkcs12_init (&pkcs12);
2767 if (result < 0)
2768 error (EXIT_FAILURE, 0, "p12_init: %s", gnutls_strerror (result));
2770 data.data = fread_file (infile, &size);
2771 data.size = size;
2773 result = gnutls_pkcs12_import (pkcs12, &data, info.incert_format, 0);
2774 free (data.data);
2775 if (result < 0)
2776 error (EXIT_FAILURE, 0, "p12_import: %s", gnutls_strerror (result));
2778 if (info.pass)
2779 pass = info.pass;
2780 else
2781 pass = get_pass ();
2783 result = gnutls_pkcs12_verify_mac (pkcs12, pass);
2784 if (result < 0)
2785 error (0, 0, "verify_mac: %s", gnutls_strerror (result));
2787 for (indx = 0;; indx++)
2789 result = gnutls_pkcs12_bag_init (&bag);
2790 if (result < 0)
2791 error (EXIT_FAILURE, 0, "bag_init: %s", gnutls_strerror (result));
2793 result = gnutls_pkcs12_get_bag (pkcs12, indx, bag);
2794 if (result < 0)
2795 break;
2797 result = gnutls_pkcs12_bag_get_count (bag);
2798 if (result < 0)
2799 error (EXIT_FAILURE, 0, "bag_count: %s", gnutls_strerror (result));
2801 fprintf (outfile, "BAG #%d\n", indx);
2803 result = gnutls_pkcs12_bag_get_type (bag, 0);
2804 if (result < 0)
2805 error (EXIT_FAILURE, 0, "bag_init: %s", gnutls_strerror (result));
2807 if (result == GNUTLS_BAG_ENCRYPTED)
2809 fprintf (stderr, "\tType: %s\n", BAGTYPE (result));
2810 fprintf (stderr, "\n\tDecrypting...\n");
2812 result = gnutls_pkcs12_bag_decrypt (bag, pass);
2814 if (result < 0)
2816 error (0, 0, "bag_decrypt: %s", gnutls_strerror (result));
2817 continue;
2820 result = gnutls_pkcs12_bag_get_count (bag);
2821 if (result < 0)
2822 error (EXIT_FAILURE, 0, "encrypted bag_count: %s",
2823 gnutls_strerror (result));
2826 print_bag_data (bag);
2828 gnutls_pkcs12_bag_deinit (bag);
2832 void
2833 pkcs7_info (void)
2835 gnutls_pkcs7_t pkcs7;
2836 int result;
2837 size_t size;
2838 gnutls_datum_t data, b64;
2839 int indx, count;
2841 result = gnutls_pkcs7_init (&pkcs7);
2842 if (result < 0)
2843 error (EXIT_FAILURE, 0, "p7_init: %s", gnutls_strerror (result));
2845 data.data = fread_file (infile, &size);
2846 data.size = size;
2848 result = gnutls_pkcs7_import (pkcs7, &data, info.incert_format);
2849 free (data.data);
2850 if (result < 0)
2851 error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (result));
2853 /* Read and print the certificates.
2855 result = gnutls_pkcs7_get_crt_count (pkcs7);
2856 if (result < 0)
2857 error (EXIT_FAILURE, 0, "p7_crt_count: %s", gnutls_strerror (result));
2859 count = result;
2861 if (count > 0)
2862 fprintf (outfile, "Number of certificates: %u\n", count);
2864 for (indx = 0; indx < count; indx++)
2866 fputs ("\n", outfile);
2868 size = sizeof (buffer);
2869 result = gnutls_pkcs7_get_crt_raw (pkcs7, indx, buffer, &size);
2870 if (result < 0)
2871 break;
2873 data.data = buffer;
2874 data.size = size;
2876 result = gnutls_pem_base64_encode_alloc ("CERTIFICATE", &data, &b64);
2877 if (result < 0)
2878 error (EXIT_FAILURE, 0, "encoding: %s", gnutls_strerror (result));
2880 fputs (b64.data, outfile);
2881 gnutls_free (b64.data);
2884 /* Read the CRLs now.
2886 result = gnutls_pkcs7_get_crl_count (pkcs7);
2887 if (result < 0)
2888 error (EXIT_FAILURE, 0, "p7_crl_count: %s", gnutls_strerror (result));
2890 count = result;
2892 if (count > 0)
2893 fprintf (outfile, "\nNumber of CRLs: %u\n", count);
2895 for (indx = 0; indx < count; indx++)
2897 fputs ("\n", outfile);
2899 size = sizeof (buffer);
2900 result = gnutls_pkcs7_get_crl_raw (pkcs7, indx, buffer, &size);
2901 if (result < 0)
2902 break;
2904 data.data = buffer;
2905 data.size = size;
2907 result = gnutls_pem_base64_encode_alloc ("X509 CRL", &data, &b64);
2908 if (result < 0)
2909 error (EXIT_FAILURE, 0, "encoding: %s", gnutls_strerror (result));
2911 fputs (b64.data, outfile);
2912 gnutls_free (b64.data);
2916 void
2917 smime_to_pkcs7 (void)
2919 size_t linesize = 0;
2920 char *lineptr = NULL;
2921 ssize_t len;
2923 /* Find body. FIXME: Handle non-b64 Content-Transfer-Encoding.
2924 Reject non-S/MIME tagged Content-Type's? */
2927 len = getline (&lineptr, &linesize, infile);
2928 if (len == -1)
2929 error (EXIT_FAILURE, 0, "cannot find RFC 2822 header/body separator");
2931 while (strcmp (lineptr, "\r\n") != 0 && strcmp (lineptr, "\n") != 0);
2935 len = getline (&lineptr, &linesize, infile);
2936 if (len == -1)
2937 error (EXIT_FAILURE, 0, "message has RFC 2822 header but no body");
2939 while (strcmp (lineptr, "\r\n") == 0 && strcmp (lineptr, "\n") == 0);
2941 fprintf (outfile, "%s", "-----BEGIN PKCS7-----\n");
2945 while (len > 0
2946 && (lineptr[len - 1] == '\r' || lineptr[len - 1] == '\n'))
2947 lineptr[--len] = '\0';
2948 if (strcmp (lineptr, "") != 0)
2949 fprintf (outfile, "%s\n", lineptr);
2950 len = getline (&lineptr, &linesize, infile);
2952 while (len != -1);
2954 fprintf (outfile, "%s", "-----END PKCS7-----\n");
2956 free (lineptr);
2959 void
2960 certtool_version (void)
2962 const char *p = PACKAGE_NAME;
2963 if (strcmp (gnutls_check_version (NULL), PACKAGE_VERSION) != 0)
2964 p = PACKAGE_STRING;
2965 version_etc (stdout, program_name, p, gnutls_check_version (NULL),
2966 "Nikos Mavrogiannopoulos", "Simon Josefsson", (char *) NULL);