The test now works.
[gnutls.git] / src / certtool.c
blobbf0990f7a7f8ab0689cc757fc6894f99e9844373
1 /*
2 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 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 3 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, see <http://www.gnu.org/licenses/>.
20 #include <config.h>
21 #include <gnutls/gnutls.h>
22 #include <gcrypt.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include <gnutls/x509.h>
29 #include <gnutls/openpgp.h>
30 #include <time.h>
31 #include "certtool-gaa.h"
32 #include <gnutls/pkcs12.h>
33 #include <unistd.h>
34 #include <certtool-cfg.h>
35 #include <gcrypt.h>
36 #include <errno.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <fcntl.h>
41 /* Gnulib portability files. */
42 #include <read-file.h>
43 #include <error.h>
44 #include <progname.h>
45 #include <version-etc.h>
47 static void print_crl_info (gnutls_x509_crl_t crl, FILE * out);
48 int generate_prime (int bits, int how);
49 void pkcs7_info (void);
50 void smime_to_pkcs7 (void);
51 void pkcs12_info (void);
52 void generate_pkcs12 (void);
53 void generate_pkcs8 (void);
54 void verify_chain (void);
55 void verify_crl (void);
56 void pgp_privkey_info (void);
57 void pgp_ring_info (void);
58 gnutls_x509_privkey_t load_private_key (int mand);
59 gnutls_x509_crq_t load_request (void);
60 gnutls_x509_privkey_t load_ca_private_key (void);
61 gnutls_x509_crt_t load_ca_cert (void);
62 gnutls_x509_crt_t load_cert (int mand);
63 void certificate_info (void);
64 void pgp_certificate_info (void);
65 void crl_info (void);
66 void privkey_info (void);
67 static void print_certificate_info (gnutls_x509_crt_t crt, FILE * out,
68 unsigned int);
69 static void gaa_parser (int argc, char **argv);
70 void generate_self_signed (void);
71 void generate_request (void);
72 gnutls_x509_crt_t *load_cert_list (int mand, int *size);
74 static void print_hex_datum (gnutls_datum_t * dat);
77 static gaainfo info;
78 FILE *outfile;
79 FILE *infile;
80 gnutls_digest_algorithm_t dig = GNUTLS_DIG_SHA1;
82 #define UNKNOWN "Unknown"
84 /* non interactive operation if set
86 int batch;
88 unsigned char buffer[64 * 1024];
89 const int buffer_size = sizeof (buffer);
91 static void
92 tls_log_func (int level, const char *str)
94 fprintf (stderr, "|<%d>| %s", level, str);
97 int
98 main (int argc, char **argv)
100 set_program_name (argv[0]);
101 cfg_init ();
102 gaa_parser (argc, argv);
104 return 0;
107 const char *
108 raw_to_string (const unsigned char *raw, size_t raw_size)
110 static char buf[1024];
111 size_t i;
112 if (raw_size == 0)
113 return NULL;
115 if (raw_size * 3 + 1 >= sizeof (buf))
116 return NULL;
118 for (i = 0; i < raw_size; i++)
120 sprintf (&(buf[i * 3]), "%02X%s", raw[i],
121 (i == raw_size - 1) ? "" : ":");
123 buf[sizeof (buf) - 1] = '\0';
125 return buf;
128 void
129 print_dsa_pkey (gnutls_datum * x, gnutls_datum * y, gnutls_datum * p,
130 gnutls_datum * q, gnutls_datum * g)
132 fprintf (outfile, "private key:");
133 print_hex_datum (x);
134 fprintf (outfile, "public key:");
135 print_hex_datum (y);
136 fprintf (outfile, "p:");
137 print_hex_datum (p);
138 fprintf (outfile, "q:");
139 print_hex_datum (q);
140 fprintf (outfile, "g:");
141 print_hex_datum (g);
144 void
145 print_rsa_pkey (gnutls_datum * m, gnutls_datum * e, gnutls_datum * d,
146 gnutls_datum * p, gnutls_datum * q, gnutls_datum * u)
148 fprintf (outfile, "modulus:");
149 print_hex_datum (m);
150 fprintf (outfile, "public exponent:");
151 print_hex_datum (e);
152 fprintf (outfile, "private exponent:");
153 print_hex_datum (d);
154 fprintf (outfile, "prime1:");
155 print_hex_datum (p);
156 fprintf (outfile, "prime2:");
157 print_hex_datum (q);
158 fprintf (outfile, "coefficient:");
159 print_hex_datum (u);
162 static gnutls_x509_privkey_t
163 generate_private_key_int (void)
165 gnutls_x509_privkey_t key;
166 int ret, key_type;
168 if (info.dsa)
170 key_type = GNUTLS_PK_DSA;
171 /* FIXME: Remove me once we depend on 1.3.x */
172 if (info.bits > 1024 && gcry_check_version ("1.3.1") == NULL)
173 info.bits = 1024;
175 else
176 key_type = GNUTLS_PK_RSA;
178 ret = gnutls_x509_privkey_init (&key);
179 if (ret < 0)
180 error (EXIT_FAILURE, 0, "privkey_init: %s", gnutls_strerror (ret));
182 fprintf (stderr, "Generating a %d bit %s private key...\n", info.bits,
183 gnutls_pk_algorithm_get_name (key_type));
185 if (info.quick_random == 0)
186 fprintf (stderr,
187 "This might take several minutes depending on availability of randomness"
188 " in /dev/random.\n");
190 ret = gnutls_x509_privkey_generate (key, key_type, info.bits, 0);
191 if (ret < 0)
192 error (EXIT_FAILURE, 0, "privkey_generate: %s", gnutls_strerror (ret));
194 return key;
197 static void
198 print_private_key (gnutls_x509_privkey_t key)
200 int ret;
201 size_t size;
203 if (!key)
204 return;
206 if (!info.pkcs8)
208 size = sizeof (buffer);
209 ret = gnutls_x509_privkey_export (key, info.outcert_format,
210 buffer, &size);
211 if (ret < 0)
212 error (EXIT_FAILURE, 0, "privkey_export: %s",
213 gnutls_strerror (ret));
215 else
217 unsigned int flags;
218 const char *pass;
220 if (info.export)
221 flags = GNUTLS_PKCS_USE_PKCS12_RC2_40;
222 else
223 flags = GNUTLS_PKCS_USE_PKCS12_3DES;
225 if ((pass = get_confirmed_pass (true)) == NULL || *pass == '\0')
226 flags = GNUTLS_PKCS_PLAIN;
228 size = sizeof (buffer);
229 ret =
230 gnutls_x509_privkey_export_pkcs8 (key, info.outcert_format, pass,
231 flags, buffer, &size);
232 if (ret < 0)
233 error (EXIT_FAILURE, 0, "privkey_export_pkcs8: %s",
234 gnutls_strerror (ret));
238 fwrite (buffer, 1, size, outfile);
241 void
242 generate_private_key (void)
244 gnutls_x509_privkey_t key;
246 key = generate_private_key_int ();
248 print_private_key (key);
250 gnutls_x509_privkey_deinit (key);
254 gnutls_x509_crt_t
255 generate_certificate (gnutls_x509_privkey_t * ret_key,
256 gnutls_x509_crt_t ca_crt, int proxy)
258 gnutls_x509_crt_t crt;
259 gnutls_x509_privkey_t key = NULL;
260 size_t size;
261 int ret;
262 int serial, client;
263 int days, result, ca_status = 0, path_len;
264 const char *str;
265 int vers;
266 unsigned int usage = 0, server;
267 gnutls_x509_crq_t crq; /* request */
269 ret = gnutls_x509_crt_init (&crt);
270 if (ret < 0)
271 error (EXIT_FAILURE, 0, "crt_init: %s", gnutls_strerror (ret));
273 crq = load_request ();
275 if (crq == NULL)
278 key = load_private_key (1);
280 if (!batch)
281 fprintf (stderr,
282 "Please enter the details of the certificate's distinguished name. "
283 "Just press enter to ignore a field.\n");
285 /* set the DN.
287 if (proxy)
289 result = gnutls_x509_crt_set_proxy_dn (crt, ca_crt, 0, NULL, 0);
290 if (result < 0)
291 error (EXIT_FAILURE, 0, "set_proxy_dn: %s",
292 gnutls_strerror (result));
294 get_cn_crt_set (crt);
296 else
298 get_country_crt_set (crt);
299 get_organization_crt_set (crt);
300 get_unit_crt_set (crt);
301 get_locality_crt_set (crt);
302 get_state_crt_set (crt);
303 get_cn_crt_set (crt);
304 get_uid_crt_set (crt);
305 get_oid_crt_set (crt);
307 if (!batch)
308 fprintf (stderr,
309 "This field should not be used in new certificates.\n");
311 get_pkcs9_email_crt_set (crt);
314 result = gnutls_x509_crt_set_key (crt, key);
315 if (result < 0)
316 error (EXIT_FAILURE, 0, "set_key: %s", gnutls_strerror (result));
318 else
320 result = gnutls_x509_crt_set_crq (crt, crq);
321 if (result < 0)
322 error (EXIT_FAILURE, 0, "set_crq: %s", gnutls_strerror (result));
326 serial = get_serial ();
327 buffer[4] = serial & 0xff;
328 buffer[3] = (serial >> 8) & 0xff;
329 buffer[2] = (serial >> 16) & 0xff;
330 buffer[1] = (serial >> 24) & 0xff;
331 buffer[0] = 0;
333 result = gnutls_x509_crt_set_serial (crt, buffer, 5);
334 if (result < 0)
335 error (EXIT_FAILURE, 0, "serial: %s", gnutls_strerror (result));
337 if (!batch)
338 fprintf (stderr, "\n\nActivation/Expiration time.\n");
340 gnutls_x509_crt_set_activation_time (crt, time (NULL));
342 days = get_days ();
344 result =
345 gnutls_x509_crt_set_expiration_time (crt,
346 time (NULL) +
347 days * 24 * 60 * 60);
348 if (result < 0)
349 error (EXIT_FAILURE, 0, "set_expiration: %s",
350 gnutls_strerror (result));
352 if (!batch)
353 fprintf (stderr, "\n\nExtensions.\n");
355 /* do not allow extensions on a v1 certificate */
356 if (info.v1_cert == 0)
359 if (proxy)
361 const char *policylanguage;
362 char *policy;
363 size_t policylen;
364 int proxypathlen = get_path_len ();
366 if (!batch)
368 printf ("1.3.6.1.5.5.7.21.1 ::= id-ppl-inheritALL\n");
369 printf ("1.3.6.1.5.5.7.21.2 ::= id-ppl-independent\n");
372 policylanguage = get_proxy_policy (&policy, &policylen);
374 result =
375 gnutls_x509_crt_set_proxy (crt, proxypathlen, policylanguage,
376 policy, policylen);
377 if (result < 0)
378 error (EXIT_FAILURE, 0, "set_proxy: %s",
379 gnutls_strerror (result));
382 if (!proxy)
383 ca_status = get_ca_status ();
384 if (ca_status)
385 path_len = get_path_len ();
386 else
387 path_len = -1;
389 result =
390 gnutls_x509_crt_set_basic_constraints (crt, ca_status, path_len);
391 if (result < 0)
392 error (EXIT_FAILURE, 0, "basic_constraints: %s",
393 gnutls_strerror (result));
395 client = get_tls_client_status ();
396 if (client != 0)
398 result = gnutls_x509_crt_set_key_purpose_oid (crt,
399 GNUTLS_KP_TLS_WWW_CLIENT,
401 if (result < 0)
402 error (EXIT_FAILURE, 0, "key_kp: %s",
403 gnutls_strerror (result));
406 server = get_tls_server_status ();
407 if (server != 0)
409 result = 0;
411 if (!proxy)
413 str = get_dns_name ();
414 if (str != NULL)
416 result = gnutls_x509_crt_set_subject_alternative_name
417 (crt, GNUTLS_SAN_DNSNAME, str);
419 else
421 str = get_ip_addr ();
422 if (str != NULL)
424 result = gnutls_x509_crt_set_subject_alternative_name
425 (crt, GNUTLS_SAN_IPADDRESS, str);
429 if (result < 0)
430 error (EXIT_FAILURE, 0, "subject_alt_name: %s",
431 gnutls_strerror (result));
434 result =
435 gnutls_x509_crt_set_key_purpose_oid (crt,
436 GNUTLS_KP_TLS_WWW_SERVER,
438 if (result < 0)
439 error (EXIT_FAILURE, 0, "key_kp: %s",
440 gnutls_strerror (result));
442 else if (!proxy)
444 str = get_email ();
446 if (str != NULL)
448 result = gnutls_x509_crt_set_subject_alternative_name
449 (crt, GNUTLS_SAN_RFC822NAME, str);
450 if (result < 0)
451 error (EXIT_FAILURE, 0, "subject_alt_name: %s",
452 gnutls_strerror (result));
456 if (!ca_status || server)
458 int pk;
461 pk = gnutls_x509_crt_get_pk_algorithm (crt, NULL);
463 if (pk != GNUTLS_PK_DSA)
464 { /* DSA keys can only sign.
466 result = get_sign_status (server);
467 if (result)
468 usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
470 result = get_encrypt_status (server);
471 if (result)
472 usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
474 else
475 usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
479 if (ca_status)
481 result = get_cert_sign_status ();
482 if (result)
483 usage |= GNUTLS_KEY_KEY_CERT_SIGN;
485 result = get_crl_sign_status ();
486 if (result)
487 usage |= GNUTLS_KEY_CRL_SIGN;
489 result = get_code_sign_status ();
490 if (result)
492 result =
493 gnutls_x509_crt_set_key_purpose_oid (crt,
494 GNUTLS_KP_CODE_SIGNING,
496 if (result < 0)
497 error (EXIT_FAILURE, 0, "key_kp: %s",
498 gnutls_strerror (result));
501 result = get_ocsp_sign_status ();
502 if (result)
504 result =
505 gnutls_x509_crt_set_key_purpose_oid (crt,
506 GNUTLS_KP_OCSP_SIGNING,
508 if (result < 0)
509 error (EXIT_FAILURE, 0, "key_kp: %s",
510 gnutls_strerror (result));
513 result = get_time_stamp_status ();
514 if (result)
516 result =
517 gnutls_x509_crt_set_key_purpose_oid (crt,
518 GNUTLS_KP_TIME_STAMPING,
520 if (result < 0)
521 error (EXIT_FAILURE, 0, "key_kp: %s",
522 gnutls_strerror (result));
526 if (usage != 0)
528 result = gnutls_x509_crt_set_key_usage (crt, usage);
529 if (result < 0)
530 error (EXIT_FAILURE, 0, "key_usage: %s",
531 gnutls_strerror (result));
534 /* Subject Key ID.
536 size = sizeof (buffer);
537 result = gnutls_x509_crt_get_key_id (crt, 0, buffer, &size);
538 if (result >= 0)
540 result = gnutls_x509_crt_set_subject_key_id (crt, buffer, size);
541 if (result < 0)
542 error (EXIT_FAILURE, 0, "set_subject_key_id: %s",
543 gnutls_strerror (result));
546 /* Authority Key ID.
548 if (ca_crt != NULL)
550 size = sizeof (buffer);
551 result = gnutls_x509_crt_get_subject_key_id (ca_crt, buffer,
552 &size, NULL);
553 if (result < 0)
555 size = sizeof (buffer);
556 result =
557 gnutls_x509_crt_get_key_id (ca_crt, 0, buffer, &size);
559 if (result >= 0)
561 result =
562 gnutls_x509_crt_set_authority_key_id (crt, buffer, size);
563 if (result < 0)
564 error (EXIT_FAILURE, 0, "set_authority_key_id: %s",
565 gnutls_strerror (result));
570 /* Version.
572 if (info.v1_cert != 0)
573 vers = 1;
574 else
575 vers = 3;
576 result = gnutls_x509_crt_set_version (crt, vers);
577 if (result < 0)
578 error (EXIT_FAILURE, 0, "set_version: %s", gnutls_strerror (result));
580 *ret_key = key;
581 return crt;
585 gnutls_x509_crl_t
586 generate_crl (void)
588 gnutls_x509_crl_t crl;
589 gnutls_x509_crt_t *crts;
590 int size;
591 int days, result, i;
592 time_t now = time (NULL);
594 result = gnutls_x509_crl_init (&crl);
595 if (result < 0)
596 error (EXIT_FAILURE, 0, "crl_init: %s", gnutls_strerror (result));
598 crts = load_cert_list (0, &size);
600 for (i = 0; i < size; i++)
602 result = gnutls_x509_crl_set_crt (crl, crts[i], now);
603 if (result < 0)
604 error (EXIT_FAILURE, 0, "crl_set_crt: %s",
605 gnutls_strerror (result));
608 result = gnutls_x509_crl_set_this_update (crl, now);
609 if (result < 0)
610 error (EXIT_FAILURE, 0, "this_update: %s", gnutls_strerror (result));
612 fprintf (stderr, "Update times.\n");
613 days = get_crl_next_update ();
615 result =
616 gnutls_x509_crl_set_next_update (crl, now + days * 24 * 60 * 60);
617 if (result < 0)
618 error (EXIT_FAILURE, 0, "next_update: %s", gnutls_strerror (result));
620 result = gnutls_x509_crl_set_version (crl, 2);
621 if (result < 0)
622 error (EXIT_FAILURE, 0, "set_version: %s", gnutls_strerror (result));
624 return crl;
627 void
628 generate_self_signed (void)
630 gnutls_x509_crt_t crt;
631 gnutls_x509_privkey_t key;
632 size_t size;
633 int result;
634 const char *uri;
636 fprintf (stderr, "Generating a self signed certificate...\n");
638 crt = generate_certificate (&key, NULL, 0);
640 if (!key)
641 key = load_private_key (1);
643 uri = get_crl_dist_point_url ();
644 if (uri)
646 result = gnutls_x509_crt_set_crl_dist_points (crt, GNUTLS_SAN_URI,
647 uri,
648 0 /* all reasons */ );
649 if (result < 0)
650 error (EXIT_FAILURE, 0, "crl_dist_points: %s",
651 gnutls_strerror (result));
654 print_certificate_info (crt, stderr, 0);
656 fprintf (stderr, "\n\nSigning certificate...\n");
658 result = gnutls_x509_crt_sign2 (crt, crt, key, dig, 0);
659 if (result < 0)
660 error (EXIT_FAILURE, 0, "crt_sign: %s", gnutls_strerror (result));
662 size = sizeof (buffer);
663 result =
664 gnutls_x509_crt_export (crt, info.outcert_format, buffer, &size);
665 if (result < 0)
666 error (EXIT_FAILURE, 0, "crt_export: %s", gnutls_strerror (result));
668 fwrite (buffer, 1, size, outfile);
670 gnutls_x509_crt_deinit (crt);
671 gnutls_x509_privkey_deinit (key);
674 void
675 generate_signed_certificate (void)
677 gnutls_x509_crt_t crt;
678 gnutls_x509_privkey_t key;
679 size_t size;
680 int result;
681 gnutls_x509_privkey_t ca_key;
682 gnutls_x509_crt_t ca_crt;
684 fprintf (stderr, "Generating a signed certificate...\n");
686 ca_key = load_ca_private_key ();
687 ca_crt = load_ca_cert ();
689 crt = generate_certificate (&key, ca_crt, 0);
691 /* Copy the CRL distribution points.
693 gnutls_x509_crt_cpy_crl_dist_points (crt, ca_crt);
694 /* it doesn't matter if we couldn't copy the CRL dist points.
697 print_certificate_info (crt, stderr, 0);
699 fprintf (stderr, "\n\nSigning certificate...\n");
701 result = gnutls_x509_crt_sign2 (crt, ca_crt, ca_key, dig, 0);
702 if (result < 0)
703 error (EXIT_FAILURE, 0, "crt_sign: %s", gnutls_strerror (result));
705 size = sizeof (buffer);
706 result =
707 gnutls_x509_crt_export (crt, info.outcert_format, buffer, &size);
708 if (result < 0)
709 error (EXIT_FAILURE, 0, "crt_export: %s", gnutls_strerror (result));
711 fwrite (buffer, 1, size, outfile);
713 gnutls_x509_crt_deinit (crt);
714 gnutls_x509_privkey_deinit (key);
717 void
718 generate_proxy_certificate (void)
720 gnutls_x509_crt_t crt, eecrt;
721 gnutls_x509_privkey_t key, eekey;
722 size_t size;
723 int result;
725 fprintf (stderr, "Generating a proxy certificate...\n");
727 eekey = load_ca_private_key ();
728 eecrt = load_cert (1);
730 crt = generate_certificate (&key, eecrt, 1);
732 print_certificate_info (crt, stderr, 0);
734 fprintf (stderr, "\n\nSigning certificate...\n");
736 result = gnutls_x509_crt_sign2 (crt, eecrt, eekey, dig, 0);
737 if (result < 0)
738 error (EXIT_FAILURE, 0, "crt_sign: %s", gnutls_strerror (result));
740 size = sizeof (buffer);
741 result =
742 gnutls_x509_crt_export (crt, info.outcert_format, buffer, &size);
743 if (result < 0)
744 error (EXIT_FAILURE, 0, "crt_export: %s", gnutls_strerror (result));
746 fwrite (buffer, 1, size, outfile);
748 gnutls_x509_crt_deinit (crt);
749 gnutls_x509_privkey_deinit (key);
752 void
753 generate_signed_crl (void)
755 gnutls_x509_crl_t crl;
756 int result;
757 gnutls_x509_privkey_t ca_key;
758 gnutls_x509_crt_t ca_crt;
760 fprintf (stderr, "Generating a signed CRL...\n");
762 ca_key = load_ca_private_key ();
763 ca_crt = load_ca_cert ();
764 crl = generate_crl ();
766 fprintf (stderr, "\n");
768 result = gnutls_x509_crl_sign (crl, ca_crt, ca_key);
769 if (result < 0)
770 error (EXIT_FAILURE, 0, "crl_sign: %s", gnutls_strerror (result));
772 print_crl_info (crl, stderr);
774 gnutls_x509_crl_deinit (crl);
777 void
778 update_signed_certificate (void)
780 gnutls_x509_crt_t crt;
781 size_t size;
782 int result;
783 gnutls_x509_privkey_t ca_key;
784 gnutls_x509_crt_t ca_crt;
785 int days;
786 time_t tim = time (NULL);
788 fprintf (stderr, "Generating a signed certificate...\n");
790 ca_key = load_ca_private_key ();
791 ca_crt = load_ca_cert ();
792 crt = load_cert (1);
794 fprintf (stderr, "Activation/Expiration time.\n");
795 gnutls_x509_crt_set_activation_time (crt, tim);
797 days = get_days ();
799 result =
800 gnutls_x509_crt_set_expiration_time (crt, tim + days * 24 * 60 * 60);
801 if (result < 0)
802 error (EXIT_FAILURE, 0, "set_expiration: %s",
803 gnutls_strerror (result));
805 fprintf (stderr, "\n\nSigning certificate...\n");
807 result = gnutls_x509_crt_sign2 (crt, ca_crt, ca_key, dig, 0);
808 if (result < 0)
809 error (EXIT_FAILURE, 0, "crt_sign: %s", gnutls_strerror (result));
811 size = sizeof (buffer);
812 result =
813 gnutls_x509_crt_export (crt, info.outcert_format, buffer, &size);
814 if (result < 0)
815 error (EXIT_FAILURE, 0, "crt_export: %s", gnutls_strerror (result));
817 fwrite (buffer, 1, size, outfile);
819 gnutls_x509_crt_deinit (crt);
822 FILE* safe_open_rw(const char* file)
824 mode_t oldmask;
825 FILE *fh;
827 if (info.privkey_op != 0)
829 oldmask = umask (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
832 fh = fopen (file, "wb");
834 if (info.privkey_op != 0)
836 umask (oldmask);
839 return fh;
842 void
843 gaa_parser (int argc, char **argv)
845 int ret;
847 if (gaa (argc, argv, &info) != -1)
849 fprintf (stderr, "Try `%s --help' for more information.\n",
850 program_name);
851 exit (1);
854 if (info.outfile)
856 outfile = safe_open_rw (info.outfile);
857 if (outfile == NULL)
858 error (EXIT_FAILURE, errno, "%s", info.outfile);
860 else
861 outfile = stdout;
863 if (info.infile)
865 infile = fopen (info.infile, "rb");
866 if (infile == NULL)
867 error (EXIT_FAILURE, errno, "%s", info.infile);
869 else
870 infile = stdin;
872 if (info.incert_format)
873 info.incert_format = GNUTLS_X509_FMT_DER;
874 else
875 info.incert_format = GNUTLS_X509_FMT_PEM;
877 if (info.outcert_format)
878 info.outcert_format = GNUTLS_X509_FMT_DER;
879 else
880 info.outcert_format = GNUTLS_X509_FMT_PEM;
882 if (info.hash != NULL)
884 if (strcasecmp (info.hash, "md5") == 0)
886 fprintf (stderr,
887 "Warning: MD5 is broken, and should not be used any more for digital signatures.\n");
888 dig = GNUTLS_DIG_MD5;
890 else if (strcasecmp (info.hash, "sha1") == 0)
891 dig = GNUTLS_DIG_SHA1;
892 else if (strcasecmp (info.hash, "sha256") == 0)
893 dig = GNUTLS_DIG_SHA256;
894 else if (strcasecmp (info.hash, "sha384") == 0)
895 dig = GNUTLS_DIG_SHA384;
896 else if (strcasecmp (info.hash, "sha512") == 0)
897 dig = GNUTLS_DIG_SHA512;
898 else if (strcasecmp (info.hash, "rmd160") == 0)
899 dig = GNUTLS_DIG_RMD160;
900 else
901 error (EXIT_FAILURE, 0, "invalid hash: %s", info.hash);
904 batch = 0;
905 if (info.template)
907 batch = 1;
908 template_parse (info.template);
911 if (info.quick_random != 0)
912 gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
914 gnutls_global_set_log_function (tls_log_func);
915 gnutls_global_set_log_level (info.debug);
917 if ((ret = gnutls_global_init ()) < 0)
918 error (EXIT_FAILURE, 0, "global_init: %s", gnutls_strerror (ret));
920 switch (info.action)
922 case 0:
923 generate_self_signed ();
924 break;
925 case 1:
926 generate_private_key ();
927 break;
928 case 2:
929 certificate_info ();
930 break;
931 case 3:
932 generate_request ();
933 break;
934 case 4:
935 generate_signed_certificate ();
936 break;
937 case 5:
938 verify_chain ();
939 break;
940 case 6:
941 privkey_info ();
942 break;
943 case 7:
944 update_signed_certificate ();
945 break;
946 case 8:
947 generate_pkcs12 ();
948 break;
949 case 9:
950 pkcs12_info ();
951 break;
952 case 10:
953 generate_prime (info.bits, 1);
954 break;
955 case 16:
956 generate_prime (info.bits, 0);
957 break;
958 case 11:
959 crl_info ();
960 break;
961 case 12:
962 pkcs7_info ();
963 break;
964 case 13:
965 generate_signed_crl ();
966 break;
967 case 14:
968 verify_crl ();
969 break;
970 case 15:
971 smime_to_pkcs7 ();
972 break;
973 case 17:
974 generate_proxy_certificate ();
975 break;
976 case 18:
977 generate_pkcs8 ();
978 break;
979 #ifdef ENABLE_OPENPGP
980 case 19:
981 pgp_certificate_info ();
982 break;
983 case 20:
984 pgp_privkey_info ();
985 break;
986 case 21:
987 pgp_ring_info ();
988 break;
989 #endif
990 default:
991 gaa_help ();
992 exit (0);
994 fclose (outfile);
997 #define MAX_CRTS 500
998 void
999 certificate_info (void)
1001 gnutls_x509_crt_t crt[MAX_CRTS];
1002 size_t size;
1003 int ret, i, count;
1004 gnutls_datum_t pem;
1005 unsigned int crt_num;
1007 pem.data = fread_file (infile, &size);
1008 pem.size = size;
1010 crt_num = MAX_CRTS;
1011 ret =
1012 gnutls_x509_crt_list_import (crt, &crt_num, &pem, info.incert_format,
1013 GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);
1014 if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
1016 error (0, 0,
1017 "Too many certificates (%d), will only read the first %d.",
1018 crt_num, MAX_CRTS);
1019 crt_num = MAX_CRTS;
1020 ret = gnutls_x509_crt_list_import (crt, &crt_num, &pem,
1021 info.incert_format, 0);
1023 if (ret < 0)
1024 error (EXIT_FAILURE, 0, "Import error: %s", gnutls_strerror (ret));
1026 free (pem.data);
1028 count = ret;
1030 if (count > 1 && info.outcert_format == GNUTLS_X509_FMT_DER)
1032 error (0, 0,
1033 "Cannot output multiple certificates in DER format, using PEM instead.");
1034 info.outcert_format = GNUTLS_X509_FMT_PEM;
1037 for (i = 0; i < count; i++)
1039 if (i > 0)
1040 fprintf (outfile, "\n");
1042 if (info.outcert_format == GNUTLS_X509_FMT_PEM)
1043 print_certificate_info (crt[i], outfile, 1);
1045 size = sizeof (buffer);
1046 ret = gnutls_x509_crt_export (crt[i], info.outcert_format, buffer,
1047 &size);
1048 if (ret < 0)
1049 error (EXIT_FAILURE, 0, "Export error: %s", gnutls_strerror (ret));
1050 fwrite (buffer, 1, size, outfile);
1054 #ifdef ENABLE_OPENPGP
1056 void
1057 pgp_certificate_info (void)
1059 gnutls_openpgp_crt_t crt;
1060 size_t size;
1061 int ret;
1062 gnutls_datum_t pem, out_data;
1064 pem.data = fread_file (infile, &size);
1065 pem.size = size;
1067 ret = gnutls_openpgp_crt_init (&crt);
1068 if (ret < 0)
1069 error (EXIT_FAILURE, 0, "openpgp_crt_init: %s", gnutls_strerror (ret));
1071 ret = gnutls_openpgp_crt_import (crt, &pem, info.incert_format);
1073 if (ret < 0)
1074 error (EXIT_FAILURE, 0, "Import error: %s", gnutls_strerror (ret));
1076 free (pem.data);
1078 if (info.outcert_format == GNUTLS_OPENPGP_FMT_BASE64)
1080 ret = gnutls_openpgp_crt_print (crt, 0, &out_data);
1082 if (ret == 0)
1084 fprintf (outfile, "%s\n", out_data.data);
1085 gnutls_free (out_data.data);
1089 size = sizeof (buffer);
1090 ret =
1091 gnutls_openpgp_crt_export (crt, info.outcert_format, buffer, &size);
1092 if (ret < 0)
1094 error (EXIT_FAILURE, 0, "Export error: %s", gnutls_strerror (ret));
1095 fwrite (buffer, 1, size, outfile);
1098 fprintf (outfile, "%s\n", buffer);
1100 gnutls_openpgp_crt_deinit (crt);
1103 void
1104 pgp_privkey_info (void)
1106 gnutls_openpgp_privkey_t key;
1107 gnutls_openpgp_keyid_t keyid;
1108 size_t size;
1109 int ret, i, subkeys;
1110 gnutls_datum_t pem;
1111 const char *cprint;
1113 size = fread (buffer, 1, sizeof (buffer) - 1, infile);
1114 buffer[size] = 0;
1116 gnutls_openpgp_privkey_init (&key);
1118 pem.data = buffer;
1119 pem.size = size;
1121 ret =
1122 gnutls_openpgp_privkey_import (key, &pem, info.incert_format, NULL,
1125 if (ret < 0)
1126 error (EXIT_FAILURE, 0, "Import error: %s", gnutls_strerror (ret));
1128 /* Public key algorithm
1130 subkeys = gnutls_openpgp_privkey_get_subkey_count (key);
1131 if (subkeys < 0)
1132 error (EXIT_FAILURE, 0, "privkey_get_subkey_count: %s",
1133 gnutls_strerror (subkeys));
1135 for (i = -1; i < subkeys; i++)
1138 if (i != -1)
1139 fprintf (outfile, "Subkey[%d]:\n", i);
1141 fprintf (outfile, "Public Key Info:\n");
1143 if (i == -1)
1144 ret = gnutls_openpgp_privkey_get_pk_algorithm (key, NULL);
1145 else
1146 ret =
1147 gnutls_openpgp_privkey_get_subkey_pk_algorithm (key, i, NULL);
1149 fprintf (outfile, "\tPublic Key Algorithm: ");
1151 cprint = gnutls_pk_algorithm_get_name (ret);
1152 if (cprint == NULL)
1153 cprint = UNKNOWN;
1154 fprintf (outfile, "%s\n", cprint);
1156 /* Print the raw public and private keys
1159 if (ret == GNUTLS_PK_RSA)
1161 gnutls_datum_t m, e, d, p, q, u;
1163 if (i == -1)
1164 ret =
1165 gnutls_openpgp_privkey_export_rsa_raw (key, &m, &e, &d, &p,
1166 &q, &u);
1167 else
1168 ret =
1169 gnutls_openpgp_privkey_export_subkey_rsa_raw (key, i, &m,
1170 &e, &d, &p,
1171 &q, &u);
1172 if (ret < 0)
1173 fprintf (stderr, "Error in key RSA data export: %s\n",
1174 gnutls_strerror (ret));
1175 else
1176 print_rsa_pkey (&m, &e, &d, &p, &q, &u);
1179 else if (ret == GNUTLS_PK_DSA)
1181 gnutls_datum_t p, q, g, y, x;
1183 if (i == -1)
1184 ret =
1185 gnutls_openpgp_privkey_export_dsa_raw (key, &p, &q, &g, &y,
1186 &x);
1187 else
1188 ret =
1189 gnutls_openpgp_privkey_export_subkey_dsa_raw (key, i, &p,
1190 &q, &g, &y,
1191 &x);
1192 if (ret < 0)
1193 fprintf (stderr, "Error in key DSA data export: %s\n",
1194 gnutls_strerror (ret));
1195 else
1196 print_dsa_pkey (&x, &y, &p, &q, &g);
1199 fprintf (outfile, "\n");
1201 size = sizeof (buffer);
1202 if (i == -1)
1203 ret = gnutls_openpgp_privkey_get_key_id (key, keyid);
1204 else
1205 ret = gnutls_openpgp_privkey_get_subkey_id (key, i, keyid);
1207 if (ret < 0)
1209 fprintf (stderr, "Error in key id calculation: %s\n",
1210 gnutls_strerror (ret));
1212 else
1214 fprintf (outfile, "Public Key ID: %s\n",
1215 raw_to_string (keyid, 8));
1220 size = sizeof (buffer);
1221 ret =
1222 gnutls_openpgp_privkey_export (key, GNUTLS_OPENPGP_FMT_BASE64,
1223 NULL, 0, buffer, &size);
1224 if (ret < 0)
1225 error (EXIT_FAILURE, 0, "Export error: %s", gnutls_strerror (ret));
1227 fprintf (outfile, "\n%s\n", buffer);
1230 void
1231 pgp_ring_info (void)
1233 gnutls_openpgp_keyring_t ring;
1234 gnutls_openpgp_crt_t crt;
1235 size_t size;
1236 int ret, i, count;
1237 gnutls_datum_t pem;
1239 pem.data = fread_file (infile, &size);
1240 pem.size = size;
1242 ret = gnutls_openpgp_keyring_init (&ring);
1243 if (ret < 0)
1244 error (EXIT_FAILURE, 0, "openpgp_keyring_init: %s",
1245 gnutls_strerror (ret));
1247 ret = gnutls_openpgp_keyring_import (ring, &pem, info.incert_format);
1249 if (ret < 0)
1250 error (EXIT_FAILURE, 0, "Import error: %s", gnutls_strerror (ret));
1252 free (pem.data);
1254 count = gnutls_openpgp_keyring_get_crt_count (ring);
1255 if (count > 0)
1256 fprintf (outfile, "Keyring contains %d OpenPGP certificates\n\n",
1257 count);
1258 else
1259 error (EXIT_FAILURE, 0, "Keyring error: %s", gnutls_strerror (count));
1261 for (i = 0; i < count; i++)
1263 ret = gnutls_openpgp_keyring_get_crt (ring, i, &crt);
1265 if (ret < 0)
1267 error (EXIT_FAILURE, 0, "Export error: %s", gnutls_strerror (ret));
1270 size = sizeof (buffer);
1271 ret =
1272 gnutls_openpgp_crt_export (crt, info.outcert_format, buffer,
1273 &size);
1274 if (ret < 0)
1276 error (EXIT_FAILURE, 0, "Export error: %s", gnutls_strerror (ret));
1279 fwrite (buffer, 1, size, outfile);
1280 fprintf (outfile, "\n\n");
1282 gnutls_openpgp_crt_deinit (crt);
1287 gnutls_openpgp_keyring_deinit (ring);
1291 #endif
1293 static void
1294 print_hex_datum (gnutls_datum_t * dat)
1296 unsigned int j;
1297 #define SPACE "\t"
1298 fprintf (outfile, "\n" SPACE);
1299 for (j = 0; j < dat->size; j++)
1301 fprintf (outfile, "%.2x:", (unsigned char) dat->data[j]);
1302 if ((j + 1) % 15 == 0)
1303 fprintf (outfile, "\n" SPACE);
1305 fprintf (outfile, "\n");
1309 static void
1310 print_certificate_info (gnutls_x509_crt_t crt, FILE * out,
1311 unsigned int all)
1313 gnutls_datum_t info;
1314 int ret;
1316 if (all)
1317 ret = gnutls_x509_crt_print (crt, GNUTLS_CRT_PRINT_FULL, &info);
1318 else
1319 ret =
1320 gnutls_x509_crt_print (crt, GNUTLS_CRT_PRINT_UNSIGNED_FULL, &info);
1321 if (ret == 0)
1323 fprintf (out, "%s\n", info.data);
1324 gnutls_free (info.data);
1327 if (out == stderr && batch == 0) /* interactive */
1328 if (read_yesno ("Is the above information ok? (Y/N): ") == 0)
1330 exit (1);
1334 static void
1335 print_crl_info (gnutls_x509_crl_t crl, FILE * out)
1337 gnutls_datum_t info;
1338 int ret;
1339 size_t size;
1341 ret = gnutls_x509_crl_print (crl, GNUTLS_CRT_PRINT_FULL, &info);
1342 if (ret < 0)
1343 error (EXIT_FAILURE, 0, "crl_print: %s", gnutls_strerror (ret));
1345 fprintf (out, "%s\n", info.data);
1347 gnutls_free (info.data);
1349 size = sizeof (buffer);
1350 ret = gnutls_x509_crl_export (crl, GNUTLS_X509_FMT_PEM, buffer, &size);
1351 if (ret < 0)
1352 error (EXIT_FAILURE, 0, "crl_export: %s", gnutls_strerror (ret));
1354 fwrite (buffer, 1, size, outfile);
1357 void
1358 crl_info (void)
1360 gnutls_x509_crl_t crl;
1361 int ret;
1362 size_t size;
1363 gnutls_datum_t pem;
1365 ret = gnutls_x509_crl_init (&crl);
1366 if (ret < 0)
1367 error (EXIT_FAILURE, 0, "crl_init: %s", gnutls_strerror (ret));
1369 pem.data = fread_file (infile, &size);
1370 pem.size = size;
1372 if (!pem.data)
1373 error (EXIT_FAILURE, errno, "%s", info.infile ? info.infile :
1374 "standard input");
1376 ret = gnutls_x509_crl_import (crl, &pem, info.incert_format);
1378 free (pem.data);
1379 if (ret < 0)
1380 error (EXIT_FAILURE, 0, "Import error: %s", gnutls_strerror (ret));
1382 print_crl_info (crl, outfile);
1385 void
1386 privkey_info (void)
1388 gnutls_x509_privkey_t key;
1389 size_t size;
1390 int ret;
1391 gnutls_datum_t pem;
1392 const char *cprint;
1393 const char *pass;
1395 size = fread (buffer, 1, sizeof (buffer) - 1, infile);
1396 buffer[size] = 0;
1398 gnutls_x509_privkey_init (&key);
1400 pem.data = buffer;
1401 pem.size = size;
1403 ret = 0;
1404 if (!info.pkcs8)
1405 ret = gnutls_x509_privkey_import (key, &pem, info.incert_format);
1407 /* If we failed to import the certificate previously try PKCS #8 */
1408 if (info.pkcs8 || ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
1410 if (info.pass)
1411 pass = info.pass;
1412 else
1413 pass = get_pass ();
1414 ret =
1415 gnutls_x509_privkey_import_pkcs8 (key, &pem, info.incert_format,
1416 pass, 0);
1418 if (ret < 0)
1419 error (EXIT_FAILURE, 0, "Import error: %s", gnutls_strerror (ret));
1421 /* Public key algorithm
1423 fprintf (outfile, "Public Key Info:\n");
1424 ret = gnutls_x509_privkey_get_pk_algorithm (key);
1425 fprintf (outfile, "\tPublic Key Algorithm: ");
1427 cprint = gnutls_pk_algorithm_get_name (ret);
1428 if (cprint == NULL)
1429 cprint = UNKNOWN;
1430 fprintf (outfile, "%s\n", cprint);
1432 /* Print the raw public and private keys
1434 if (ret == GNUTLS_PK_RSA)
1436 gnutls_datum_t m, e, d, p, q, u;
1438 ret =
1439 gnutls_x509_privkey_export_rsa_raw (key, &m, &e, &d, &p, &q, &u);
1440 if (ret < 0)
1441 fprintf (stderr, "Error in key RSA data export: %s\n",
1442 gnutls_strerror (ret));
1443 else
1444 print_rsa_pkey (&m, &e, &d, &p, &q, &u);
1447 else if (ret == GNUTLS_PK_DSA)
1449 gnutls_datum_t p, q, g, y, x;
1451 ret = gnutls_x509_privkey_export_dsa_raw (key, &p, &q, &g, &y, &x);
1452 if (ret < 0)
1453 fprintf (stderr, "Error in key DSA data export: %s\n",
1454 gnutls_strerror (ret));
1455 else
1456 print_dsa_pkey (&x, &y, &p, &q, &g);
1459 fprintf (outfile, "\n");
1461 size = sizeof (buffer);
1462 if ((ret = gnutls_x509_privkey_get_key_id (key, 0, buffer, &size)) < 0)
1464 fprintf (stderr, "Error in key id calculation: %s\n",
1465 gnutls_strerror (ret));
1467 else
1469 fprintf (outfile, "Public Key ID: %s\n",
1470 raw_to_string (buffer, size));
1473 if (info.fix_key != 0)
1475 ret = gnutls_x509_privkey_fix (key);
1476 if (ret < 0)
1477 error (EXIT_FAILURE, 0, "privkey_fix: %s", gnutls_strerror (ret));
1480 size = sizeof (buffer);
1481 ret =
1482 gnutls_x509_privkey_export (key, GNUTLS_X509_FMT_PEM, buffer, &size);
1483 if (ret < 0)
1484 error (EXIT_FAILURE, 0, "Export error: %s", gnutls_strerror (ret));
1486 fprintf (outfile, "\n%s\n", buffer);
1490 /* Load the private key.
1491 * @mand should be non zero if it is required to read a private key.
1493 gnutls_x509_privkey_t
1494 load_private_key (int mand)
1496 gnutls_x509_privkey_t key;
1497 int ret;
1498 gnutls_datum_t dat;
1499 size_t size;
1501 if (!info.privkey && !mand)
1502 return NULL;
1504 if (info.privkey == NULL)
1505 error (EXIT_FAILURE, 0, "missing --load-privkey");
1507 ret = gnutls_x509_privkey_init (&key);
1508 if (ret < 0)
1509 error (EXIT_FAILURE, 0, "privkey_init: %s", gnutls_strerror (ret));
1511 dat.data = read_binary_file (info.privkey, &size);
1512 dat.size = size;
1514 if (!dat.data)
1515 error (EXIT_FAILURE, errno, "reading --load-privkey: %s",
1516 info.privkey);
1518 if (info.pkcs8)
1520 const char *pass = get_pass ();
1521 ret =
1522 gnutls_x509_privkey_import_pkcs8 (key, &dat, info.incert_format,
1523 pass, 0);
1525 else
1526 ret = gnutls_x509_privkey_import (key, &dat, info.incert_format);
1528 free (dat.data);
1530 if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
1532 error (EXIT_FAILURE, 0,
1533 "Import error: Could not find a valid PEM header. Check if your key is PKCS #8 or PKCS #12 encoded.");
1536 if (ret < 0)
1537 error (EXIT_FAILURE, 0, "importing --load-privkey: %s: %s",
1538 info.privkey, gnutls_strerror (ret));
1540 return key;
1543 /* Load the Certificate Request.
1545 gnutls_x509_crq_t
1546 load_request (void)
1548 gnutls_x509_crq_t crq;
1549 int ret;
1550 gnutls_datum_t dat;
1551 size_t size;
1553 if (!info.request)
1554 return NULL;
1556 ret = gnutls_x509_crq_init (&crq);
1557 if (ret < 0)
1558 error (EXIT_FAILURE, 0, "crq_init: %s", gnutls_strerror (ret));
1560 dat.data = read_binary_file (info.request, &size);
1561 dat.size = size;
1563 if (!dat.data)
1564 error (EXIT_FAILURE, errno, "reading --load-request: %s",
1565 info.request);
1567 ret = gnutls_x509_crq_import (crq, &dat, info.incert_format);
1568 if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
1570 error (EXIT_FAILURE, 0,
1571 "Import error: Could not find a valid PEM header.");
1574 free (dat.data);
1575 if (ret < 0)
1576 error (EXIT_FAILURE, 0, "importing --load-request: %s: %s",
1577 info.request, gnutls_strerror (ret));
1579 return crq;
1582 /* Load the CA's private key.
1584 gnutls_x509_privkey_t
1585 load_ca_private_key (void)
1587 gnutls_x509_privkey_t key;
1588 int ret;
1589 gnutls_datum_t dat;
1590 size_t size;
1592 if (info.ca_privkey == NULL)
1593 error (EXIT_FAILURE, 0, "missing --load-ca-privkey");
1595 ret = gnutls_x509_privkey_init (&key);
1596 if (ret < 0)
1597 error (EXIT_FAILURE, 0, "privkey_init: %s", gnutls_strerror (ret));
1599 dat.data = read_binary_file (info.ca_privkey, &size);
1600 dat.size = size;
1602 if (!dat.data)
1603 error (EXIT_FAILURE, errno, "reading --load-ca-privkey: %s",
1604 info.ca_privkey);
1606 if (info.pkcs8)
1608 const char *pass = get_pass ();
1609 ret =
1610 gnutls_x509_privkey_import_pkcs8 (key, &dat, info.incert_format,
1611 pass, 0);
1613 else
1614 ret = gnutls_x509_privkey_import (key, &dat, info.incert_format);
1615 free (dat.data);
1616 if (ret < 0)
1617 error (EXIT_FAILURE, 0, "importing --load-ca-privkey: %s: %s",
1618 info.ca_privkey, gnutls_strerror (ret));
1620 return key;
1623 /* Loads the CA's certificate
1625 gnutls_x509_crt_t
1626 load_ca_cert (void)
1628 gnutls_x509_crt_t crt;
1629 int ret;
1630 gnutls_datum_t dat;
1631 size_t size;
1633 if (info.ca == NULL)
1634 error (EXIT_FAILURE, 0, "missing --load-ca-certificate");
1636 ret = gnutls_x509_crt_init (&crt);
1637 if (ret < 0)
1638 error (EXIT_FAILURE, 0, "crt_init: %s", gnutls_strerror (ret));
1640 dat.data = read_binary_file (info.ca, &size);
1641 dat.size = size;
1643 if (!dat.data)
1644 error (EXIT_FAILURE, errno, "reading --load-ca-certificate: %s",
1645 info.ca);
1647 ret = gnutls_x509_crt_import (crt, &dat, info.incert_format);
1648 free (dat.data);
1649 if (ret < 0)
1650 error (EXIT_FAILURE, 0, "importing --load-ca-certificate: %s: %s",
1651 info.ca, gnutls_strerror (ret));
1653 return crt;
1656 /* Loads the certificate
1657 * If mand is non zero then a certificate is mandatory. Otherwise
1658 * null will be returned if the certificate loading fails.
1660 gnutls_x509_crt_t
1661 load_cert (int mand)
1663 gnutls_x509_crt_t *crt;
1664 int size;
1666 crt = load_cert_list (mand, &size);
1668 return crt ? crt[0] : NULL;
1671 #define MAX_CERTS 256
1673 /* Loads a certificate list
1675 gnutls_x509_crt_t *
1676 load_cert_list (int mand, int *crt_size)
1678 FILE *fd;
1679 static gnutls_x509_crt_t crt[MAX_CERTS];
1680 char *ptr;
1681 int ret, i;
1682 gnutls_datum_t dat;
1683 size_t size;
1684 int ptr_size;
1686 *crt_size = 0;
1687 fprintf (stderr, "Loading certificate list...\n");
1689 if (info.cert == NULL)
1691 if (mand)
1692 error (EXIT_FAILURE, 0, "missing --load-certificate");
1693 else
1694 return NULL;
1697 fd = fopen (info.cert, "r");
1698 if (fd == NULL)
1699 error (EXIT_FAILURE, 0, "File %s does not exist", info.cert);
1701 size = fread (buffer, 1, sizeof (buffer) - 1, fd);
1702 buffer[size] = 0;
1704 fclose (fd);
1706 ptr = buffer;
1707 ptr_size = size;
1709 for (i = 0; i < MAX_CERTS; i++)
1711 ret = gnutls_x509_crt_init (&crt[i]);
1712 if (ret < 0)
1713 error (EXIT_FAILURE, 0, "crt_init: %s", gnutls_strerror (ret));
1715 dat.data = ptr;
1716 dat.size = ptr_size;
1718 ret = gnutls_x509_crt_import (crt[i], &dat, info.incert_format);
1719 if (ret < 0 && *crt_size > 0)
1720 break;
1721 if (ret < 0)
1722 error (EXIT_FAILURE, 0, "crt_import: %s", gnutls_strerror (ret));
1724 ptr = strstr (ptr, "---END");
1725 if (ptr == NULL)
1726 break;
1727 ptr++;
1729 ptr_size = size;
1730 ptr_size -=
1731 (unsigned int) ((unsigned char *) ptr -
1732 (unsigned char *) buffer);
1734 if (ptr_size < 0)
1735 break;
1737 (*crt_size)++;
1739 fprintf (stderr, "Loaded %d certificates.\n", *crt_size);
1741 return crt;
1745 /* Generate a PKCS #10 certificate request.
1747 void
1748 generate_request (void)
1750 gnutls_x509_crq_t crq;
1751 gnutls_x509_privkey_t key;
1752 int ret;
1753 const char *pass;
1754 size_t size;
1756 fprintf (stderr, "Generating a PKCS #10 certificate request...\n");
1758 ret = gnutls_x509_crq_init (&crq);
1759 if (ret < 0)
1760 error (EXIT_FAILURE, 0, "crq_init: %s", gnutls_strerror (ret));
1762 /* Load the private key.
1764 key = load_private_key (0);
1765 if (!key)
1767 key = generate_private_key_int ();
1769 print_private_key (key);
1772 /* Set the DN.
1774 get_country_crq_set (crq);
1775 get_organization_crq_set (crq);
1776 get_unit_crq_set (crq);
1777 get_locality_crq_set (crq);
1778 get_state_crq_set (crq);
1779 get_cn_crq_set (crq);
1780 get_uid_crq_set (crq);
1781 get_oid_crq_set (crq);
1783 pass = get_challenge_pass ();
1785 if (pass != NULL)
1787 ret = gnutls_x509_crq_set_challenge_password (crq, pass);
1788 if (ret < 0)
1789 error (EXIT_FAILURE, 0, "set_pass: %s", gnutls_strerror (ret));
1792 ret = gnutls_x509_crq_set_key (crq, key);
1793 if (ret < 0)
1794 error (EXIT_FAILURE, 0, "set_key: %s", gnutls_strerror (ret));
1796 ret = gnutls_x509_crq_sign (crq, key);
1797 if (ret < 0)
1798 error (EXIT_FAILURE, 0, "sign: %s", gnutls_strerror (ret));
1800 size = sizeof (buffer);
1801 ret = gnutls_x509_crq_export (crq, info.outcert_format, buffer, &size);
1802 if (ret < 0)
1803 error (EXIT_FAILURE, 0, "export: %s", gnutls_strerror (ret));
1805 fwrite (buffer, 1, size, outfile);
1807 gnutls_x509_crq_deinit (crq);
1808 gnutls_x509_privkey_deinit (key);
1812 static void print_verification_res (gnutls_x509_crt_t crt,
1813 gnutls_x509_crt_t issuer,
1814 gnutls_x509_crl_t * crl_list,
1815 int crl_list_size);
1817 #define CERT_SEP "-----BEGIN CERT"
1818 #define CRL_SEP "-----BEGIN X509 CRL"
1820 _verify_x509_mem (const void *cert, int cert_size)
1822 int siz, i;
1823 const char *ptr;
1824 int ret;
1825 char name[256];
1826 char issuer_name[256];
1827 size_t name_size;
1828 size_t issuer_name_size;
1829 gnutls_datum_t tmp;
1830 gnutls_x509_crt_t *x509_cert_list = NULL;
1831 gnutls_x509_crl_t *x509_crl_list = NULL;
1832 int x509_ncerts, x509_ncrls;
1835 /* Decode the CA certificate
1838 /* Decode the CRL list
1840 siz = cert_size;
1841 ptr = cert;
1843 i = 1;
1845 if (strstr (ptr, CRL_SEP) != NULL) /* if CRLs exist */
1848 x509_crl_list =
1849 (gnutls_x509_crl_t *) realloc (x509_crl_list,
1850 i * sizeof (gnutls_x509_crl_t));
1851 if (x509_crl_list == NULL)
1852 error (EXIT_FAILURE, 0, "memory error");
1854 tmp.data = (char *) ptr;
1855 tmp.size = cert_size;
1856 tmp.size -=
1857 (unsigned int) ((unsigned char *) ptr -
1858 (unsigned char *) cert);
1860 ret = gnutls_x509_crl_init (&x509_crl_list[i - 1]);
1861 if (ret < 0)
1862 error (EXIT_FAILURE, 0, "Error parsing the CRL[%d]: %s", i,
1863 gnutls_strerror (ret));
1865 ret = gnutls_x509_crl_import (x509_crl_list[i - 1], &tmp,
1866 GNUTLS_X509_FMT_PEM);
1867 if (ret < 0)
1868 error (EXIT_FAILURE, 0, "Error parsing the CRL[%d]: %s", i,
1869 gnutls_strerror (ret));
1871 /* now we move ptr after the pem header */
1872 ptr = strstr (ptr, CRL_SEP);
1873 if (ptr != NULL)
1874 ptr++;
1876 i++;
1878 while ((ptr = strstr (ptr, CRL_SEP)) != NULL);
1880 x509_ncrls = i - 1;
1883 /* Decode the certificate chain.
1885 siz = cert_size;
1886 ptr = cert;
1888 i = 1;
1892 x509_cert_list =
1893 (gnutls_x509_crt_t *) realloc (x509_cert_list,
1894 i * sizeof (gnutls_x509_crt_t));
1895 if (x509_cert_list == NULL)
1896 error (EXIT_FAILURE, 0, "memory error");
1899 tmp.data = (char *) ptr;
1900 tmp.size = cert_size;
1901 tmp.size -=
1902 (unsigned int) ((unsigned char *) ptr - (unsigned char *) cert);
1904 ret = gnutls_x509_crt_init (&x509_cert_list[i - 1]);
1905 if (ret < 0)
1906 error (EXIT_FAILURE, 0, "Error parsing the certificate[%d]: %s", i,
1907 gnutls_strerror (ret));
1909 ret =
1910 gnutls_x509_crt_import (x509_cert_list[i - 1], &tmp,
1911 GNUTLS_X509_FMT_PEM);
1912 if (ret < 0)
1913 error (EXIT_FAILURE, 0, "Error parsing the certificate[%d]: %s", i,
1914 gnutls_strerror (ret));
1917 if (i - 1 != 0)
1919 /* verify the previous certificate using this one
1920 * as CA.
1923 name_size = sizeof (name);
1924 ret =
1925 gnutls_x509_crt_get_dn (x509_cert_list[i - 2], name,
1926 &name_size);
1927 if (ret < 0)
1928 error (EXIT_FAILURE, 0, "get_dn: %s", gnutls_strerror (ret));
1930 fprintf (outfile, "Certificate[%d]: %s\n", i - 2, name);
1932 /* print issuer
1934 issuer_name_size = sizeof (issuer_name);
1935 ret =
1936 gnutls_x509_crt_get_issuer_dn (x509_cert_list[i - 2],
1937 issuer_name,
1938 &issuer_name_size);
1939 if (ret < 0)
1940 error (EXIT_FAILURE, 0, "get_issuer_dn: %s",
1941 gnutls_strerror (ret));
1943 fprintf (outfile, "\tIssued by: %s\n", issuer_name);
1945 /* Get the Issuer's name
1947 name_size = sizeof (name);
1948 ret =
1949 gnutls_x509_crt_get_dn (x509_cert_list[i - 1], name,
1950 &name_size);
1951 if (ret < 0)
1952 error (EXIT_FAILURE, 0, "get_dn: %s", gnutls_strerror (ret));
1954 fprintf (outfile, "\tVerifying against certificate[%d].\n",
1955 i - 1);
1957 if (strcmp (issuer_name, name) != 0)
1959 fprintf (stderr, "Error: Issuer's name: %s\n", name);
1960 error (EXIT_FAILURE, 0,
1961 "Issuer's name does not match the next certificate");
1964 fprintf (outfile, "\tVerification output: ");
1965 print_verification_res (x509_cert_list[i - 2],
1966 x509_cert_list[i - 1], x509_crl_list,
1967 x509_ncrls);
1968 fprintf (outfile, ".\n\n");
1973 /* now we move ptr after the pem header
1975 ptr = strstr (ptr, CERT_SEP);
1976 if (ptr != NULL)
1977 ptr++;
1979 i++;
1981 while ((ptr = strstr (ptr, CERT_SEP)) != NULL);
1983 x509_ncerts = i - 1;
1985 /* The last certificate in the list will be used as
1986 * a CA (should be self signed).
1988 name_size = sizeof (name);
1989 ret = gnutls_x509_crt_get_dn (x509_cert_list[x509_ncerts - 1], name,
1990 &name_size);
1991 if (ret < 0)
1992 error (EXIT_FAILURE, 0, "get_dn: %s", gnutls_strerror (ret));
1994 fprintf (outfile, "Certificate[%d]: %s\n", x509_ncerts - 1, name);
1996 /* print issuer
1998 issuer_name_size = sizeof (issuer_name);
1999 ret =
2000 gnutls_x509_crt_get_issuer_dn (x509_cert_list[x509_ncerts - 1],
2001 issuer_name, &issuer_name_size);
2002 if (ret < 0)
2003 error (EXIT_FAILURE, 0, "get_issuer_dn: %s", gnutls_strerror (ret));
2005 fprintf (outfile, "\tIssued by: %s\n", name);
2007 if (strcmp (issuer_name, name) != 0)
2008 error (EXIT_FAILURE, 0,
2009 "Error: The last certificate is not self signed.");
2011 fprintf (outfile, "\tVerification output: ");
2012 print_verification_res (x509_cert_list[x509_ncerts - 1],
2013 x509_cert_list[x509_ncerts - 1], x509_crl_list,
2014 x509_ncrls);
2016 fprintf (outfile, ".\n\n");
2018 for (i = 0; i < x509_ncerts; i++)
2019 gnutls_x509_crt_deinit (x509_cert_list[i]);
2021 for (i = 0; i < x509_ncrls; i++)
2022 gnutls_x509_crl_deinit (x509_crl_list[i]);
2024 free (x509_cert_list);
2025 free (x509_crl_list);
2027 if (ret < 0)
2028 error (EXIT_FAILURE, 0, "Error in verification: %s",
2029 gnutls_strerror (ret));
2031 return 0;
2034 static void
2035 print_verification_res (gnutls_x509_crt_t crt,
2036 gnutls_x509_crt_t issuer,
2037 gnutls_x509_crl_t * crl_list, int crl_list_size)
2039 unsigned int output;
2040 int comma = 0;
2041 int ret;
2042 time_t now = time (0);
2044 ret = gnutls_x509_crt_verify (crt, &issuer, 1, 0, &output);
2045 if (ret < 0)
2046 error (EXIT_FAILURE, 0, "Error in verification: %s",
2047 gnutls_strerror (ret));
2049 if (output & GNUTLS_CERT_INVALID)
2051 fprintf (outfile, "Not verified");
2052 comma = 1;
2054 else
2056 fprintf (outfile, "Verified");
2057 comma = 1;
2060 if (output & GNUTLS_CERT_SIGNER_NOT_CA)
2062 if (comma)
2063 fprintf (outfile, ", ");
2064 fprintf (outfile, "Issuer is not a CA");
2065 comma = 1;
2068 if (output & GNUTLS_CERT_INSECURE_ALGORITHM)
2070 if (comma)
2071 fprintf (outfile, ", ");
2072 fprintf (outfile, "Insecure algorithm");
2073 comma = 1;
2076 /* Check expiration dates.
2079 if (gnutls_x509_crt_get_activation_time (crt) > now)
2081 if (comma)
2082 fprintf (outfile, ", ");
2083 comma = 1;
2084 fprintf (outfile, "Not activated");
2087 if (gnutls_x509_crt_get_expiration_time (crt) < now)
2089 if (comma)
2090 fprintf (outfile, ", ");
2091 comma = 1;
2092 fprintf (outfile, "Expired");
2095 ret = gnutls_x509_crt_check_revocation (crt, crl_list, crl_list_size);
2096 if (ret < 0)
2097 error (EXIT_FAILURE, 0, "Revocation check: %s", gnutls_strerror (ret));
2099 if (ret == 1)
2100 { /* revoked */
2101 if (comma)
2102 fprintf (outfile, ", ");
2103 comma = 1;
2104 fprintf (outfile, "Revoked");
2108 void
2109 verify_chain (void)
2111 char *buffer;
2112 size_t size;
2114 buffer = fread_file (infile, &size);
2115 if (buffer == NULL)
2116 error (EXIT_FAILURE, errno, "reading chain");
2118 buffer[size] = 0;
2120 _verify_x509_mem (buffer, size);
2124 void
2125 verify_crl (void)
2127 size_t size, dn_size;
2128 char dn[128];
2129 unsigned int output;
2130 int comma = 0;
2131 int ret;
2132 gnutls_datum_t pem;
2133 gnutls_x509_crl_t crl;
2134 time_t now = time (0);
2135 gnutls_x509_crt_t issuer;
2137 issuer = load_ca_cert ();
2139 fprintf (outfile, "\nCA certificate:\n");
2141 dn_size = sizeof (dn);
2142 ret = gnutls_x509_crt_get_dn (issuer, dn, &dn_size);
2143 if (ret < 0)
2144 error (EXIT_FAILURE, 0, "crt_get_dn: %s", gnutls_strerror (ret));
2146 fprintf (outfile, "\tSubject: %s\n\n", dn);
2148 ret = gnutls_x509_crl_init (&crl);
2149 if (ret < 0)
2150 error (EXIT_FAILURE, 0, "crl_init: %s", gnutls_strerror (ret));
2152 pem.data = fread_file (infile, &size);
2153 pem.size = size;
2155 ret = gnutls_x509_crl_import (crl, &pem, info.incert_format);
2156 free (pem.data);
2157 if (ret < 0)
2158 error (EXIT_FAILURE, 0, "Import error: %s", gnutls_strerror (ret));
2160 print_crl_info (crl, outfile);
2162 fprintf (outfile, "Verification output: ");
2163 ret = gnutls_x509_crl_verify (crl, &issuer, 1, 0, &output);
2164 if (ret < 0)
2165 error (EXIT_FAILURE, 0, "Verification error: %s",
2166 gnutls_strerror (ret));
2168 if (output & GNUTLS_CERT_INVALID)
2170 fprintf (outfile, "Not verified");
2171 comma = 1;
2173 else
2175 fprintf (outfile, "Verified");
2176 comma = 1;
2179 if (output & GNUTLS_CERT_SIGNER_NOT_CA)
2181 if (comma)
2182 fprintf (outfile, ", ");
2183 fprintf (outfile, "Issuer is not a CA");
2184 comma = 1;
2187 if (output & GNUTLS_CERT_INSECURE_ALGORITHM)
2189 if (comma)
2190 fprintf (outfile, ", ");
2191 fprintf (outfile, "Insecure algorithm");
2192 comma = 1;
2195 /* Check expiration dates.
2198 if (gnutls_x509_crl_get_this_update (crl) > now)
2200 if (comma)
2201 fprintf (outfile, ", ");
2202 comma = 1;
2203 fprintf (outfile, "Issued in the future!");
2206 if (gnutls_x509_crl_get_next_update (crl) < now)
2208 if (comma)
2209 fprintf (outfile, ", ");
2210 comma = 1;
2211 fprintf (outfile, "CRL is not up to date");
2214 fprintf (outfile, "\n");
2217 void
2218 generate_pkcs8 (void)
2220 gnutls_x509_privkey_t key;
2221 int result;
2222 size_t size;
2223 int flags = 0;
2224 const char *password;
2226 fprintf (stderr, "Generating a PKCS #8 key structure...\n");
2228 key = load_private_key (1);
2230 if (info.pass)
2231 password = info.pass;
2232 else
2233 password = get_pass ();
2235 if (info.export)
2236 flags = GNUTLS_PKCS_USE_PKCS12_RC2_40;
2237 else
2238 flags = GNUTLS_PKCS_USE_PKCS12_3DES;
2240 if (password == NULL || password[0] == 0)
2242 flags = GNUTLS_PKCS_PLAIN;
2245 size = sizeof (buffer);
2246 result =
2247 gnutls_x509_privkey_export_pkcs8 (key, info.outcert_format,
2248 password, flags, buffer, &size);
2250 if (result < 0)
2251 error (EXIT_FAILURE, 0, "key_export: %s", gnutls_strerror (result));
2253 fwrite (buffer, 1, size, outfile);
2258 #include <gnutls/pkcs12.h>
2259 #include <unistd.h>
2261 void
2262 generate_pkcs12 (void)
2264 gnutls_pkcs12_t pkcs12;
2265 gnutls_x509_crt_t *crts;
2266 gnutls_x509_privkey_t key;
2267 int result;
2268 size_t size;
2269 gnutls_datum_t data;
2270 const char *password;
2271 const char *name;
2272 unsigned int flags;
2273 gnutls_datum_t key_id;
2274 unsigned char _key_id[20];
2275 int index;
2276 int ncrts;
2277 int i;
2279 fprintf (stderr, "Generating a PKCS #12 structure...\n");
2281 key = load_private_key (0);
2282 crts = load_cert_list (0, &ncrts);
2284 name = get_pkcs12_key_name ();
2286 result = gnutls_pkcs12_init (&pkcs12);
2287 if (result < 0)
2288 error (EXIT_FAILURE, 0, "pkcs12_init: %s", gnutls_strerror (result));
2290 if (info.pass)
2291 password = info.pass;
2292 else
2293 password = get_pass ();
2295 for (i = 0; i < ncrts; i++)
2297 gnutls_pkcs12_bag_t bag;
2299 result = gnutls_pkcs12_bag_init (&bag);
2300 if (result < 0)
2301 error (EXIT_FAILURE, 0, "bag_init: %s", gnutls_strerror (result));
2303 result = gnutls_pkcs12_bag_set_crt (bag, crts[i]);
2304 if (result < 0)
2305 error (EXIT_FAILURE, 0, "set_crt[%d]: %s", i,
2306 gnutls_strerror (result));
2308 index = result;
2310 result = gnutls_pkcs12_bag_set_friendly_name (bag, index, name);
2311 if (result < 0)
2312 error (EXIT_FAILURE, 0, "bag_set_friendly_name: %s",
2313 gnutls_strerror (result));
2315 size = sizeof (_key_id);
2316 result = gnutls_x509_crt_get_key_id (crts[i], 0, _key_id, &size);
2317 if (result < 0)
2318 error (EXIT_FAILURE, 0, "key_id[%d]: %s", i,
2319 gnutls_strerror (result));
2321 key_id.data = _key_id;
2322 key_id.size = size;
2324 result = gnutls_pkcs12_bag_set_key_id (bag, index, &key_id);
2325 if (result < 0)
2326 error (EXIT_FAILURE, 0, "bag_set_key_id: %s",
2327 gnutls_strerror (result));
2329 if (info.export)
2330 flags = GNUTLS_PKCS_USE_PKCS12_RC2_40;
2331 else
2332 flags = GNUTLS_PKCS8_USE_PKCS12_3DES;
2334 result = gnutls_pkcs12_bag_encrypt (bag, password, flags);
2335 if (result < 0)
2336 error (EXIT_FAILURE, 0, "bag_encrypt: %s",
2337 gnutls_strerror (result));
2339 result = gnutls_pkcs12_set_bag (pkcs12, bag);
2340 if (result < 0)
2341 error (EXIT_FAILURE, 0, "set_bag: %s", gnutls_strerror (result));
2344 if (key)
2346 gnutls_pkcs12_bag_t kbag;
2348 result = gnutls_pkcs12_bag_init (&kbag);
2349 if (result < 0)
2350 error (EXIT_FAILURE, 0, "bag_init: %s", gnutls_strerror (result));
2352 if (info.export)
2353 flags = GNUTLS_PKCS_USE_PKCS12_RC2_40;
2354 else
2355 flags = GNUTLS_PKCS_USE_PKCS12_3DES;
2357 size = sizeof (buffer);
2358 result =
2359 gnutls_x509_privkey_export_pkcs8 (key, GNUTLS_X509_FMT_DER,
2360 password, flags, buffer,
2361 &size);
2362 if (result < 0)
2363 error (EXIT_FAILURE, 0, "key_export: %s",
2364 gnutls_strerror (result));
2366 data.data = buffer;
2367 data.size = size;
2368 result =
2369 gnutls_pkcs12_bag_set_data (kbag,
2370 GNUTLS_BAG_PKCS8_ENCRYPTED_KEY,
2371 &data);
2372 if (result < 0)
2373 error (EXIT_FAILURE, 0, "bag_set_data: %s",
2374 gnutls_strerror (result));
2376 index = result;
2378 result = gnutls_pkcs12_bag_set_friendly_name (kbag, index, name);
2379 if (result < 0)
2380 error (EXIT_FAILURE, 0, "bag_set_friendly_name: %s",
2381 gnutls_strerror (result));
2383 size = sizeof (_key_id);
2384 result = gnutls_x509_privkey_get_key_id (key, 0, _key_id, &size);
2385 if (result < 0)
2386 error (EXIT_FAILURE, 0, "key_id: %s", gnutls_strerror (result));
2388 key_id.data = _key_id;
2389 key_id.size = size;
2391 result = gnutls_pkcs12_bag_set_key_id (kbag, index, &key_id);
2392 if (result < 0)
2393 error (EXIT_FAILURE, 0, "bag_set_key_id: %s",
2394 gnutls_strerror (result));
2396 result = gnutls_pkcs12_set_bag (pkcs12, kbag);
2397 if (result < 0)
2398 error (EXIT_FAILURE, 0, "set_bag: %s", gnutls_strerror (result));
2401 result = gnutls_pkcs12_generate_mac (pkcs12, password);
2402 if (result < 0)
2403 error (EXIT_FAILURE, 0, "generate_mac: %s", gnutls_strerror (result));
2405 size = sizeof (buffer);
2406 result =
2407 gnutls_pkcs12_export (pkcs12, info.outcert_format, buffer, &size);
2408 if (result < 0)
2409 error (EXIT_FAILURE, 0, "pkcs12_export: %s", gnutls_strerror (result));
2411 fwrite (buffer, 1, size, outfile);
2415 const char *
2416 BAGTYPE (gnutls_pkcs12_bag_type_t x)
2418 switch (x)
2420 case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
2421 return "PKCS #8 Encrypted key";
2422 case GNUTLS_BAG_EMPTY:
2423 return "Empty";
2424 case GNUTLS_BAG_PKCS8_KEY:
2425 return "PKCS #8 Key";
2426 case GNUTLS_BAG_CERTIFICATE:
2427 return "Certificate";
2428 case GNUTLS_BAG_ENCRYPTED:
2429 return "Encrypted";
2430 case GNUTLS_BAG_CRL:
2431 return "CRL";
2432 default:
2433 return "Unknown";
2437 void
2438 print_bag_data (gnutls_pkcs12_bag_t bag)
2440 int result;
2441 int count, i, type;
2442 gnutls_datum_t cdata, id;
2443 const char *str, *name;
2444 gnutls_datum_t out;
2446 count = gnutls_pkcs12_bag_get_count (bag);
2447 if (count < 0)
2448 error (EXIT_FAILURE, 0, "get_count: %s", gnutls_strerror (count));
2450 fprintf (outfile, "\tElements: %d\n", count);
2452 for (i = 0; i < count; i++)
2454 type = gnutls_pkcs12_bag_get_type (bag, i);
2455 if (type < 0)
2456 error (EXIT_FAILURE, 0, "get_type: %s", gnutls_strerror (type));
2458 fprintf (stderr, "\tType: %s\n", BAGTYPE (type));
2460 name = NULL;
2461 result =
2462 gnutls_pkcs12_bag_get_friendly_name (bag, i, (char **) &name);
2463 if (result < 0)
2464 error (EXIT_FAILURE, 0, "get_friendly_name: %s",
2465 gnutls_strerror (type));
2466 if (name)
2467 fprintf (outfile, "\tFriendly name: %s\n", name);
2469 id.data = NULL;
2470 id.size = 0;
2471 result = gnutls_pkcs12_bag_get_key_id (bag, i, &id);
2472 if (result < 0)
2473 error (EXIT_FAILURE, 0, "get_key_id: %s", gnutls_strerror (type));
2474 fprintf (outfile, "\tKey ID: %s\n",
2475 raw_to_string (id.data, id.size));
2477 result = gnutls_pkcs12_bag_get_data (bag, i, &cdata);
2478 if (result < 0)
2479 error (EXIT_FAILURE, 0, "get_data: %s", gnutls_strerror (result));
2481 switch (type)
2483 case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
2484 str = "ENCRYPTED PRIVATE KEY";
2485 break;
2486 case GNUTLS_BAG_PKCS8_KEY:
2487 str = "PRIVATE KEY";
2488 break;
2489 case GNUTLS_BAG_CERTIFICATE:
2490 str = "CERTIFICATE";
2491 break;
2492 case GNUTLS_BAG_CRL:
2493 str = "CRL";
2494 break;
2495 case GNUTLS_BAG_ENCRYPTED:
2496 case GNUTLS_BAG_EMPTY:
2497 default:
2498 str = NULL;
2501 if (str != NULL)
2503 gnutls_pem_base64_encode_alloc (str, &cdata, &out);
2504 fprintf (outfile, "%s\n", out.data);
2506 gnutls_free (out.data);
2512 void
2513 pkcs12_info (void)
2515 gnutls_pkcs12_t pkcs12;
2516 gnutls_pkcs12_bag_t bag;
2517 int result;
2518 size_t size;
2519 gnutls_datum_t data;
2520 const char *password;
2521 int index;
2523 result = gnutls_pkcs12_init (&pkcs12);
2524 if (result < 0)
2525 error (EXIT_FAILURE, 0, "p12_init: %s", gnutls_strerror (result));
2527 data.data = fread_file (infile, &size);
2528 data.size = size;
2530 result = gnutls_pkcs12_import (pkcs12, &data, info.incert_format, 0);
2531 free (data.data);
2532 if (result < 0)
2533 error (EXIT_FAILURE, 0, "p12_import: %s", gnutls_strerror (result));
2535 if (info.pass)
2536 password = info.pass;
2537 else
2538 password = get_pass ();
2540 result = gnutls_pkcs12_verify_mac (pkcs12, password);
2541 if (result < 0)
2542 error (EXIT_FAILURE, 0, "verify_mac: %s", gnutls_strerror (result));
2544 index = 0;
2546 for (index = 0;; index++)
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_get_bag (pkcs12, index, bag);
2553 if (result < 0)
2554 break;
2556 result = gnutls_pkcs12_bag_get_count (bag);
2557 if (result < 0)
2558 error (EXIT_FAILURE, 0, "bag_count: %s", gnutls_strerror (result));
2560 fprintf (outfile, "BAG #%d\n", index);
2562 result = gnutls_pkcs12_bag_get_type (bag, 0);
2563 if (result < 0)
2564 error (EXIT_FAILURE, 0, "bag_init: %s", gnutls_strerror (result));
2566 if (result == GNUTLS_BAG_ENCRYPTED)
2568 fprintf (stderr, "\tType: %s\n", BAGTYPE (result));
2569 fprintf (stderr, "\n\tDecrypting...\n");
2571 result = gnutls_pkcs12_bag_decrypt (bag, password);
2573 if (result < 0)
2574 error (EXIT_FAILURE, 0, "bag_decrypt: %s",
2575 gnutls_strerror (result));
2577 result = gnutls_pkcs12_bag_get_count (bag);
2578 if (result < 0)
2579 error (EXIT_FAILURE, 0, "encrypted bag_count: %s",
2580 gnutls_strerror (result));
2583 print_bag_data (bag);
2585 gnutls_pkcs12_bag_deinit (bag);
2589 void
2590 pkcs7_info (void)
2592 gnutls_pkcs7_t pkcs7;
2593 int result;
2594 size_t size;
2595 gnutls_datum_t data, b64;
2596 int index, count;
2598 result = gnutls_pkcs7_init (&pkcs7);
2599 if (result < 0)
2600 error (EXIT_FAILURE, 0, "p7_init: %s", gnutls_strerror (result));
2602 data.data = fread_file (infile, &size);
2603 data.size = size;
2605 result = gnutls_pkcs7_import (pkcs7, &data, info.incert_format);
2606 free (data.data);
2607 if (result < 0)
2608 error (EXIT_FAILURE, 0, "Import error: %s", gnutls_strerror (result));
2610 /* Read and print the certificates.
2612 result = gnutls_pkcs7_get_crt_count (pkcs7);
2613 if (result < 0)
2614 error (EXIT_FAILURE, 0, "p7_crt_count: %s", gnutls_strerror (result));
2616 count = result;
2618 if (count > 0)
2619 fprintf (outfile, "Number of certificates: %u\n", count);
2621 for (index = 0; index < count; index++)
2623 fputs ("\n", outfile);
2625 size = sizeof (buffer);
2626 result = gnutls_pkcs7_get_crt_raw (pkcs7, index, buffer, &size);
2627 if (result < 0)
2628 break;
2630 data.data = buffer;
2631 data.size = size;
2633 result = gnutls_pem_base64_encode_alloc ("CERTIFICATE", &data, &b64);
2634 if (result < 0)
2635 error (EXIT_FAILURE, 0, "encoding: %s", gnutls_strerror (result));
2637 fputs (b64.data, outfile);
2638 gnutls_free (b64.data);
2641 /* Read the CRLs now.
2643 result = gnutls_pkcs7_get_crl_count (pkcs7);
2644 if (result < 0)
2645 error (EXIT_FAILURE, 0, "p7_crl_count: %s", gnutls_strerror (result));
2647 count = result;
2649 if (count > 0)
2650 fprintf (outfile, "\nNumber of CRLs: %u\n", count);
2652 for (index = 0; index < count; index++)
2654 fputs ("\n", outfile);
2656 size = sizeof (buffer);
2657 result = gnutls_pkcs7_get_crl_raw (pkcs7, index, buffer, &size);
2658 if (result < 0)
2659 break;
2661 data.data = buffer;
2662 data.size = size;
2664 result = gnutls_pem_base64_encode_alloc ("X509 CRL", &data, &b64);
2665 if (result < 0)
2666 error (EXIT_FAILURE, 0, "encoding: %s", gnutls_strerror (result));
2668 fputs (b64.data, outfile);
2669 gnutls_free (b64.data);
2673 void
2674 smime_to_pkcs7 (void)
2676 size_t linesize = 0;
2677 char *lineptr = NULL;
2678 ssize_t len;
2680 /* Find body. FIXME: Handle non-b64 Content-Transfer-Encoding.
2681 Reject non-S/MIME tagged Content-Type's? */
2684 len = getline (&lineptr, &linesize, infile);
2685 if (len == -1)
2686 error (EXIT_FAILURE, 0,
2687 "Cannot find RFC 2822 header/body separator");
2689 while (strcmp (lineptr, "\r\n") != 0 && strcmp (lineptr, "\n") != 0);
2693 len = getline (&lineptr, &linesize, infile);
2694 if (len == -1)
2695 error (EXIT_FAILURE, 0, "Message has RFC 2822 header but no body");
2697 while (strcmp (lineptr, "\r\n") == 0 && strcmp (lineptr, "\n") == 0);
2699 fprintf (outfile, "%s", "-----BEGIN PKCS7-----\n");
2703 while (len > 0
2704 && (lineptr[len - 1] == '\r' || lineptr[len - 1] == '\n'))
2705 lineptr[--len] = '\0';
2706 if (strcmp (lineptr, "") != 0)
2707 fprintf (outfile, "%s\n", lineptr);
2708 len = getline (&lineptr, &linesize, infile);
2710 while (len != -1);
2712 fprintf (outfile, "%s", "-----END PKCS7-----\n");
2714 free (lineptr);
2717 void
2718 certtool_version (void)
2720 version_etc (stdout, program_name, PACKAGE_STRING,
2721 gnutls_check_version (NULL), "Nikos Mavrogiannopoulos",
2722 "Simon Josefsson", (char *) NULL);