_gnutls_strdatum_to_buf() will account for NULL input.
[gnutls.git] / src / certtool.c
blobab9c7bae2f0a7d7bdb2bab2fff4fea07d1785602
1 /*
2 * Copyright (C) 2003-2012 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/x509.h>
25 #include <gnutls/openpgp.h>
26 #include <gnutls/pkcs12.h>
27 #include <gnutls/pkcs11.h>
28 #include <gnutls/abstract.h>
29 #include <gnutls/crypto.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 <common.h>
50 #include "certtool-args.h"
51 #include "certtool-common.h"
53 static void privkey_info_int (common_info_st*, gnutls_x509_privkey_t key);
54 static void print_crl_info (gnutls_x509_crl_t crl, FILE * out);
55 void pkcs7_info (void);
56 void crq_info (void);
57 void smime_to_pkcs7 (void);
58 void pkcs12_info (common_info_st*);
59 void generate_pkcs12 (common_info_st *);
60 void generate_pkcs8 (common_info_st *);
61 static void verify_chain (void);
62 void verify_crl (common_info_st * cinfo);
63 void pubkey_info (gnutls_x509_crt_t crt, common_info_st *);
64 void pgp_privkey_info (void);
65 void pgp_ring_info (void);
66 void certificate_info (int, common_info_st *);
67 void pgp_certificate_info (void);
68 void crl_info (void);
69 void privkey_info (common_info_st*);
70 static void cmd_parser (int argc, char **argv);
71 void generate_self_signed (common_info_st *);
72 void generate_request (common_info_st *);
73 static void print_certificate_info (gnutls_x509_crt_t crt, FILE * out,
74 unsigned int all);
75 static void verify_certificate (common_info_st * cinfo);
77 FILE *outfile;
78 FILE *infile;
79 static gnutls_digest_algorithm_t default_dig;
80 static unsigned int incert_format, outcert_format;
81 static unsigned int req_key_type;
82 gnutls_certificate_print_formats_t full_format = GNUTLS_CRT_PRINT_FULL;
84 /* non interactive operation if set
86 int batch;
89 static void
90 tls_log_func (int level, const char *str)
92 fprintf (stderr, "|<%d>| %s", level, str);
95 int
96 main (int argc, char **argv)
98 set_program_name (argv[0]);
99 cfg_init ();
100 cmd_parser (argc, argv);
102 return 0;
105 static gnutls_x509_privkey_t
106 generate_private_key_int (common_info_st * cinfo)
108 gnutls_x509_privkey_t key;
109 int ret, key_type, bits;
111 key_type = req_key_type;
113 ret = gnutls_x509_privkey_init (&key);
114 if (ret < 0)
115 error (EXIT_FAILURE, 0, "privkey_init: %s", gnutls_strerror (ret));
117 bits = get_bits (key_type, cinfo->bits, cinfo->sec_param, 1);
119 fprintf (stderr, "Generating a %d bit %s private key...\n",
120 bits, gnutls_pk_algorithm_get_name (key_type));
122 if (bits > 1024 && key_type == GNUTLS_PK_DSA)
123 fprintf (stderr,
124 "Note that DSA keys with size over 1024 may cause incompatibility problems when used with earlier than TLS 1.2 versions.\n\n");
126 ret = gnutls_x509_privkey_generate (key, key_type, bits, 0);
127 if (ret < 0)
128 error (EXIT_FAILURE, 0, "privkey_generate: %s", gnutls_strerror (ret));
130 ret = gnutls_x509_privkey_verify_params (key);
131 if (ret < 0)
132 error (EXIT_FAILURE, 0, "privkey_verify_params: %s", gnutls_strerror (ret));
134 return key;
137 static int
138 cipher_to_flags (const char *cipher)
140 if (cipher == NULL)
142 return GNUTLS_PKCS_USE_PBES2_AES_128;
144 else if (strcasecmp (cipher, "3des") == 0)
146 return GNUTLS_PKCS_USE_PBES2_3DES;
148 else if (strcasecmp (cipher, "3des-pkcs12") == 0)
150 return GNUTLS_PKCS_USE_PKCS12_3DES;
152 else if (strcasecmp (cipher, "arcfour") == 0)
154 return GNUTLS_PKCS_USE_PKCS12_ARCFOUR;
156 else if (strcasecmp (cipher, "aes-128") == 0)
158 return GNUTLS_PKCS_USE_PBES2_AES_128;
160 else if (strcasecmp (cipher, "aes-192") == 0)
162 return GNUTLS_PKCS_USE_PBES2_AES_192;
164 else if (strcasecmp (cipher, "aes-256") == 0)
166 return GNUTLS_PKCS_USE_PBES2_AES_256;
168 else if (strcasecmp (cipher, "rc2-40") == 0)
170 return GNUTLS_PKCS_USE_PKCS12_RC2_40;
173 error (EXIT_FAILURE, 0, "unknown cipher %s\n", cipher);
174 return -1;
178 static void
179 print_private_key (common_info_st* cinfo, gnutls_x509_privkey_t key)
181 int ret;
182 size_t size;
184 if (!key)
185 return;
187 if (outcert_format == GNUTLS_X509_FMT_PEM)
188 privkey_info_int(cinfo, key);
190 if (!cinfo->pkcs8)
192 size = buffer_size;
193 ret = gnutls_x509_privkey_export (key, outcert_format,
194 buffer, &size);
195 if (ret < 0)
196 error (EXIT_FAILURE, 0, "privkey_export: %s", gnutls_strerror (ret));
198 else
200 unsigned int flags = 0;
201 const char *pass;
203 pass = get_password(cinfo, &flags, 0);
204 flags |= cipher_to_flags (cinfo->pkcs_cipher);
206 size = buffer_size;
207 ret =
208 gnutls_x509_privkey_export_pkcs8 (key, outcert_format, pass,
209 flags, buffer, &size);
210 if (ret < 0)
211 error (EXIT_FAILURE, 0, "privkey_export_pkcs8: %s",
212 gnutls_strerror (ret));
215 fwrite (buffer, 1, size, outfile);
218 static void
219 generate_private_key (common_info_st* cinfo)
221 gnutls_x509_privkey_t key;
223 key = generate_private_key_int (cinfo);
225 print_private_key (cinfo, key);
227 gnutls_x509_privkey_deinit (key);
231 static gnutls_x509_crt_t
232 generate_certificate (gnutls_privkey_t * ret_key,
233 gnutls_x509_crt_t ca_crt, int proxy,
234 common_info_st * cinfo)
236 gnutls_x509_crt_t crt;
237 gnutls_privkey_t key = NULL;
238 gnutls_pubkey_t pubkey;
239 size_t size;
240 int ret;
241 int client;
242 int days, result, ca_status = 0, is_ike = 0, path_len;
243 int vers;
244 unsigned int usage = 0, server;
245 gnutls_x509_crq_t crq; /* request */
247 ret = gnutls_x509_crt_init (&crt);
248 if (ret < 0)
249 error (EXIT_FAILURE, 0, "crt_init: %s", gnutls_strerror (ret));
251 crq = load_request (cinfo);
253 if (crq == NULL)
256 key = load_private_key (0, cinfo);
258 pubkey = load_public_key_or_import (1, key, cinfo);
260 if (!batch)
261 fprintf (stderr,
262 "Please enter the details of the certificate's distinguished name. "
263 "Just press enter to ignore a field.\n");
265 /* set the DN.
267 if (proxy)
269 result = gnutls_x509_crt_set_proxy_dn (crt, ca_crt, 0, NULL, 0);
270 if (result < 0)
271 error (EXIT_FAILURE, 0, "set_proxy_dn: %s",
272 gnutls_strerror (result));
274 get_cn_crt_set (crt);
276 else
278 get_country_crt_set (crt);
279 get_organization_crt_set (crt);
280 get_unit_crt_set (crt);
281 get_locality_crt_set (crt);
282 get_state_crt_set (crt);
283 get_cn_crt_set (crt);
284 get_dc_set (TYPE_CRT, crt);
285 get_uid_crt_set (crt);
286 get_oid_crt_set (crt);
287 get_key_purpose_set (crt);
289 if (!batch)
290 fprintf (stderr,
291 "This field should not be used in new certificates.\n");
293 get_pkcs9_email_crt_set (crt);
296 result = gnutls_x509_crt_set_pubkey (crt, pubkey);
297 if (result < 0)
298 error (EXIT_FAILURE, 0, "set_key: %s", gnutls_strerror (result));
300 else
302 result = gnutls_x509_crt_set_crq (crt, crq);
303 if (result < 0)
304 error (EXIT_FAILURE, 0, "set_crq: %s", gnutls_strerror (result));
309 int serial = get_serial ();
310 char bin_serial[5];
312 bin_serial[4] = serial & 0xff;
313 bin_serial[3] = (serial >> 8) & 0xff;
314 bin_serial[2] = (serial >> 16) & 0xff;
315 bin_serial[1] = (serial >> 24) & 0xff;
316 bin_serial[0] = 0;
318 result = gnutls_x509_crt_set_serial (crt, bin_serial, 5);
319 if (result < 0)
320 error (EXIT_FAILURE, 0, "serial: %s", gnutls_strerror (result));
323 if (!batch)
324 fprintf (stderr, "\n\nActivation/Expiration time.\n");
326 gnutls_x509_crt_set_activation_time (crt, time (NULL));
328 days = get_days ();
330 result =
331 gnutls_x509_crt_set_expiration_time (crt,
332 time (NULL) + ((time_t) days) * 24 * 60 * 60);
333 if (result < 0)
334 error (EXIT_FAILURE, 0, "set_expiration: %s", gnutls_strerror (result));
336 if (!batch)
337 fprintf (stderr, "\n\nExtensions.\n");
339 /* do not allow extensions on a v1 certificate */
340 if (crq && get_crq_extensions_status () != 0)
342 result = gnutls_x509_crt_set_crq_extensions (crt, crq);
343 if (result < 0)
344 error (EXIT_FAILURE, 0, "set_crq: %s", gnutls_strerror (result));
347 /* append additional extensions */
348 if (cinfo->v1_cert == 0)
351 if (proxy)
353 const char *policylanguage;
354 char *policy;
355 size_t policylen;
356 int proxypathlen = get_path_len ();
358 if (!batch)
360 printf ("1.3.6.1.5.5.7.21.1 ::= id-ppl-inheritALL\n");
361 printf ("1.3.6.1.5.5.7.21.2 ::= id-ppl-independent\n");
364 policylanguage = get_proxy_policy (&policy, &policylen);
366 result =
367 gnutls_x509_crt_set_proxy (crt, proxypathlen, policylanguage,
368 policy, policylen);
369 if (result < 0)
370 error (EXIT_FAILURE, 0, "set_proxy: %s",
371 gnutls_strerror (result));
374 if (!proxy)
375 ca_status = get_ca_status ();
376 if (ca_status)
377 path_len = get_path_len ();
378 else
379 path_len = -1;
381 result =
382 gnutls_x509_crt_set_basic_constraints (crt, ca_status, path_len);
383 if (result < 0)
384 error (EXIT_FAILURE, 0, "basic_constraints: %s",
385 gnutls_strerror (result));
387 client = get_tls_client_status ();
388 if (client != 0)
390 result = gnutls_x509_crt_set_key_purpose_oid (crt,
391 GNUTLS_KP_TLS_WWW_CLIENT,
393 if (result < 0)
394 error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (result));
397 is_ike = get_ipsec_ike_status ();
398 server = get_tls_server_status ();
400 get_dns_name_set (TYPE_CRT, crt);
401 get_uri_set (TYPE_CRT, crt);
402 get_ip_addr_set (TYPE_CRT, crt);
403 get_policy_set (crt);
405 if (server != 0)
407 result = 0;
409 result =
410 gnutls_x509_crt_set_key_purpose_oid (crt,
411 GNUTLS_KP_TLS_WWW_SERVER, 0);
412 if (result < 0)
413 error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (result));
415 else if (!proxy)
417 get_email_set (TYPE_CRT, crt);
420 if (!ca_status || server)
422 int pk;
425 pk = gnutls_x509_crt_get_pk_algorithm (crt, NULL);
427 if (pk == GNUTLS_PK_RSA)
428 { /* DSA and ECDSA keys can only sign. */
429 result = get_sign_status (server);
430 if (result)
431 usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
433 result = get_encrypt_status (server);
434 if (result)
435 usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
437 else
438 usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
440 if (is_ike)
442 result =
443 gnutls_x509_crt_set_key_purpose_oid (crt,
444 GNUTLS_KP_IPSEC_IKE, 0);
445 if (result < 0)
446 error (EXIT_FAILURE, 0, "key_kp: %s",
447 gnutls_strerror (result));
452 if (ca_status)
454 result = get_cert_sign_status ();
455 if (result)
456 usage |= GNUTLS_KEY_KEY_CERT_SIGN;
458 result = get_crl_sign_status ();
459 if (result)
460 usage |= GNUTLS_KEY_CRL_SIGN;
462 result = get_code_sign_status ();
463 if (result)
465 result =
466 gnutls_x509_crt_set_key_purpose_oid (crt,
467 GNUTLS_KP_CODE_SIGNING,
469 if (result < 0)
470 error (EXIT_FAILURE, 0, "key_kp: %s",
471 gnutls_strerror (result));
474 result = get_ocsp_sign_status ();
475 if (result)
477 result =
478 gnutls_x509_crt_set_key_purpose_oid (crt,
479 GNUTLS_KP_OCSP_SIGNING,
481 if (result < 0)
482 error (EXIT_FAILURE, 0, "key_kp: %s",
483 gnutls_strerror (result));
486 result = get_time_stamp_status ();
487 if (result)
489 result =
490 gnutls_x509_crt_set_key_purpose_oid (crt,
491 GNUTLS_KP_TIME_STAMPING,
493 if (result < 0)
494 error (EXIT_FAILURE, 0, "key_kp: %s",
495 gnutls_strerror (result));
498 get_ocsp_issuer_set(crt);
499 get_ca_issuers_set(crt);
501 if (usage != 0)
503 /* http://tools.ietf.org/html/rfc4945#section-5.1.3.2: if any KU is
504 set, then either digitalSignature or the nonRepudiation bits in the
505 KeyUsage extension MUST for all IKE certs */
506 if (is_ike && (get_sign_status (server) != 1))
507 usage |= GNUTLS_KEY_NON_REPUDIATION;
508 result = gnutls_x509_crt_set_key_usage (crt, usage);
509 if (result < 0)
510 error (EXIT_FAILURE, 0, "key_usage: %s",
511 gnutls_strerror (result));
514 /* Subject Key ID.
516 size = buffer_size;
517 result = gnutls_x509_crt_get_key_id (crt, 0, buffer, &size);
518 if (result >= 0)
520 result = gnutls_x509_crt_set_subject_key_id (crt, buffer, size);
521 if (result < 0)
522 error (EXIT_FAILURE, 0, "set_subject_key_id: %s",
523 gnutls_strerror (result));
526 /* Authority Key ID.
528 if (ca_crt != NULL)
530 size = buffer_size;
531 result = gnutls_x509_crt_get_subject_key_id (ca_crt, buffer,
532 &size, NULL);
533 if (result < 0)
535 size = buffer_size;
536 result = gnutls_x509_crt_get_key_id (ca_crt, 0, buffer, &size);
538 if (result >= 0)
540 result =
541 gnutls_x509_crt_set_authority_key_id (crt, buffer, size);
542 if (result < 0)
543 error (EXIT_FAILURE, 0, "set_authority_key_id: %s",
544 gnutls_strerror (result));
549 /* Version.
551 if (cinfo->v1_cert != 0)
552 vers = 1;
553 else
554 vers = 3;
555 result = gnutls_x509_crt_set_version (crt, vers);
556 if (result < 0)
557 error (EXIT_FAILURE, 0, "set_version: %s", gnutls_strerror (result));
559 *ret_key = key;
560 return crt;
564 static gnutls_x509_crl_t
565 generate_crl (gnutls_x509_crt_t ca_crt, common_info_st * cinfo)
567 gnutls_x509_crl_t crl;
568 gnutls_x509_crt_t *crts;
569 size_t size;
570 int days, result;
571 unsigned int i;
572 time_t now = time (NULL);
574 result = gnutls_x509_crl_init (&crl);
575 if (result < 0)
576 error (EXIT_FAILURE, 0, "crl_init: %s", gnutls_strerror (result));
578 crts = load_cert_list (0, &size, cinfo);
580 for (i = 0; i < size; i++)
582 result = gnutls_x509_crl_set_crt (crl, crts[i], now);
583 if (result < 0)
584 error (EXIT_FAILURE, 0, "crl_set_crt: %s", gnutls_strerror (result));
587 result = gnutls_x509_crl_set_this_update (crl, now);
588 if (result < 0)
589 error (EXIT_FAILURE, 0, "this_update: %s", gnutls_strerror (result));
591 fprintf (stderr, "Update times.\n");
592 days = get_crl_next_update ();
594 result = gnutls_x509_crl_set_next_update (crl, now + days * 24 * 60 * 60);
595 if (result < 0)
596 error (EXIT_FAILURE, 0, "next_update: %s", gnutls_strerror (result));
598 result = gnutls_x509_crl_set_version (crl, 2);
599 if (result < 0)
600 error (EXIT_FAILURE, 0, "set_version: %s", gnutls_strerror (result));
602 /* Authority Key ID.
604 if (ca_crt != NULL)
606 size = buffer_size;
607 result = gnutls_x509_crt_get_subject_key_id (ca_crt, buffer,
608 &size, NULL);
609 if (result < 0)
611 size = buffer_size;
612 result = gnutls_x509_crt_get_key_id (ca_crt, 0, buffer, &size);
614 if (result >= 0)
616 result = gnutls_x509_crl_set_authority_key_id (crl, buffer, size);
617 if (result < 0)
618 error (EXIT_FAILURE, 0, "set_authority_key_id: %s",
619 gnutls_strerror (result));
624 unsigned int number = get_crl_number ();
625 char bin_number[5];
627 bin_number[4] = number & 0xff;
628 bin_number[3] = (number >> 8) & 0xff;
629 bin_number[2] = (number >> 16) & 0xff;
630 bin_number[1] = (number >> 24) & 0xff;
631 bin_number[0] = 0;
633 result = gnutls_x509_crl_set_number (crl, bin_number, 5);
634 if (result < 0)
635 error (EXIT_FAILURE, 0, "set_number: %s", gnutls_strerror (result));
638 return crl;
641 static gnutls_digest_algorithm_t
642 get_dig_for_pub (gnutls_pubkey_t pubkey)
644 gnutls_digest_algorithm_t dig;
645 int result;
646 unsigned int mand;
648 result = gnutls_pubkey_get_preferred_hash_algorithm (pubkey, &dig, &mand);
649 if (result < 0)
651 error (EXIT_FAILURE, 0, "crt_get_preferred_hash_algorithm: %s",
652 gnutls_strerror (result));
655 /* if algorithm allows alternatives */
656 if (mand == 0 && default_dig != GNUTLS_DIG_UNKNOWN)
657 dig = default_dig;
659 return dig;
662 static gnutls_digest_algorithm_t
663 get_dig (gnutls_x509_crt_t crt)
665 gnutls_digest_algorithm_t dig;
666 gnutls_pubkey_t pubkey;
667 int result;
669 gnutls_pubkey_init(&pubkey);
671 result = gnutls_pubkey_import_x509(pubkey, crt, 0);
672 if (result < 0)
674 error (EXIT_FAILURE, 0, "gnutls_pubkey_import_x509: %s",
675 gnutls_strerror (result));
678 dig = get_dig_for_pub (pubkey);
680 gnutls_pubkey_deinit(pubkey);
682 return dig;
685 void
686 generate_self_signed (common_info_st * cinfo)
688 gnutls_x509_crt_t crt;
689 gnutls_privkey_t key;
690 size_t size;
691 int result;
692 const char *uri;
694 fprintf (stderr, "Generating a self signed certificate...\n");
696 crt = generate_certificate (&key, NULL, 0, cinfo);
698 if (!key)
699 key = load_private_key (1, cinfo);
701 uri = get_crl_dist_point_url ();
702 if (uri)
704 result = gnutls_x509_crt_set_crl_dist_points (crt, GNUTLS_SAN_URI,
705 uri,
706 0 /* all reasons */ );
707 if (result < 0)
708 error (EXIT_FAILURE, 0, "crl_dist_points: %s",
709 gnutls_strerror (result));
712 print_certificate_info (crt, stderr, 0);
714 fprintf (stderr, "\n\nSigning certificate...\n");
716 result = gnutls_x509_crt_privkey_sign (crt, crt, key, get_dig (crt), 0);
717 if (result < 0)
718 error (EXIT_FAILURE, 0, "crt_sign: %s", gnutls_strerror (result));
720 size = buffer_size;
721 result = gnutls_x509_crt_export (crt, outcert_format, buffer, &size);
722 if (result < 0)
723 error (EXIT_FAILURE, 0, "crt_export: %s", gnutls_strerror (result));
725 fwrite (buffer, 1, size, outfile);
727 gnutls_x509_crt_deinit (crt);
728 gnutls_privkey_deinit (key);
731 static void
732 generate_signed_certificate (common_info_st * cinfo)
734 gnutls_x509_crt_t crt;
735 gnutls_privkey_t key;
736 size_t size;
737 int result;
738 gnutls_privkey_t ca_key;
739 gnutls_x509_crt_t ca_crt;
741 fprintf (stderr, "Generating a signed certificate...\n");
743 ca_key = load_ca_private_key (cinfo);
744 ca_crt = load_ca_cert (cinfo);
746 crt = generate_certificate (&key, ca_crt, 0, cinfo);
748 /* Copy the CRL distribution points.
750 gnutls_x509_crt_cpy_crl_dist_points (crt, ca_crt);
751 /* it doesn't matter if we couldn't copy the CRL dist points.
754 print_certificate_info (crt, stderr, 0);
756 fprintf (stderr, "\n\nSigning certificate...\n");
758 result = gnutls_x509_crt_privkey_sign (crt, ca_crt, ca_key, get_dig (ca_crt), 0);
759 if (result < 0)
760 error (EXIT_FAILURE, 0, "crt_sign: %s", gnutls_strerror (result));
762 size = buffer_size;
763 result = gnutls_x509_crt_export (crt, outcert_format, buffer, &size);
764 if (result < 0)
765 error (EXIT_FAILURE, 0, "crt_export: %s", gnutls_strerror (result));
767 fwrite (buffer, 1, size, outfile);
769 gnutls_x509_crt_deinit (crt);
770 gnutls_privkey_deinit (key);
771 gnutls_privkey_deinit(ca_key);
774 static void
775 generate_proxy_certificate (common_info_st * cinfo)
777 gnutls_x509_crt_t crt, eecrt;
778 gnutls_privkey_t key, eekey;
779 size_t size;
780 int result;
782 fprintf (stderr, "Generating a proxy certificate...\n");
784 eekey = load_ca_private_key (cinfo);
785 eecrt = load_cert (1, cinfo);
787 crt = generate_certificate (&key, eecrt, 1, cinfo);
789 print_certificate_info (crt, stderr, 0);
791 fprintf (stderr, "\n\nSigning certificate...\n");
793 result = gnutls_x509_crt_privkey_sign (crt, eecrt, eekey, get_dig (eecrt), 0);
794 if (result < 0)
795 error (EXIT_FAILURE, 0, "crt_sign: %s", gnutls_strerror (result));
797 size = buffer_size;
798 result = gnutls_x509_crt_export (crt, outcert_format, buffer, &size);
799 if (result < 0)
800 error (EXIT_FAILURE, 0, "crt_export: %s", gnutls_strerror (result));
802 fwrite (buffer, 1, size, outfile);
804 gnutls_x509_crt_deinit (eecrt);
805 gnutls_x509_crt_deinit (crt);
806 gnutls_privkey_deinit (key);
807 gnutls_privkey_deinit (eekey);
810 static void
811 generate_signed_crl (common_info_st * cinfo)
813 gnutls_x509_crl_t crl;
814 int result;
815 gnutls_privkey_t ca_key;
816 gnutls_x509_crt_t ca_crt;
818 fprintf (stderr, "Generating a signed CRL...\n");
820 ca_key = load_ca_private_key (cinfo);
821 ca_crt = load_ca_cert (cinfo);
822 crl = generate_crl (ca_crt, cinfo);
824 fprintf (stderr, "\n");
825 result = gnutls_x509_crl_privkey_sign(crl, ca_crt, ca_key, get_dig (ca_crt), 0);
826 if (result < 0)
827 error (EXIT_FAILURE, 0, "crl_privkey_sign: %s", gnutls_strerror (result));
829 print_crl_info (crl, stderr);
831 gnutls_privkey_deinit( ca_key);
832 gnutls_x509_crl_deinit (crl);
835 static void
836 update_signed_certificate (common_info_st * cinfo)
838 gnutls_x509_crt_t crt;
839 size_t size;
840 int result;
841 gnutls_privkey_t ca_key;
842 gnutls_x509_crt_t ca_crt;
843 int days;
844 time_t tim = time (NULL);
846 fprintf (stderr, "Generating a signed certificate...\n");
848 ca_key = load_ca_private_key (cinfo);
849 ca_crt = load_ca_cert (cinfo);
850 crt = load_cert (1, cinfo);
852 fprintf (stderr, "Activation/Expiration time.\n");
853 gnutls_x509_crt_set_activation_time (crt, tim);
855 days = get_days ();
857 result =
858 gnutls_x509_crt_set_expiration_time (crt, tim + ((time_t) days) * 24 * 60 * 60);
859 if (result < 0)
860 error (EXIT_FAILURE, 0, "set_expiration: %s", gnutls_strerror (result));
862 fprintf (stderr, "\n\nSigning certificate...\n");
864 result = gnutls_x509_crt_privkey_sign (crt, ca_crt, ca_key, get_dig (ca_crt), 0);
865 if (result < 0)
866 error (EXIT_FAILURE, 0, "crt_sign: %s", gnutls_strerror (result));
868 size = buffer_size;
869 result = gnutls_x509_crt_export (crt, outcert_format, buffer, &size);
870 if (result < 0)
871 error (EXIT_FAILURE, 0, "crt_export: %s", gnutls_strerror (result));
873 fwrite (buffer, 1, size, outfile);
875 gnutls_x509_crt_deinit (crt);
878 static void
879 cmd_parser (int argc, char **argv)
881 int ret, privkey_op = 0;
882 common_info_st cinfo;
884 optionProcess( &certtoolOptions, argc, argv);
886 if (HAVE_OPT(GENERATE_PRIVKEY) || HAVE_OPT(GENERATE_REQUEST) ||
887 HAVE_OPT(KEY_INFO) || HAVE_OPT(PGP_KEY_INFO))
888 privkey_op = 1;
890 if (HAVE_OPT(HEX_NUMBERS))
891 full_format = GNUTLS_CRT_PRINT_FULL_NUMBERS;
893 if (HAVE_OPT(OUTFILE))
895 outfile = safe_open_rw (OPT_ARG(OUTFILE), privkey_op);
896 if (outfile == NULL)
897 error (EXIT_FAILURE, errno, "%s", OPT_ARG(OUTFILE));
899 else
900 outfile = stdout;
902 if (HAVE_OPT(INFILE))
904 infile = fopen (OPT_ARG(INFILE), "rb");
905 if (infile == NULL)
906 error (EXIT_FAILURE, errno, "%s", OPT_ARG(INFILE));
908 else
909 infile = stdin;
911 if (HAVE_OPT(INDER) || HAVE_OPT(INRAW))
912 incert_format = GNUTLS_X509_FMT_DER;
913 else
914 incert_format = GNUTLS_X509_FMT_PEM;
916 if (HAVE_OPT(OUTDER) || HAVE_OPT(OUTRAW))
917 outcert_format = GNUTLS_X509_FMT_DER;
918 else
919 outcert_format = GNUTLS_X509_FMT_PEM;
921 if (HAVE_OPT(DSA))
922 req_key_type = GNUTLS_PK_DSA;
923 else if (HAVE_OPT(ECC))
924 req_key_type = GNUTLS_PK_ECC;
925 else
926 req_key_type = GNUTLS_PK_RSA;
928 default_dig = GNUTLS_DIG_UNKNOWN;
929 if (HAVE_OPT(HASH))
931 if (strcasecmp (OPT_ARG(HASH), "md5") == 0)
933 fprintf (stderr,
934 "Warning: MD5 is broken, and should not be used any more for digital signatures.\n");
935 default_dig = GNUTLS_DIG_MD5;
937 else if (strcasecmp (OPT_ARG(HASH), "sha1") == 0)
938 default_dig = GNUTLS_DIG_SHA1;
939 else if (strcasecmp (OPT_ARG(HASH), "sha256") == 0)
940 default_dig = GNUTLS_DIG_SHA256;
941 else if (strcasecmp (OPT_ARG(HASH), "sha224") == 0)
942 default_dig = GNUTLS_DIG_SHA224;
943 else if (strcasecmp (OPT_ARG(HASH), "sha384") == 0)
944 default_dig = GNUTLS_DIG_SHA384;
945 else if (strcasecmp (OPT_ARG(HASH), "sha512") == 0)
946 default_dig = GNUTLS_DIG_SHA512;
947 else if (strcasecmp (OPT_ARG(HASH), "rmd160") == 0)
948 default_dig = GNUTLS_DIG_RMD160;
949 else
950 error (EXIT_FAILURE, 0, "invalid hash: %s", OPT_ARG(HASH));
953 batch = 0;
954 if (HAVE_OPT(TEMPLATE))
956 batch = 1;
957 template_parse (OPT_ARG(TEMPLATE));
960 gnutls_global_set_log_function (tls_log_func);
962 if (HAVE_OPT(DEBUG))
964 gnutls_global_set_log_level (OPT_VALUE_DEBUG);
965 printf ("Setting log level to %d\n", (int)OPT_VALUE_DEBUG);
968 if ((ret = gnutls_global_init ()) < 0)
969 error (EXIT_FAILURE, 0, "global_init: %s", gnutls_strerror (ret));
971 #ifdef ENABLE_PKCS11
972 pkcs11_common();
973 #endif
975 memset (&cinfo, 0, sizeof (cinfo));
977 if (HAVE_OPT(VERBOSE))
978 cinfo.verbose = 1;
980 if (HAVE_OPT(LOAD_PRIVKEY))
981 cinfo.privkey = OPT_ARG(LOAD_PRIVKEY);
983 cinfo.v1_cert = HAVE_OPT(V1);
984 if (HAVE_OPT(NO_CRQ_EXTENSIONS))
985 cinfo.crq_extensions = 0;
986 else cinfo.crq_extensions = 1;
988 if (HAVE_OPT(LOAD_PUBKEY))
989 cinfo.pubkey = OPT_ARG(LOAD_PUBKEY);
991 cinfo.pkcs8 = HAVE_OPT(PKCS8);
992 cinfo.incert_format = incert_format;
994 if (HAVE_OPT(LOAD_CERTIFICATE))
995 cinfo.cert = OPT_ARG(LOAD_CERTIFICATE);
997 if (HAVE_OPT(LOAD_REQUEST))
998 cinfo.request = OPT_ARG(LOAD_REQUEST);
1000 if (HAVE_OPT(LOAD_CA_CERTIFICATE))
1001 cinfo.ca = OPT_ARG(LOAD_CA_CERTIFICATE);
1003 if (HAVE_OPT(LOAD_CA_PRIVKEY))
1004 cinfo.ca_privkey = OPT_ARG(LOAD_CA_PRIVKEY);
1006 if (HAVE_OPT(BITS))
1007 cinfo.bits = OPT_VALUE_BITS;
1009 if (HAVE_OPT(SEC_PARAM))
1010 cinfo.sec_param = OPT_ARG(SEC_PARAM);
1012 if (HAVE_OPT(PKCS_CIPHER))
1013 cinfo.pkcs_cipher = OPT_ARG(PKCS_CIPHER);
1015 if (HAVE_OPT(PASSWORD))
1017 cinfo.password = OPT_ARG(PASSWORD);
1018 if (HAVE_OPT(GENERATE_PRIVKEY) && cinfo.pkcs8 == 0)
1020 fprintf(stderr, "Assuming PKCS #8 format...\n");
1021 cinfo.pkcs8 = 1;
1025 if (HAVE_OPT(NULL_PASSWORD))
1027 cinfo.null_password = 1;
1028 cinfo.password = "";
1031 if (HAVE_OPT(GENERATE_SELF_SIGNED))
1032 generate_self_signed (&cinfo);
1033 else if (HAVE_OPT(GENERATE_CERTIFICATE))
1034 generate_signed_certificate (&cinfo);
1035 else if (HAVE_OPT(GENERATE_PROXY))
1036 generate_proxy_certificate (&cinfo);
1037 else if (HAVE_OPT(GENERATE_CRL))
1038 generate_signed_crl (&cinfo);
1039 else if (HAVE_OPT(UPDATE_CERTIFICATE))
1040 update_signed_certificate (&cinfo);
1041 else if (HAVE_OPT(GENERATE_PRIVKEY))
1042 generate_private_key (&cinfo);
1043 else if (HAVE_OPT(GENERATE_REQUEST))
1044 generate_request (&cinfo);
1045 else if (HAVE_OPT(VERIFY_CHAIN))
1046 verify_chain ();
1047 else if (HAVE_OPT(VERIFY))
1048 verify_certificate (&cinfo);
1049 else if (HAVE_OPT(VERIFY_CRL))
1050 verify_crl (&cinfo);
1051 else if (HAVE_OPT(CERTIFICATE_INFO))
1052 certificate_info (0, &cinfo);
1053 else if (HAVE_OPT(DH_INFO))
1054 dh_info (&cinfo);
1055 else if (HAVE_OPT(CERTIFICATE_PUBKEY))
1056 certificate_info (1, &cinfo);
1057 else if (HAVE_OPT(KEY_INFO))
1058 privkey_info (&cinfo);
1059 else if (HAVE_OPT(PUBKEY_INFO))
1060 pubkey_info (NULL, &cinfo);
1061 else if (HAVE_OPT(TO_P12))
1062 generate_pkcs12 (&cinfo);
1063 else if (HAVE_OPT(P12_INFO))
1064 pkcs12_info (&cinfo);
1065 else if (HAVE_OPT(GENERATE_DH_PARAMS))
1066 generate_prime (1, &cinfo);
1067 else if (HAVE_OPT(GET_DH_PARAMS))
1068 generate_prime (0, &cinfo);
1069 else if (HAVE_OPT(CRL_INFO))
1070 crl_info ();
1071 else if (HAVE_OPT(P7_INFO))
1072 pkcs7_info ();
1073 else if (HAVE_OPT(SMIME_TO_P7))
1074 smime_to_pkcs7 ();
1075 else if (HAVE_OPT(TO_P8))
1076 generate_pkcs8 (&cinfo);
1077 #ifdef ENABLE_OPENPGP
1078 else if (HAVE_OPT(PGP_CERTIFICATE_INFO))
1079 pgp_certificate_info ();
1080 else if (HAVE_OPT(PGP_KEY_INFO))
1081 pgp_privkey_info ();
1082 else if (HAVE_OPT(PGP_RING_INFO))
1083 pgp_ring_info ();
1084 #endif
1085 else if (HAVE_OPT(CRQ_INFO))
1086 crq_info ();
1087 else
1088 USAGE(1);
1090 fclose (outfile);
1092 #ifdef ENABLE_PKCS11
1093 gnutls_pkcs11_deinit ();
1094 #endif
1095 gnutls_global_deinit ();
1098 #define MAX_CRTS 500
1099 void
1100 certificate_info (int pubkey, common_info_st * cinfo)
1102 gnutls_x509_crt_t crt[MAX_CRTS];
1103 size_t size;
1104 int ret, i, count;
1105 gnutls_datum_t pem;
1106 unsigned int crt_num;
1108 pem.data = (void*)fread_file (infile, &size);
1109 pem.size = size;
1111 crt_num = MAX_CRTS;
1112 ret =
1113 gnutls_x509_crt_list_import (crt, &crt_num, &pem, incert_format,
1114 GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);
1115 if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
1117 error (0, 0, "too many certificates (%d); "
1118 "will only read the first %d", crt_num, MAX_CRTS);
1119 crt_num = MAX_CRTS;
1120 ret = gnutls_x509_crt_list_import (crt, &crt_num, &pem,
1121 incert_format, 0);
1123 if (ret < 0)
1124 error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));
1126 free (pem.data);
1128 count = ret;
1130 if (count > 1 && outcert_format == GNUTLS_X509_FMT_DER)
1132 error (0, 0, "cannot output multiple certificates in DER format; "
1133 "using PEM instead");
1134 outcert_format = GNUTLS_X509_FMT_PEM;
1137 for (i = 0; i < count; i++)
1139 if (i > 0)
1140 fprintf (outfile, "\n");
1142 if (outcert_format == GNUTLS_X509_FMT_PEM)
1143 print_certificate_info (crt[i], outfile, 1);
1145 if (pubkey)
1146 pubkey_info (crt[i], cinfo);
1147 else
1149 size = buffer_size;
1150 ret = gnutls_x509_crt_export (crt[i], outcert_format, buffer,
1151 &size);
1152 if (ret < 0)
1153 error (EXIT_FAILURE, 0, "export error: %s", gnutls_strerror (ret));
1155 fwrite (buffer, 1, size, outfile);
1158 gnutls_x509_crt_deinit (crt[i]);
1162 #ifdef ENABLE_OPENPGP
1164 void
1165 pgp_certificate_info (void)
1167 gnutls_openpgp_crt_t crt;
1168 size_t size;
1169 int ret;
1170 gnutls_datum_t pem, out_data;
1171 unsigned int verify_status;
1173 pem.data = (void*)fread_file (infile, &size);
1174 pem.size = size;
1176 ret = gnutls_openpgp_crt_init (&crt);
1177 if (ret < 0)
1178 error (EXIT_FAILURE, 0, "openpgp_crt_init: %s", gnutls_strerror (ret));
1180 ret = gnutls_openpgp_crt_import (crt, &pem, incert_format);
1182 if (ret < 0)
1183 error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));
1185 free (pem.data);
1187 if (outcert_format == GNUTLS_OPENPGP_FMT_BASE64)
1189 ret = gnutls_openpgp_crt_print (crt, 0, &out_data);
1191 if (ret == 0)
1193 fprintf (outfile, "%s\n", out_data.data);
1194 gnutls_free (out_data.data);
1199 ret = gnutls_openpgp_crt_verify_self (crt, 0, &verify_status);
1200 if (ret < 0)
1202 error (EXIT_FAILURE, 0, "verify signature error: %s",
1203 gnutls_strerror (ret));
1206 if (verify_status & GNUTLS_CERT_INVALID)
1208 fprintf (outfile, "Self Signature verification: failed\n\n");
1210 else
1212 fprintf (outfile, "Self Signature verification: ok (%x)\n\n",
1213 verify_status);
1216 size = buffer_size;
1217 ret = gnutls_openpgp_crt_export (crt, outcert_format, buffer, &size);
1218 if (ret < 0)
1220 error (EXIT_FAILURE, 0, "export error: %s", gnutls_strerror (ret));
1221 fwrite (buffer, 1, size, outfile);
1224 fprintf (outfile, "%s\n", buffer);
1225 gnutls_openpgp_crt_deinit (crt);
1228 void
1229 pgp_privkey_info (void)
1231 gnutls_openpgp_privkey_t key;
1232 unsigned char keyid[GNUTLS_OPENPGP_KEYID_SIZE];
1233 size_t size;
1234 int ret, i, subkeys, bits = 0;
1235 gnutls_datum_t pem;
1236 const char *cprint;
1238 size = fread (buffer, 1, buffer_size - 1, infile);
1239 buffer[size] = 0;
1241 gnutls_openpgp_privkey_init (&key);
1243 pem.data = buffer;
1244 pem.size = size;
1246 ret = gnutls_openpgp_privkey_import (key, &pem, incert_format,
1247 NULL, 0);
1249 if (ret < 0)
1250 error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));
1252 /* Public key algorithm
1254 subkeys = gnutls_openpgp_privkey_get_subkey_count (key);
1255 if (subkeys < 0)
1256 error (EXIT_FAILURE, 0, "privkey_get_subkey_count: %s",
1257 gnutls_strerror (subkeys));
1259 for (i = -1; i < subkeys; i++)
1262 if (i != -1)
1263 fprintf (outfile, "Subkey[%d]:\n", i);
1265 fprintf (outfile, "Public Key Info:\n");
1267 if (i == -1)
1268 ret = gnutls_openpgp_privkey_get_pk_algorithm (key, NULL);
1269 else
1270 ret = gnutls_openpgp_privkey_get_subkey_pk_algorithm (key, i, NULL);
1272 fprintf (outfile, "\tPublic Key Algorithm: ");
1273 cprint = gnutls_pk_algorithm_get_name (ret);
1274 fprintf (outfile, "%s\n", cprint ? cprint : "Unknown");
1275 fprintf (outfile, "\tKey Security Level: %s\n",
1276 gnutls_sec_param_get_name (gnutls_openpgp_privkey_sec_param
1277 (key)));
1279 /* Print the raw public and private keys
1282 if (ret == GNUTLS_PK_RSA)
1284 gnutls_datum_t m, e, d, p, q, u;
1286 if (i == -1)
1287 ret =
1288 gnutls_openpgp_privkey_export_rsa_raw (key, &m, &e, &d, &p,
1289 &q, &u);
1290 else
1291 ret =
1292 gnutls_openpgp_privkey_export_subkey_rsa_raw (key, i, &m,
1293 &e, &d, &p,
1294 &q, &u);
1295 if (ret < 0)
1296 fprintf (stderr, "Error in key RSA data export: %s\n",
1297 gnutls_strerror (ret));
1298 else
1299 print_rsa_pkey (outfile, &m, &e, &d, &p, &q, &u, NULL, NULL);
1301 bits = m.size * 8;
1303 else if (ret == GNUTLS_PK_DSA)
1305 gnutls_datum_t p, q, g, y, x;
1307 if (i == -1)
1308 ret =
1309 gnutls_openpgp_privkey_export_dsa_raw (key, &p, &q, &g, &y, &x);
1310 else
1311 ret =
1312 gnutls_openpgp_privkey_export_subkey_dsa_raw (key, i, &p,
1313 &q, &g, &y, &x);
1314 if (ret < 0)
1315 fprintf (stderr, "Error in key DSA data export: %s\n",
1316 gnutls_strerror (ret));
1317 else
1318 print_dsa_pkey (outfile, &x, &y, &p, &q, &g);
1320 bits = y.size * 8;
1323 fprintf (outfile, "\n");
1325 size = buffer_size;
1326 if (i == -1)
1327 ret = gnutls_openpgp_privkey_get_key_id (key, keyid);
1328 else
1329 ret = gnutls_openpgp_privkey_get_subkey_id (key, i, keyid);
1331 if (ret < 0)
1333 fprintf (stderr, "Error in key id calculation: %s\n",
1334 gnutls_strerror (ret));
1336 else
1338 fprintf (outfile, "Public key ID: %s\n", raw_to_string (keyid, 8));
1341 size = buffer_size;
1342 if (i == -1)
1343 ret = gnutls_openpgp_privkey_get_fingerprint (key, buffer, &size);
1344 else
1345 ret = gnutls_openpgp_privkey_get_subkey_fingerprint (key, i, buffer, &size);
1347 if (ret < 0)
1349 fprintf (stderr, "Error in fingerprint calculation: %s\n",
1350 gnutls_strerror (ret));
1352 else
1354 gnutls_datum_t art;
1356 fprintf (outfile, "Fingerprint: %s\n", raw_to_string (buffer, size));
1358 ret = gnutls_random_art(GNUTLS_RANDOM_ART_OPENSSH, cprint, bits, buffer, size, &art);
1359 if (ret >= 0)
1361 fprintf (outfile, "Fingerprint's random art:\n%s\n\n", art.data);
1362 gnutls_free(art.data);
1367 size = buffer_size;
1368 ret = gnutls_openpgp_privkey_export (key, GNUTLS_OPENPGP_FMT_BASE64,
1369 NULL, 0, buffer, &size);
1370 if (ret < 0)
1371 error (EXIT_FAILURE, 0, "export error: %s", gnutls_strerror (ret));
1373 fprintf (outfile, "\n%s\n", buffer);
1375 gnutls_openpgp_privkey_deinit (key);
1378 void
1379 pgp_ring_info (void)
1381 gnutls_openpgp_keyring_t ring;
1382 gnutls_openpgp_crt_t crt;
1383 size_t size;
1384 int ret, i, count;
1385 gnutls_datum_t pem;
1387 pem.data = (void*)fread_file (infile, &size);
1388 pem.size = size;
1390 ret = gnutls_openpgp_keyring_init (&ring);
1391 if (ret < 0)
1392 error (EXIT_FAILURE, 0, "openpgp_keyring_init: %s",
1393 gnutls_strerror (ret));
1395 ret = gnutls_openpgp_keyring_import (ring, &pem, incert_format);
1397 if (ret < 0)
1398 error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));
1400 free (pem.data);
1402 count = gnutls_openpgp_keyring_get_crt_count (ring);
1403 if (count >= 0)
1404 fprintf (outfile, "Keyring contains %d OpenPGP certificates\n\n", count);
1405 else
1406 error (EXIT_FAILURE, 0, "keyring error: %s", gnutls_strerror (count));
1408 for (i = 0; i < count; i++)
1410 ret = gnutls_openpgp_keyring_get_crt (ring, i, &crt);
1411 if (ret < 0)
1412 error (EXIT_FAILURE, 0, "export error: %s", gnutls_strerror (ret));
1414 size = buffer_size;
1415 ret = gnutls_openpgp_crt_export (crt, outcert_format,
1416 buffer, &size);
1417 if (ret < 0)
1418 error (EXIT_FAILURE, 0, "export error: %s", gnutls_strerror (ret));
1420 fwrite (buffer, 1, size, outfile);
1421 fprintf (outfile, "\n\n");
1423 gnutls_openpgp_crt_deinit (crt);
1428 gnutls_openpgp_keyring_deinit (ring);
1432 #endif
1436 static void
1437 print_certificate_info (gnutls_x509_crt_t crt, FILE * out, unsigned int all)
1439 gnutls_datum_t data;
1440 int ret;
1442 if (all)
1443 ret = gnutls_x509_crt_print (crt, full_format, &data);
1444 else
1445 ret = gnutls_x509_crt_print (crt, GNUTLS_CRT_PRINT_UNSIGNED_FULL, &data);
1446 if (ret == 0)
1448 fprintf (out, "%s\n", data.data);
1449 gnutls_free (data.data);
1452 if (out == stderr && batch == 0) /* interactive */
1453 if (read_yesno ("Is the above information ok? (y/N): ") == 0)
1455 exit (1);
1459 static void
1460 print_crl_info (gnutls_x509_crl_t crl, FILE * out)
1462 gnutls_datum_t data;
1463 int ret;
1464 size_t size;
1466 ret = gnutls_x509_crl_print (crl, full_format, &data);
1467 if (ret < 0)
1468 error (EXIT_FAILURE, 0, "crl_print: %s", gnutls_strerror (ret));
1470 fprintf (out, "%s\n", data.data);
1472 gnutls_free (data.data);
1474 size = buffer_size;
1475 ret = gnutls_x509_crl_export (crl, GNUTLS_X509_FMT_PEM, buffer, &size);
1476 if (ret < 0)
1477 error (EXIT_FAILURE, 0, "crl_export: %s", gnutls_strerror (ret));
1479 fwrite (buffer, 1, size, outfile);
1482 void
1483 crl_info (void)
1485 gnutls_x509_crl_t crl;
1486 int ret;
1487 size_t size;
1488 gnutls_datum_t pem;
1490 ret = gnutls_x509_crl_init (&crl);
1491 if (ret < 0)
1492 error (EXIT_FAILURE, 0, "crl_init: %s", gnutls_strerror (ret));
1494 pem.data = (void*)fread_file (infile, &size);
1495 pem.size = size;
1497 if (!pem.data)
1498 error (EXIT_FAILURE, errno, "%s", infile ? "file" :
1499 "standard input");
1501 ret = gnutls_x509_crl_import (crl, &pem, incert_format);
1503 free (pem.data);
1504 if (ret < 0)
1505 error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));
1507 print_crl_info (crl, outfile);
1509 gnutls_x509_crl_deinit (crl);
1512 static void
1513 print_crq_info (gnutls_x509_crq_t crq, FILE * out)
1515 gnutls_datum_t data;
1516 int ret;
1517 size_t size;
1519 if (outcert_format == GNUTLS_X509_FMT_PEM)
1521 ret = gnutls_x509_crq_print (crq, full_format, &data);
1522 if (ret < 0)
1523 error (EXIT_FAILURE, 0, "crq_print: %s", gnutls_strerror (ret));
1525 fprintf (out, "%s\n", data.data);
1527 gnutls_free (data.data);
1530 ret = gnutls_x509_crq_verify(crq, 0);
1531 if (ret < 0)
1533 fprintf(out, "Self signature: FAILED\n\n");
1535 else
1537 fprintf(out, "Self signature: verified\n\n");
1540 size = buffer_size;
1541 ret = gnutls_x509_crq_export (crq, outcert_format, buffer, &size);
1542 if (ret < 0)
1543 error (EXIT_FAILURE, 0, "crq_export: %s", gnutls_strerror (ret));
1545 fwrite (buffer, 1, size, outfile);
1548 void
1549 crq_info (void)
1551 gnutls_x509_crq_t crq;
1552 int ret;
1553 size_t size;
1554 gnutls_datum_t pem;
1556 ret = gnutls_x509_crq_init (&crq);
1557 if (ret < 0)
1558 error (EXIT_FAILURE, 0, "crq_init: %s", gnutls_strerror (ret));
1560 pem.data = (void*)fread_file (infile, &size);
1561 pem.size = size;
1563 if (!pem.data)
1564 error (EXIT_FAILURE, errno, "%s", infile ? "file" :
1565 "standard input");
1567 ret = gnutls_x509_crq_import (crq, &pem, incert_format);
1569 free (pem.data);
1570 if (ret < 0)
1571 error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));
1573 print_crq_info (crq, outfile);
1575 gnutls_x509_crq_deinit (crq);
1578 static void privkey_info_int (common_info_st* cinfo, gnutls_x509_privkey_t key)
1580 int ret, key_type;
1581 unsigned int bits = 0;
1582 size_t size;
1583 const char *cprint;
1585 /* Public key algorithm
1587 fprintf (outfile, "Public Key Info:\n");
1588 ret = gnutls_x509_privkey_get_pk_algorithm2 (key, &bits);
1589 fprintf (outfile, "\tPublic Key Algorithm: ");
1591 key_type = ret;
1593 cprint = gnutls_pk_algorithm_get_name (key_type);
1594 fprintf (outfile, "%s\n", cprint ? cprint : "Unknown");
1595 fprintf (outfile, "\tKey Security Level: %s (%u bits)\n\n",
1596 gnutls_sec_param_get_name (gnutls_x509_privkey_sec_param (key)), bits);
1598 /* Print the raw public and private keys
1600 if (key_type == GNUTLS_PK_RSA)
1602 gnutls_datum_t m, e, d, p, q, u, exp1, exp2;
1604 ret =
1605 gnutls_x509_privkey_export_rsa_raw2 (key, &m, &e, &d, &p, &q, &u,
1606 &exp1, &exp2);
1607 if (ret < 0)
1608 fprintf (stderr, "Error in key RSA data export: %s\n",
1609 gnutls_strerror (ret));
1610 else
1612 print_rsa_pkey (outfile, &m, &e, &d, &p, &q, &u, &exp1, &exp2);
1614 gnutls_free (m.data);
1615 gnutls_free (e.data);
1616 gnutls_free (d.data);
1617 gnutls_free (p.data);
1618 gnutls_free (q.data);
1619 gnutls_free (u.data);
1620 gnutls_free (exp1.data);
1621 gnutls_free (exp2.data);
1624 else if (key_type == GNUTLS_PK_DSA)
1626 gnutls_datum_t p, q, g, y, x;
1628 ret = gnutls_x509_privkey_export_dsa_raw (key, &p, &q, &g, &y, &x);
1629 if (ret < 0)
1630 fprintf (stderr, "Error in key DSA data export: %s\n",
1631 gnutls_strerror (ret));
1632 else
1634 print_dsa_pkey (outfile, &x, &y, &p, &q, &g);
1636 gnutls_free (x.data);
1637 gnutls_free (y.data);
1638 gnutls_free (p.data);
1639 gnutls_free (q.data);
1640 gnutls_free (g.data);
1643 else if (key_type == GNUTLS_PK_EC)
1645 gnutls_datum_t y, x, k;
1646 gnutls_ecc_curve_t curve;
1648 ret = gnutls_x509_privkey_export_ecc_raw (key, &curve, &x, &y, &k);
1649 if (ret < 0)
1650 fprintf (stderr, "Error in key ECC data export: %s\n",
1651 gnutls_strerror (ret));
1652 else
1654 print_ecc_pkey (outfile, curve, &k, &x, &y);
1656 gnutls_free (x.data);
1657 gnutls_free (y.data);
1658 gnutls_free (k.data);
1662 fprintf (outfile, "\n");
1664 size = buffer_size;
1665 if ((ret = gnutls_x509_privkey_get_key_id (key, 0, buffer, &size)) < 0)
1667 fprintf (stderr, "Error in key id calculation: %s\n",
1668 gnutls_strerror (ret));
1670 else
1672 gnutls_datum_t art;
1674 fprintf (outfile, "Public Key ID: %s\n", raw_to_string (buffer, size));
1676 ret = gnutls_random_art(GNUTLS_RANDOM_ART_OPENSSH, cprint, bits, buffer, size, &art);
1677 if (ret >= 0)
1679 fprintf (outfile, "Public key's random art:\n%s\n", art.data);
1680 gnutls_free(art.data);
1683 fprintf (outfile, "\n");
1687 void
1688 privkey_info (common_info_st* cinfo)
1690 gnutls_x509_privkey_t key;
1691 size_t size;
1692 int ret;
1693 gnutls_datum_t pem;
1694 const char *pass;
1695 unsigned int flags = 0;
1697 size = fread (buffer, 1, buffer_size - 1, infile);
1698 buffer[size] = 0;
1700 gnutls_x509_privkey_init (&key);
1702 pem.data = buffer;
1703 pem.size = size;
1705 ret = gnutls_x509_privkey_import2 (key, &pem, incert_format, NULL, 0);
1707 /* If we failed to import the certificate previously try PKCS #8 */
1708 if (ret == GNUTLS_E_DECRYPTION_FAILED)
1710 fprintf(stderr, "Encrypted structure detected...\n");
1711 pass = get_password(cinfo, &flags, 0);
1713 ret = gnutls_x509_privkey_import2 (key, &pem,
1714 incert_format, pass, flags);
1716 if (ret < 0)
1717 error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));
1719 if (outcert_format == GNUTLS_X509_FMT_PEM)
1720 privkey_info_int (cinfo, key);
1722 ret = gnutls_x509_privkey_verify_params (key);
1723 if (ret < 0)
1724 fprintf (outfile, "\n** Private key parameters validation failed **\n\n");
1726 size = buffer_size;
1727 ret = gnutls_x509_privkey_export (key, outcert_format, buffer, &size);
1728 if (ret < 0)
1729 error (EXIT_FAILURE, 0, "export error: %s", gnutls_strerror (ret));
1731 fwrite (buffer, 1, size, outfile);
1733 gnutls_x509_privkey_deinit (key);
1737 /* Generate a PKCS #10 certificate request.
1739 void
1740 generate_request (common_info_st * cinfo)
1742 gnutls_x509_crq_t crq;
1743 gnutls_x509_privkey_t xkey;
1744 gnutls_pubkey_t pubkey;
1745 gnutls_privkey_t pkey;
1746 int ret, ca_status, path_len, pk;
1747 const char *pass;
1748 unsigned int usage = 0;
1750 fprintf (stderr, "Generating a PKCS #10 certificate request...\n");
1752 ret = gnutls_x509_crq_init (&crq);
1753 if (ret < 0)
1754 error (EXIT_FAILURE, 0, "crq_init: %s", gnutls_strerror (ret));
1757 /* Load the private key.
1759 pkey = load_private_key (0, cinfo);
1760 if (!pkey)
1762 ret = gnutls_privkey_init (&pkey);
1763 if (ret < 0)
1764 error (EXIT_FAILURE, 0, "privkey_init: %s", gnutls_strerror (ret));
1766 xkey = generate_private_key_int (cinfo);
1768 print_private_key (cinfo, xkey);
1770 ret = gnutls_privkey_import_x509(pkey, xkey, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
1771 if (ret < 0)
1772 error (EXIT_FAILURE, 0, "privkey_import_x509: %s", gnutls_strerror (ret));
1775 pubkey = load_public_key_or_import (1, pkey, cinfo);
1777 pk = gnutls_pubkey_get_pk_algorithm (pubkey, NULL);
1779 /* Set the DN.
1781 get_country_crq_set (crq);
1782 get_organization_crq_set (crq);
1783 get_unit_crq_set (crq);
1784 get_locality_crq_set (crq);
1785 get_state_crq_set (crq);
1786 get_cn_crq_set (crq);
1787 get_dc_set (TYPE_CRQ, crq);
1788 get_uid_crq_set (crq);
1789 get_oid_crq_set (crq);
1791 get_dns_name_set (TYPE_CRQ, crq);
1792 get_uri_set (TYPE_CRQ, crq);
1793 get_ip_addr_set (TYPE_CRQ, crq);
1794 get_email_set (TYPE_CRQ, crq);
1796 pass = get_challenge_pass ();
1798 if (pass != NULL && pass[0] != 0)
1800 ret = gnutls_x509_crq_set_challenge_password (crq, pass);
1801 if (ret < 0)
1802 error (EXIT_FAILURE, 0, "set_pass: %s", gnutls_strerror (ret));
1805 if (cinfo->crq_extensions != 0)
1807 ca_status = get_ca_status ();
1808 if (ca_status)
1809 path_len = get_path_len ();
1810 else
1811 path_len = -1;
1813 ret = gnutls_x509_crq_set_basic_constraints (crq, ca_status, path_len);
1814 if (ret < 0)
1815 error (EXIT_FAILURE, 0, "set_basic_constraints: %s",
1816 gnutls_strerror (ret));
1818 if (pk == GNUTLS_PK_RSA)
1820 ret = get_sign_status (1);
1821 if (ret)
1822 usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
1824 /* Only ask for an encryption certificate
1825 * if it is an RSA one */
1826 ret = get_encrypt_status (1);
1827 if (ret)
1828 usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
1829 else
1830 usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
1832 else /* DSA and ECDSA are always signing */
1833 usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
1835 if (ca_status)
1837 ret = get_cert_sign_status ();
1838 if (ret)
1839 usage |= GNUTLS_KEY_KEY_CERT_SIGN;
1841 ret = get_crl_sign_status ();
1842 if (ret)
1843 usage |= GNUTLS_KEY_CRL_SIGN;
1845 ret = get_code_sign_status ();
1846 if (ret)
1848 ret = gnutls_x509_crq_set_key_purpose_oid
1849 (crq, GNUTLS_KP_CODE_SIGNING, 0);
1850 if (ret < 0)
1851 error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (ret));
1854 ret = get_ocsp_sign_status ();
1855 if (ret)
1857 ret = gnutls_x509_crq_set_key_purpose_oid
1858 (crq, GNUTLS_KP_OCSP_SIGNING, 0);
1859 if (ret < 0)
1860 error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (ret));
1863 ret = get_time_stamp_status ();
1864 if (ret)
1866 ret = gnutls_x509_crq_set_key_purpose_oid
1867 (crq, GNUTLS_KP_TIME_STAMPING, 0);
1868 if (ret < 0)
1869 error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (ret));
1872 ret = get_ipsec_ike_status ();
1873 if (ret)
1875 ret = gnutls_x509_crq_set_key_purpose_oid
1876 (crq, GNUTLS_KP_IPSEC_IKE, 0);
1877 if (ret < 0)
1878 error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (ret));
1882 ret = gnutls_x509_crq_set_key_usage (crq, usage);
1883 if (ret < 0)
1884 error (EXIT_FAILURE, 0, "key_usage: %s", gnutls_strerror (ret));
1886 ret = get_tls_client_status ();
1887 if (ret != 0)
1889 ret = gnutls_x509_crq_set_key_purpose_oid
1890 (crq, GNUTLS_KP_TLS_WWW_CLIENT, 0);
1891 if (ret < 0)
1892 error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (ret));
1895 ret = get_tls_server_status ();
1896 if (ret != 0)
1898 ret = gnutls_x509_crq_set_key_purpose_oid
1899 (crq, GNUTLS_KP_TLS_WWW_SERVER, 0);
1900 if (ret < 0)
1901 error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (ret));
1905 ret = gnutls_x509_crq_set_pubkey (crq, pubkey);
1906 if (ret < 0)
1907 error (EXIT_FAILURE, 0, "set_key: %s", gnutls_strerror (ret));
1909 ret = gnutls_x509_crq_privkey_sign (crq, pkey, get_dig_for_pub (pubkey), 0);
1910 if (ret < 0)
1911 error (EXIT_FAILURE, 0, "sign: %s", gnutls_strerror (ret));
1913 print_crq_info (crq, outfile);
1915 gnutls_x509_crq_deinit (crq);
1916 gnutls_privkey_deinit( pkey);
1917 gnutls_pubkey_deinit( pubkey);
1921 static void print_verification_res (FILE* outfile, unsigned int output);
1923 static int detailed_verification(gnutls_x509_crt_t cert,
1924 gnutls_x509_crt_t issuer, gnutls_x509_crl_t crl,
1925 unsigned int verification_output)
1927 char name[512];
1928 char tmp[255];
1929 char issuer_name[512];
1930 size_t name_size;
1931 size_t issuer_name_size;
1932 int ret;
1934 issuer_name_size = sizeof (issuer_name);
1935 ret =
1936 gnutls_x509_crt_get_issuer_dn (cert, issuer_name, &issuer_name_size);
1937 if (ret < 0)
1938 error (EXIT_FAILURE, 0, "gnutls_x509_crt_get_issuer_dn: %s", gnutls_strerror (ret));
1940 name_size = sizeof (name);
1941 ret =
1942 gnutls_x509_crt_get_dn (cert, name, &name_size);
1943 if (ret < 0)
1944 error (EXIT_FAILURE, 0, "gnutls_x509_crt_get_dn: %s", gnutls_strerror (ret));
1946 fprintf (outfile, "\tSubject: %s\n", name);
1947 fprintf (outfile, "\tIssuer: %s\n", issuer_name);
1949 if (issuer != NULL)
1951 issuer_name_size = sizeof (issuer_name);
1952 ret =
1953 gnutls_x509_crt_get_dn (issuer, issuer_name, &issuer_name_size);
1954 if (ret < 0)
1955 error (EXIT_FAILURE, 0, "gnutls_x509_crt_get_issuer_dn: %s", gnutls_strerror (ret));
1957 fprintf (outfile, "\tChecked against: %s\n", issuer_name);
1960 if (crl != NULL)
1962 gnutls_datum_t data;
1964 issuer_name_size = sizeof (issuer_name);
1965 ret =
1966 gnutls_x509_crl_get_issuer_dn (crl, issuer_name, &issuer_name_size);
1967 if (ret < 0)
1968 error (EXIT_FAILURE, 0, "gnutls_x509_crl_get_issuer_dn: %s", gnutls_strerror (ret));
1970 name_size = sizeof(tmp);
1971 ret = gnutls_x509_crl_get_number(crl, tmp, &name_size, NULL);
1972 if (ret < 0)
1973 strcpy(name, "unnumbered");
1974 else
1976 data.data = (void*)tmp;
1977 data.size = name_size;
1979 name_size = sizeof(name);
1980 ret = gnutls_hex_encode(&data, name, &name_size);
1981 if (ret < 0)
1982 error (EXIT_FAILURE, 0, "gnutls_hex_encode: %s", gnutls_strerror (ret));
1984 fprintf (outfile, "\tChecked against CRL[%s] of: %s\n", name, issuer_name);
1987 fprintf (outfile, "\tOutput: ");
1988 print_verification_res(outfile, verification_output);
1990 fputs("\n\n", outfile);
1992 return 0;
1995 /* Will verify a certificate chain. If no CA certificates
1996 * are provided, then the last certificate in the certificate
1997 * chain is used as a CA.
1999 static int
2000 _verify_x509_mem (const void *cert, int cert_size, const void* ca, int ca_size)
2002 int ret;
2003 gnutls_datum_t tmp;
2004 gnutls_x509_crt_t *x509_cert_list = NULL;
2005 gnutls_x509_crt_t *x509_ca_list = NULL;
2006 gnutls_x509_crl_t *x509_crl_list = NULL;
2007 unsigned int x509_ncerts, x509_ncrls = 0, x509_ncas = 0;
2008 gnutls_x509_trust_list_t list;
2009 unsigned int output;
2011 ret = gnutls_x509_trust_list_init(&list, 0);
2012 if (ret < 0)
2013 error (EXIT_FAILURE, 0, "gnutls_x509_trust_list_init: %s",
2014 gnutls_strerror (ret));
2016 if (ca == NULL)
2018 tmp.data = (void*)cert;
2019 tmp.size = cert_size;
2021 else
2023 tmp.data = (void*)ca;
2024 tmp.size = ca_size;
2026 /* Load CAs */
2027 ret = gnutls_x509_crt_list_import2( &x509_ca_list, &x509_ncas, &tmp,
2028 GNUTLS_X509_FMT_PEM, 0);
2029 if (ret < 0 || x509_ncas < 1)
2030 error (EXIT_FAILURE, 0, "error parsing CAs: %s",
2031 gnutls_strerror (ret));
2034 ret = gnutls_x509_crl_list_import2( &x509_crl_list, &x509_ncrls, &tmp,
2035 GNUTLS_X509_FMT_PEM, 0);
2036 if (ret < 0)
2038 x509_crl_list = NULL;
2039 x509_ncrls = 0;
2042 tmp.data = (void*)cert;
2043 tmp.size = cert_size;
2045 /* ignore errors. CRLs might not be given */
2046 ret = gnutls_x509_crt_list_import2( &x509_cert_list, &x509_ncerts, &tmp,
2047 GNUTLS_X509_FMT_PEM, 0);
2048 if (ret < 0 || x509_ncerts < 1)
2049 error (EXIT_FAILURE, 0, "error parsing CRTs: %s",
2050 gnutls_strerror (ret));
2052 if (ca == NULL)
2054 x509_ca_list = &x509_cert_list[x509_ncerts - 1];
2055 x509_ncas = 1;
2058 fprintf(stdout, "Loaded %d certificates, %d CAs and %d CRLs\n\n",
2059 x509_ncerts, x509_ncas, x509_ncrls);
2061 ret = gnutls_x509_trust_list_add_cas(list, x509_ca_list, x509_ncas, 0);
2062 if (ret < 0)
2063 error (EXIT_FAILURE, 0, "gnutls_x509_trust_add_cas: %s",
2064 gnutls_strerror (ret));
2066 ret = gnutls_x509_trust_list_add_crls(list, x509_crl_list, x509_ncrls, 0, 0);
2067 if (ret < 0)
2068 error (EXIT_FAILURE, 0, "gnutls_x509_trust_add_crls: %s",
2069 gnutls_strerror (ret));
2071 gnutls_free(x509_crl_list);
2073 ret = gnutls_x509_trust_list_verify_crt (list, x509_cert_list, x509_ncerts,
2074 GNUTLS_VERIFY_DO_NOT_ALLOW_SAME|GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT, &output,
2075 detailed_verification);
2076 if (ret < 0)
2077 error (EXIT_FAILURE, 0, "gnutls_x509_trusted_list_verify_crt: %s",
2078 gnutls_strerror (ret));
2080 fprintf (outfile, "Chain verification output: ");
2081 print_verification_res(outfile, output);
2083 fprintf (outfile, "\n\n");
2085 gnutls_free(x509_cert_list);
2086 gnutls_x509_trust_list_deinit(list, 1);
2088 if (output != 0)
2089 exit(EXIT_FAILURE);
2091 return 0;
2094 static void
2095 print_verification_res (FILE* outfile, unsigned int output)
2097 gnutls_datum_t pout;
2098 int ret;
2100 if (output)
2102 fprintf (outfile, "Not verified.");
2104 else
2106 fprintf (outfile, "Verified.");
2109 ret = gnutls_certificate_verification_status_print( output, GNUTLS_CRT_X509, &pout, 0);
2110 if (ret < 0)
2112 fprintf(stderr, "error: %s\n", gnutls_strerror(ret));
2113 exit(EXIT_FAILURE);
2116 fprintf (outfile, " %s", pout.data);
2117 gnutls_free(pout.data);
2120 static void
2121 verify_chain (void)
2123 char *buf;
2124 size_t size;
2126 buf = (void*)fread_file (infile, &size);
2127 if (buf == NULL)
2128 error (EXIT_FAILURE, errno, "reading chain");
2130 buf[size] = 0;
2132 _verify_x509_mem (buf, size, NULL, 0);
2136 static void
2137 verify_certificate (common_info_st * cinfo)
2139 char *cert;
2140 char *cas;
2141 size_t cert_size, ca_size;
2142 FILE * ca_file = fopen(cinfo->ca, "r");
2144 if (ca_file == NULL)
2145 error (EXIT_FAILURE, errno, "opening CA file");
2147 cert = (void*)fread_file (infile, &cert_size);
2148 if (cert == NULL)
2149 error (EXIT_FAILURE, errno, "reading certificate chain");
2151 cert[cert_size] = 0;
2153 cas = (void*)fread_file (ca_file, &ca_size);
2154 if (cas == NULL)
2155 error (EXIT_FAILURE, errno, "reading CA list");
2157 cas[ca_size] = 0;
2158 fclose(ca_file);
2160 _verify_x509_mem (cert, cert_size, cas, ca_size);
2165 void
2166 verify_crl (common_info_st * cinfo)
2168 size_t size, dn_size;
2169 char dn[128];
2170 unsigned int output;
2171 int ret;
2172 gnutls_datum_t pem, pout;
2173 gnutls_x509_crl_t crl;
2174 gnutls_x509_crt_t issuer;
2176 issuer = load_ca_cert (cinfo);
2178 fprintf (outfile, "\nCA certificate:\n");
2180 dn_size = sizeof (dn);
2181 ret = gnutls_x509_crt_get_dn (issuer, dn, &dn_size);
2182 if (ret < 0)
2183 error (EXIT_FAILURE, 0, "crt_get_dn: %s", gnutls_strerror (ret));
2185 fprintf (outfile, "\tSubject: %s\n\n", dn);
2187 ret = gnutls_x509_crl_init (&crl);
2188 if (ret < 0)
2189 error (EXIT_FAILURE, 0, "crl_init: %s", gnutls_strerror (ret));
2191 pem.data = (void*)fread_file (infile, &size);
2192 pem.size = size;
2194 ret = gnutls_x509_crl_import (crl, &pem, incert_format);
2195 free (pem.data);
2196 if (ret < 0)
2197 error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (ret));
2199 print_crl_info (crl, outfile);
2201 fprintf (outfile, "Verification output: ");
2202 ret = gnutls_x509_crl_verify (crl, &issuer, 1, 0, &output);
2203 if (ret < 0)
2204 error (EXIT_FAILURE, 0, "verification error: %s", gnutls_strerror (ret));
2206 if (output)
2208 fprintf (outfile, "Not verified. ");
2210 else
2212 fprintf (outfile, "Verified.");
2215 ret = gnutls_certificate_verification_status_print( output, GNUTLS_CRT_X509, &pout, 0);
2216 if (ret < 0)
2218 fprintf(stderr, "error: %s\n", gnutls_strerror(ret));
2219 exit(EXIT_FAILURE);
2222 fprintf (outfile, " %s", pout.data);
2223 gnutls_free(pout.data);
2225 fprintf (outfile, "\n");
2230 void
2231 generate_pkcs8 (common_info_st * cinfo)
2233 gnutls_x509_privkey_t key;
2234 int result;
2235 size_t size;
2236 unsigned int flags = 0;
2237 const char *password;
2239 fprintf (stderr, "Generating a PKCS #8 key structure...\n");
2241 key = load_x509_private_key (1, cinfo);
2243 password = get_password(cinfo, &flags, 1);
2245 flags |= cipher_to_flags (cinfo->pkcs_cipher);
2247 size = buffer_size;
2248 result =
2249 gnutls_x509_privkey_export_pkcs8 (key, outcert_format,
2250 password, flags, buffer, &size);
2252 if (result < 0)
2253 error (EXIT_FAILURE, 0, "key_export: %s", gnutls_strerror (result));
2255 fwrite (buffer, 1, size, outfile);
2260 #include <gnutls/pkcs12.h>
2261 #include <unistd.h>
2263 void
2264 generate_pkcs12 (common_info_st * cinfo)
2266 gnutls_pkcs12_t pkcs12;
2267 gnutls_x509_crt_t *crts;
2268 gnutls_x509_privkey_t *keys;
2269 int result;
2270 size_t size;
2271 gnutls_datum_t data;
2272 const char *pass;
2273 const char *name;
2274 unsigned int flags = 0, i;
2275 gnutls_datum_t key_id;
2276 unsigned char _key_id[32];
2277 int indx;
2278 size_t ncrts;
2279 size_t nkeys;
2281 fprintf (stderr, "Generating a PKCS #12 structure...\n");
2283 keys = load_privkey_list (0, &nkeys, cinfo);
2284 crts = load_cert_list (0, &ncrts, cinfo);
2286 name = get_pkcs12_key_name ();
2288 result = gnutls_pkcs12_init (&pkcs12);
2289 if (result < 0)
2290 error (EXIT_FAILURE, 0, "pkcs12_init: %s", gnutls_strerror (result));
2292 pass = get_password(cinfo, &flags, 1);
2293 flags |= cipher_to_flags (cinfo->pkcs_cipher);
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 indx = result;
2310 if (i==0) /* only the first certificate gets the friendly name */
2312 result = gnutls_pkcs12_bag_set_friendly_name (bag, indx, name);
2313 if (result < 0)
2314 error (EXIT_FAILURE, 0, "bag_set_friendly_name: %s",
2315 gnutls_strerror (result));
2318 size = sizeof (_key_id);
2319 result = gnutls_x509_crt_get_key_id (crts[i], 0, _key_id, &size);
2320 if (result < 0)
2321 error (EXIT_FAILURE, 0, "key_id[%d]: %s", i,
2322 gnutls_strerror (result));
2324 key_id.data = _key_id;
2325 key_id.size = size;
2327 result = gnutls_pkcs12_bag_set_key_id (bag, indx, &key_id);
2328 if (result < 0)
2329 error (EXIT_FAILURE, 0, "bag_set_key_id: %s",
2330 gnutls_strerror (result));
2332 result = gnutls_pkcs12_bag_encrypt (bag, pass, flags);
2333 if (result < 0)
2334 error (EXIT_FAILURE, 0, "bag_encrypt: %s", gnutls_strerror (result));
2336 result = gnutls_pkcs12_set_bag (pkcs12, bag);
2337 if (result < 0)
2338 error (EXIT_FAILURE, 0, "set_bag: %s", gnutls_strerror (result));
2341 for (i = 0; i < nkeys; i++)
2343 gnutls_pkcs12_bag_t kbag;
2345 result = gnutls_pkcs12_bag_init (&kbag);
2346 if (result < 0)
2347 error (EXIT_FAILURE, 0, "bag_init: %s", gnutls_strerror (result));
2349 size = buffer_size;
2350 result =
2351 gnutls_x509_privkey_export_pkcs8 (keys[i], GNUTLS_X509_FMT_DER,
2352 pass, flags, buffer, &size);
2353 if (result < 0)
2354 error (EXIT_FAILURE, 0, "key_export[%d]: %s", i, gnutls_strerror (result));
2356 data.data = buffer;
2357 data.size = size;
2358 result =
2359 gnutls_pkcs12_bag_set_data (kbag,
2360 GNUTLS_BAG_PKCS8_ENCRYPTED_KEY, &data);
2361 if (result < 0)
2362 error (EXIT_FAILURE, 0, "bag_set_data: %s", gnutls_strerror (result));
2364 indx = result;
2366 result = gnutls_pkcs12_bag_set_friendly_name (kbag, indx, name);
2367 if (result < 0)
2368 error (EXIT_FAILURE, 0, "bag_set_friendly_name: %s",
2369 gnutls_strerror (result));
2371 size = sizeof (_key_id);
2372 result = gnutls_x509_privkey_get_key_id (keys[i], 0, _key_id, &size);
2373 if (result < 0)
2374 error (EXIT_FAILURE, 0, "key_id[%d]: %s", i, gnutls_strerror (result));
2376 key_id.data = _key_id;
2377 key_id.size = size;
2379 result = gnutls_pkcs12_bag_set_key_id (kbag, indx, &key_id);
2380 if (result < 0)
2381 error (EXIT_FAILURE, 0, "bag_set_key_id: %s",
2382 gnutls_strerror (result));
2384 result = gnutls_pkcs12_set_bag (pkcs12, kbag);
2385 if (result < 0)
2386 error (EXIT_FAILURE, 0, "set_bag: %s", gnutls_strerror (result));
2389 result = gnutls_pkcs12_generate_mac (pkcs12, pass);
2390 if (result < 0)
2391 error (EXIT_FAILURE, 0, "generate_mac: %s", gnutls_strerror (result));
2393 size = buffer_size;
2394 result = gnutls_pkcs12_export (pkcs12, outcert_format, buffer, &size);
2395 if (result < 0)
2396 error (EXIT_FAILURE, 0, "pkcs12_export: %s", gnutls_strerror (result));
2398 fwrite (buffer, 1, size, outfile);
2402 static const char *
2403 BAGTYPE (gnutls_pkcs12_bag_type_t x)
2405 switch (x)
2407 case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
2408 return "PKCS #8 Encrypted key";
2409 case GNUTLS_BAG_EMPTY:
2410 return "Empty";
2411 case GNUTLS_BAG_PKCS8_KEY:
2412 return "PKCS #8 Key";
2413 case GNUTLS_BAG_CERTIFICATE:
2414 return "Certificate";
2415 case GNUTLS_BAG_ENCRYPTED:
2416 return "Encrypted";
2417 case GNUTLS_BAG_CRL:
2418 return "CRL";
2419 case GNUTLS_BAG_SECRET:
2420 return "Secret";
2421 default:
2422 return "Unknown";
2426 static void
2427 print_bag_data (gnutls_pkcs12_bag_t bag)
2429 int result;
2430 int count, i, type;
2431 gnutls_datum_t cdata, id;
2432 const char *str, *name;
2433 gnutls_datum_t out;
2435 count = gnutls_pkcs12_bag_get_count (bag);
2436 if (count < 0)
2437 error (EXIT_FAILURE, 0, "get_count: %s", gnutls_strerror (count));
2439 fprintf (outfile, "\tElements: %d\n", count);
2441 for (i = 0; i < count; i++)
2443 type = gnutls_pkcs12_bag_get_type (bag, i);
2444 if (type < 0)
2445 error (EXIT_FAILURE, 0, "get_type: %s", gnutls_strerror (type));
2447 fprintf (stderr, "\tType: %s\n", BAGTYPE (type));
2449 name = NULL;
2450 result = gnutls_pkcs12_bag_get_friendly_name (bag, i, (char **) &name);
2451 if (result < 0)
2452 error (EXIT_FAILURE, 0, "get_friendly_name: %s",
2453 gnutls_strerror (type));
2454 if (name)
2455 fprintf (outfile, "\tFriendly name: %s\n", name);
2457 id.data = NULL;
2458 id.size = 0;
2459 result = gnutls_pkcs12_bag_get_key_id (bag, i, &id);
2460 if (result < 0)
2461 error (EXIT_FAILURE, 0, "get_key_id: %s", gnutls_strerror (type));
2462 if (id.size > 0)
2463 fprintf (outfile, "\tKey ID: %s\n", raw_to_string (id.data, id.size));
2465 result = gnutls_pkcs12_bag_get_data (bag, i, &cdata);
2466 if (result < 0)
2467 error (EXIT_FAILURE, 0, "get_data: %s", gnutls_strerror (result));
2469 switch (type)
2471 case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
2472 str = "ENCRYPTED PRIVATE KEY";
2473 break;
2474 case GNUTLS_BAG_PKCS8_KEY:
2475 str = "PRIVATE KEY";
2476 break;
2477 case GNUTLS_BAG_CERTIFICATE:
2478 str = "CERTIFICATE";
2479 break;
2480 case GNUTLS_BAG_CRL:
2481 str = "CRL";
2482 break;
2483 case GNUTLS_BAG_ENCRYPTED:
2484 case GNUTLS_BAG_EMPTY:
2485 default:
2486 str = NULL;
2489 if (str != NULL)
2491 gnutls_pem_base64_encode_alloc (str, &cdata, &out);
2492 fprintf (outfile, "%s\n", out.data);
2494 gnutls_free (out.data);
2500 void
2501 pkcs12_info (common_info_st* cinfo)
2503 gnutls_pkcs12_t pkcs12;
2504 gnutls_pkcs12_bag_t bag;
2505 int result;
2506 size_t size;
2507 gnutls_datum_t data;
2508 const char *pass;
2509 int indx, fail = 0;
2511 result = gnutls_pkcs12_init (&pkcs12);
2512 if (result < 0)
2513 error (EXIT_FAILURE, 0, "p12_init: %s", gnutls_strerror (result));
2515 data.data = (void*)fread_file (infile, &size);
2516 data.size = size;
2518 result = gnutls_pkcs12_import (pkcs12, &data, incert_format, 0);
2519 free (data.data);
2520 if (result < 0)
2521 error (EXIT_FAILURE, 0, "p12_import: %s", gnutls_strerror (result));
2523 pass = get_password(cinfo, NULL, 0);
2525 result = gnutls_pkcs12_verify_mac (pkcs12, pass);
2526 if (result < 0)
2528 fail = 1;
2529 error (0, 0, "verify_mac: %s", gnutls_strerror (result));
2532 for (indx = 0;; indx++)
2534 result = gnutls_pkcs12_bag_init (&bag);
2535 if (result < 0)
2536 error (EXIT_FAILURE, 0, "bag_init: %s", gnutls_strerror (result));
2538 result = gnutls_pkcs12_get_bag (pkcs12, indx, bag);
2539 if (result < 0)
2540 break;
2542 result = gnutls_pkcs12_bag_get_count (bag);
2543 if (result < 0)
2544 error (EXIT_FAILURE, 0, "bag_count: %s", gnutls_strerror (result));
2546 fprintf (outfile, "BAG #%d\n", indx);
2548 result = gnutls_pkcs12_bag_get_type (bag, 0);
2549 if (result < 0)
2550 error (EXIT_FAILURE, 0, "bag_init: %s", gnutls_strerror (result));
2552 if (result == GNUTLS_BAG_ENCRYPTED)
2554 fprintf (stderr, "\tType: %s\n", BAGTYPE (result));
2555 fprintf (stderr, "\n\tDecrypting...\n");
2557 result = gnutls_pkcs12_bag_decrypt (bag, pass);
2559 if (result < 0)
2561 fail = 1;
2562 error (0, 0, "bag_decrypt: %s", gnutls_strerror (result));
2563 continue;
2566 result = gnutls_pkcs12_bag_get_count (bag);
2567 if (result < 0)
2568 error (EXIT_FAILURE, 0, "encrypted bag_count: %s",
2569 gnutls_strerror (result));
2572 print_bag_data (bag);
2574 gnutls_pkcs12_bag_deinit (bag);
2577 if (fail)
2578 error (EXIT_FAILURE, 0, "There were errors parsing the structure\n");
2581 void
2582 pkcs7_info (void)
2584 gnutls_pkcs7_t pkcs7;
2585 int result;
2586 size_t size;
2587 gnutls_datum_t data, b64;
2588 int indx, count;
2590 result = gnutls_pkcs7_init (&pkcs7);
2591 if (result < 0)
2592 error (EXIT_FAILURE, 0, "p7_init: %s", gnutls_strerror (result));
2594 data.data = (void*)fread_file (infile, &size);
2595 data.size = size;
2597 result = gnutls_pkcs7_import (pkcs7, &data, incert_format);
2598 free (data.data);
2599 if (result < 0)
2600 error (EXIT_FAILURE, 0, "import error: %s", gnutls_strerror (result));
2602 /* Read and print the certificates.
2604 result = gnutls_pkcs7_get_crt_count (pkcs7);
2605 if (result < 0)
2606 error (EXIT_FAILURE, 0, "p7_crt_count: %s", gnutls_strerror (result));
2608 count = result;
2610 if (count > 0)
2611 fprintf (outfile, "Number of certificates: %u\n", count);
2613 for (indx = 0; indx < count; indx++)
2615 fputs ("\n", outfile);
2617 size = buffer_size;
2618 result = gnutls_pkcs7_get_crt_raw (pkcs7, indx, buffer, &size);
2619 if (result < 0)
2620 break;
2622 data.data = buffer;
2623 data.size = size;
2625 result = gnutls_pem_base64_encode_alloc ("CERTIFICATE", &data, &b64);
2626 if (result < 0)
2627 error (EXIT_FAILURE, 0, "encoding: %s", gnutls_strerror (result));
2629 fputs ((void*)b64.data, outfile);
2630 gnutls_free (b64.data);
2633 /* Read the CRLs now.
2635 result = gnutls_pkcs7_get_crl_count (pkcs7);
2636 if (result < 0)
2637 error (EXIT_FAILURE, 0, "p7_crl_count: %s", gnutls_strerror (result));
2639 count = result;
2641 if (count > 0)
2642 fprintf (outfile, "\nNumber of CRLs: %u\n", count);
2644 for (indx = 0; indx < count; indx++)
2646 fputs ("\n", outfile);
2648 size = buffer_size;
2649 result = gnutls_pkcs7_get_crl_raw (pkcs7, indx, buffer, &size);
2650 if (result < 0)
2651 break;
2653 data.data = buffer;
2654 data.size = size;
2656 result = gnutls_pem_base64_encode_alloc ("X509 CRL", &data, &b64);
2657 if (result < 0)
2658 error (EXIT_FAILURE, 0, "encoding: %s", gnutls_strerror (result));
2660 fputs ((void*)b64.data, outfile);
2661 gnutls_free (b64.data);
2665 void
2666 smime_to_pkcs7 (void)
2668 size_t linesize = 0;
2669 char *lineptr = NULL;
2670 ssize_t len;
2672 /* Find body. FIXME: Handle non-b64 Content-Transfer-Encoding.
2673 Reject non-S/MIME tagged Content-Type's? */
2676 len = getline (&lineptr, &linesize, infile);
2677 if (len == -1)
2678 error (EXIT_FAILURE, 0, "cannot find RFC 2822 header/body separator");
2680 while (strcmp (lineptr, "\r\n") != 0 && strcmp (lineptr, "\n") != 0);
2684 len = getline (&lineptr, &linesize, infile);
2685 if (len == -1)
2686 error (EXIT_FAILURE, 0, "message has RFC 2822 header but no body");
2688 while (strcmp (lineptr, "\r\n") == 0 && strcmp (lineptr, "\n") == 0);
2690 fprintf (outfile, "%s", "-----BEGIN PKCS7-----\n");
2694 while (len > 0
2695 && (lineptr[len - 1] == '\r' || lineptr[len - 1] == '\n'))
2696 lineptr[--len] = '\0';
2697 if (strcmp (lineptr, "") != 0)
2698 fprintf (outfile, "%s\n", lineptr);
2699 len = getline (&lineptr, &linesize, infile);
2701 while (len != -1);
2703 fprintf (outfile, "%s", "-----END PKCS7-----\n");
2705 free (lineptr);
2709 void
2710 pubkey_info (gnutls_x509_crt_t crt, common_info_st * cinfo)
2712 gnutls_pubkey_t pubkey;
2713 gnutls_privkey_t privkey = NULL;
2714 gnutls_x509_crq_t crq = NULL;
2715 int ret;
2716 size_t size;
2718 ret = gnutls_pubkey_init (&pubkey);
2719 if (ret < 0)
2721 error (EXIT_FAILURE, 0, "pubkey_init: %s", gnutls_strerror (ret));
2724 if (crt == NULL)
2726 crt = load_cert (0, cinfo);
2729 if (crq == NULL)
2731 crq = load_request (cinfo);
2734 if (crt != NULL)
2736 ret = gnutls_pubkey_import_x509 (pubkey, crt, 0);
2737 if (ret < 0)
2738 error (EXIT_FAILURE, 0, "pubkey_import_x509: %s",
2739 gnutls_strerror (ret));
2741 else if (crq != NULL)
2743 ret = gnutls_pubkey_import_x509_crq (pubkey, crq, 0);
2744 if (ret < 0)
2745 error (EXIT_FAILURE, 0, "pubkey_import_x509_crq: %s",
2746 gnutls_strerror (ret));
2748 else
2750 privkey = load_private_key (0, cinfo);
2752 if (privkey != NULL)
2754 ret = gnutls_pubkey_import_privkey(pubkey, privkey, 0, 0);
2755 if (ret < 0)
2756 error (EXIT_FAILURE, 0, "pubkey_import_privkey: %s",
2757 gnutls_strerror (ret));
2759 else
2761 gnutls_pubkey_deinit(pubkey);
2762 pubkey = load_pubkey (1, cinfo);
2766 if (outcert_format == GNUTLS_X509_FMT_DER)
2768 size = buffer_size;
2769 ret = gnutls_pubkey_export (pubkey, outcert_format, buffer, &size);
2770 if (ret < 0)
2771 error (EXIT_FAILURE, 0, "export error: %s", gnutls_strerror (ret));
2773 fwrite (buffer, 1, size, outfile);
2775 gnutls_pubkey_deinit (pubkey);
2777 return;
2780 /* PEM */
2782 _pubkey_info(outfile, full_format, pubkey);
2783 gnutls_pubkey_deinit (pubkey);