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/>.
20 * In addition, as a special exception, the copyright holders give
21 * permission to link the code of portions of this program with the
22 * OpenSSL library under certain conditions as described in each
23 * individual source file, and distribute linked combinations including
26 * You must obey the GNU General Public License in all respects for all
27 * of the code used other than OpenSSL. If you modify file(s) with this
28 * exception, you may extend this exception to your version of the
29 * file(s), but you are not obligated to do so. If you do not wish to do
30 * so, delete this exception statement from your version. If you delete
31 * this exception statement from all source files in the program, then
32 * also delete it here.
37 #include <gnutls/gnutls.h>
38 #include <gnutls/x509.h>
39 #include <gnutls/openpgp.h>
40 #include <gnutls/pkcs12.h>
41 #include <gnutls/pkcs11.h>
42 #include <gnutls/abstract.h>
51 #include <sys/types.h>
55 #include "certtool-common.h"
56 #include "certtool-args.h"
57 #include "certtool-cfg.h"
60 /* Gnulib portability files. */
61 #include <read-file.h>
63 unsigned char *lbuffer = NULL;
64 unsigned long lbuffer_size = 0;
66 static unsigned long file_size(FILE *fp)
69 unsigned long cur = ftell(fp);
70 fseek(fp, 0, SEEK_END);
72 fseek(fp, cur, SEEK_SET);
76 void fix_lbuffer(unsigned long size)
78 if (lbuffer_size == 0 || lbuffer == NULL) {
80 lbuffer_size = 64*1024;
82 lbuffer_size = MAX(64*1024,size+1);
83 lbuffer = malloc(lbuffer_size);
84 } else if (size > lbuffer_size) {
85 lbuffer_size = MAX(64*1024,size+1);
86 lbuffer = realloc(lbuffer, lbuffer_size);
89 if (lbuffer == NULL) {
90 fprintf(stderr, "memory error");
95 FILE *safe_open_rw(const char *file, int privkey_op)
100 if (privkey_op != 0) {
101 omask = umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
104 fh = fopen(file, "wb");
106 if (privkey_op != 0) {
113 gnutls_datum_t *load_secret_key(int mand, common_info_st * info)
115 static char raw_key[64];
116 size_t raw_key_size = sizeof(raw_key);
117 static gnutls_datum_t key;
118 gnutls_datum_t hex_key;
122 fprintf(stderr, "Loading secret key...\n");
124 if (info->secret_key == NULL) {
126 fprintf(stderr, "missing --secret-key\n");
132 hex_key.data = (void *) info->secret_key;
133 hex_key.size = strlen(info->secret_key);
135 ret = gnutls_hex_decode(&hex_key, raw_key, &raw_key_size);
137 fprintf(stderr, "hex_decode: %s\n", gnutls_strerror(ret));
141 key.data = (void *) raw_key;
142 key.size = raw_key_size;
147 const char *get_password(common_info_st * cinfo, unsigned int *flags,
152 if (cinfo->null_password) {
154 *flags |= GNUTLS_PKCS_NULL_PASSWORD;
156 } else if (cinfo->password) {
160 p = get_confirmed_pass(true);
165 if ((p == NULL || p[0] == 0) && flags && !cinfo->empty_password)
166 *flags |= GNUTLS_PKCS_PLAIN;
171 static gnutls_privkey_t _load_privkey(gnutls_datum_t * dat,
172 common_info_st * info)
175 gnutls_privkey_t key;
176 unsigned int flags = 0;
179 ret = gnutls_privkey_init(&key);
181 fprintf(stderr, "privkey_init: %s\n", gnutls_strerror(ret));
186 gnutls_privkey_import_x509_raw(key, dat, info->incert_format,
188 if (ret == GNUTLS_E_DECRYPTION_FAILED) {
189 pass = get_password(info, &flags, 0);
191 gnutls_privkey_import_x509_raw(key, dat,
196 if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR) {
198 "import error: could not find a valid PEM header; "
199 "check if your key is PKCS #12 encoded\n");
204 fprintf(stderr, "importing --load-privkey: %s: %s\n",
205 info->privkey, gnutls_strerror(ret));
212 static gnutls_privkey_t _load_url_privkey(const char *url)
215 gnutls_privkey_t key;
217 ret = gnutls_privkey_init(&key);
219 fprintf(stderr, "privkey_init: %s\n", gnutls_strerror(ret));
223 ret = gnutls_privkey_import_url(key, url, 0);
225 fprintf(stderr, "importing key: %s: %s\n",
226 url, gnutls_strerror(ret));
233 static gnutls_pubkey_t _load_url_pubkey(const char *url)
236 gnutls_pubkey_t pubkey;
237 unsigned int obj_flags = 0;
239 ret = gnutls_pubkey_init(&pubkey);
241 fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__,
242 gnutls_strerror(ret));
246 ret = gnutls_pubkey_import_url(pubkey, url, obj_flags);
248 fprintf(stderr, "Error in %s:%d: %s: %s\n", __func__,
249 __LINE__, gnutls_strerror(ret), url);
256 /* Load the private key.
257 * @mand should be non zero if it is required to read a private key.
259 gnutls_privkey_t load_private_key(int mand, common_info_st * info)
261 gnutls_privkey_t key;
265 if (!info->privkey && !mand)
268 if (info->privkey == NULL) {
269 fprintf(stderr, "missing --load-privkey\n");
273 if (gnutls_url_is_supported(info->privkey) != 0)
274 return _load_url_privkey(info->privkey);
276 dat.data = (void *) read_binary_file(info->privkey, &size);
280 fprintf(stderr, "reading --load-privkey: %s\n",
285 key = _load_privkey(&dat, info);
292 /* Load the private key.
293 * @mand should be non zero if it is required to read a private key.
295 gnutls_x509_privkey_t
296 load_x509_private_key(int mand, common_info_st * info)
298 gnutls_x509_privkey_t key;
302 unsigned int flags = 0;
305 if (!info->privkey && !mand)
308 if (info->privkey == NULL) {
309 fprintf(stderr, "missing --load-privkey\n");
313 ret = gnutls_x509_privkey_init(&key);
315 fprintf(stderr, "privkey_init: %s\n", gnutls_strerror(ret));
319 dat.data = (void *) read_binary_file(info->privkey, &size);
323 fprintf(stderr, "reading --load-privkey: %s\n",
329 pass = get_password(info, &flags, 0);
331 gnutls_x509_privkey_import_pkcs8(key, &dat,
336 gnutls_x509_privkey_import2(key, &dat,
337 info->incert_format, NULL,
339 if (ret == GNUTLS_E_DECRYPTION_FAILED) {
340 pass = get_password(info, &flags, 0);
342 gnutls_x509_privkey_import2(key, &dat,
351 if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR) {
353 "import error: could not find a valid PEM header; "
354 "check if your key is PEM encoded\n");
359 fprintf(stderr, "importing --load-privkey: %s: %s\n",
360 info->privkey, gnutls_strerror(ret));
368 /* Loads the certificate
369 * If mand is non zero then a certificate is mandatory. Otherwise
370 * null will be returned if the certificate loading fails.
372 gnutls_x509_crt_t load_cert(int mand, common_info_st * info)
374 gnutls_x509_crt_t *crt;
375 gnutls_x509_crt_t ret_crt;
378 crt = load_cert_list(mand, &size, info);
382 gnutls_x509_crt_deinit(crt[i]);
390 /* Loads a certificate list
392 gnutls_x509_crt_t *load_cert_list(int mand, size_t * crt_size,
393 common_info_st * info)
396 static gnutls_x509_crt_t *crt;
400 unsigned int crt_max;
404 fprintf(stderr, "Loading certificate list...\n");
406 if (info->cert == NULL) {
408 fprintf(stderr, "missing --load-certificate\n");
414 fd = fopen(info->cert, "r");
416 fprintf(stderr, "Could not open %s\n", info->cert);
420 fix_lbuffer(file_size(fd));
422 size = fread(lbuffer, 1, lbuffer_size - 1, fd);
427 dat.data = (void *) lbuffer;
430 ret = gnutls_x509_crt_list_import2(&crt, &crt_max, &dat, GNUTLS_X509_FMT_PEM, 0);
432 fprintf(stderr, "Error loading certificates: %s\n", gnutls_strerror(ret));
439 fprintf(stderr, "Loaded %d certificates.\n",
445 /* Load the Certificate Request.
447 gnutls_x509_crq_t load_request(common_info_st * info)
449 gnutls_x509_crq_t crq;
457 ret = gnutls_x509_crq_init(&crq);
459 fprintf(stderr, "crq_init: %s\n", gnutls_strerror(ret));
463 dat.data = (void *) read_binary_file(info->request, &size);
467 fprintf(stderr, "reading --load-request: %s\n",
472 ret = gnutls_x509_crq_import(crq, &dat, info->incert_format);
473 if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR) {
475 "import error: could not find a valid PEM header\n");
481 fprintf(stderr, "importing --load-request: %s: %s\n",
482 info->request, gnutls_strerror(ret));
488 /* Load the CA's private key.
490 gnutls_privkey_t load_ca_private_key(common_info_st * info)
492 gnutls_privkey_t key;
496 if (info->ca_privkey == NULL) {
497 fprintf(stderr, "missing --load-ca-privkey\n");
501 if (gnutls_url_is_supported(info->ca_privkey) != 0)
502 return _load_url_privkey(info->ca_privkey);
504 dat.data = (void *) read_binary_file(info->ca_privkey, &size);
508 fprintf(stderr, "reading --load-ca-privkey: %s\n",
513 key = _load_privkey(&dat, info);
520 /* Loads the CA's certificate
522 gnutls_x509_crt_t load_ca_cert(unsigned mand, common_info_st * info)
524 gnutls_x509_crt_t crt;
529 if (mand == 0 && info->ca == NULL) {
533 if (info->ca == NULL) {
534 fprintf(stderr, "missing --load-ca-certificate\n");
538 ret = gnutls_x509_crt_init(&crt);
540 fprintf(stderr, "crt_init: %s\n", gnutls_strerror(ret));
544 dat.data = (void *) read_binary_file(info->ca, &size);
548 fprintf(stderr, "error reading --load-ca-certificate: %s\n",
553 ret = gnutls_x509_crt_import(crt, &dat, info->incert_format);
556 fprintf(stderr, "importing --load-ca-certificate: %s: %s\n",
557 info->ca, gnutls_strerror(ret));
564 /* Load a public key.
565 * @mand should be non zero if it is required to read a public key.
567 gnutls_pubkey_t load_pubkey(int mand, common_info_st * info)
574 if (!info->pubkey && !mand)
577 if (info->pubkey == NULL) {
578 fprintf(stderr, "missing --load-pubkey\n");
582 if (gnutls_url_is_supported(info->pubkey) != 0)
583 return _load_url_pubkey(info->pubkey);
585 ret = gnutls_pubkey_init(&key);
587 fprintf(stderr, "privkey_init: %s\n", gnutls_strerror(ret));
591 dat.data = (void *) read_binary_file(info->pubkey, &size);
595 fprintf(stderr, "reading --load-pubkey: %s\n", info->pubkey);
599 ret = gnutls_pubkey_import(key, &dat, info->incert_format);
603 if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR) {
605 "import error: could not find a valid PEM header; "
606 "check if your key has the PUBLIC KEY header\n");
611 fprintf(stderr, "importing --load-pubkey: %s: %s\n",
612 info->pubkey, gnutls_strerror(ret));
619 gnutls_pubkey_t load_public_key_or_import(int mand,
620 gnutls_privkey_t privkey,
621 common_info_st * info)
623 gnutls_pubkey_t pubkey;
626 ret = gnutls_pubkey_init(&pubkey);
628 fprintf(stderr, "gnutls_pubkey_init: %s\n",
629 gnutls_strerror(ret));
633 if (!privkey || (ret = gnutls_pubkey_import_privkey(pubkey, privkey, 0, 0)) < 0) { /* could not get (e.g. on PKCS #11 */
634 gnutls_pubkey_deinit(pubkey);
635 pubkey = load_pubkey(0, info);
636 if (pubkey == NULL && mand) {
637 fprintf(stderr, "You must specify --load-privkey\n");
646 get_bits(gnutls_pk_algorithm_t key_type, int info_bits,
647 const char *info_sec_param, int warn)
651 if (info_bits != 0) {
652 static int warned = 0;
654 if (warned == 0 && warn != 0 && GNUTLS_BITS_ARE_CURVE(info_bits)==0) {
657 "** Note: Please use the --sec-param instead of --bits\n");
661 if (info_sec_param == 0) {
662 /* For ECDSA keys use 256 bits or better, as they are widely supported */
663 if (key_type == GNUTLS_PK_EC)
664 info_sec_param = "HIGH";
666 info_sec_param = "MEDIUM";
669 gnutls_sec_param_to_pk_bits(key_type,
677 gnutls_sec_param_t str_to_sec_param(const char *str)
679 if (strcasecmp(str, "low") == 0) {
680 return GNUTLS_SEC_PARAM_LOW;
681 } else if (strcasecmp(str, "legacy") == 0) {
682 return GNUTLS_SEC_PARAM_LEGACY;
683 } else if (strcasecmp(str, "normal") == 0 || strcasecmp(str, "medium") == 0) {
684 return GNUTLS_SEC_PARAM_MEDIUM;
685 } else if (strcasecmp(str, "high") == 0) {
686 return GNUTLS_SEC_PARAM_HIGH;
687 } else if (strcasecmp(str, "ultra") == 0) {
688 return GNUTLS_SEC_PARAM_ULTRA;
690 fprintf(stderr, "Unknown security parameter string: %s\n",
699 print_hex_datum(FILE * outfile, gnutls_datum_t * dat, int cprint)
704 fprintf(outfile, "\n" SPACE "\"");
705 for (j = 0; j < dat->size; j++) {
706 fprintf(outfile, "\\x%.2x",
707 (unsigned char) dat->data[j]);
708 if ((j + 1) % 15 == 0)
709 fprintf(outfile, "\"\n" SPACE "\"");
711 fprintf(outfile, "\";\n\n");
716 fprintf(outfile, "\n" SPACE);
717 for (j = 0; j < dat->size; j++) {
718 fprintf(outfile, "%.2x:", (unsigned char) dat->data[j]);
719 if ((j + 1) % 15 == 0)
720 fprintf(outfile, "\n" SPACE);
722 fprintf(outfile, "\n\n");
725 static void print_head(FILE * out, const char *txt, unsigned int size,
733 asprintf(&ntxt, "const unsigned char %s[%u] =",
736 asprintf(&ntxt, "const unsigned char %s[] =\n",
739 p = strstr(ntxt, "char");
742 for (i = 0; i < strlen(txt); i++)
746 fprintf(out, "%s", ntxt);
751 fprintf(out, "%s:", txt);
755 print_dsa_pkey(FILE * outfile, gnutls_datum_t * x, gnutls_datum_t * y,
756 gnutls_datum_t * p, gnutls_datum_t * q, gnutls_datum_t * g,
760 print_head(outfile, "private key", x->size, cprint);
761 print_hex_datum(outfile, x, cprint);
763 print_head(outfile, "public key", y->size, cprint);
764 print_hex_datum(outfile, y, cprint);
765 print_head(outfile, "p", p->size, cprint);
766 print_hex_datum(outfile, p, cprint);
767 print_head(outfile, "q", q->size, cprint);
768 print_hex_datum(outfile, q, cprint);
769 print_head(outfile, "g", g->size, cprint);
770 print_hex_datum(outfile, g, cprint);
773 gnutls_ecc_curve_t str_to_curve(const char *str)
776 const gnutls_ecc_curve_t *list, *p;
778 list = gnutls_ecc_curve_list();
782 if (strcasecmp(str, gnutls_ecc_curve_get_name(*p)) == 0)
788 fprintf(stderr, "Unsupported curve: %s\nAvailable curves:\n", str);
793 fprintf(stderr, "\t- %s\n",
794 gnutls_ecc_curve_get_name(*p));
801 print_ecc_pkey(FILE * outfile, gnutls_ecc_curve_t curve,
802 gnutls_datum_t * k, gnutls_datum_t * x, gnutls_datum_t * y,
806 fprintf(outfile, "/* curve: %s */\n",
807 gnutls_ecc_curve_get_name(curve));
809 fprintf(outfile, "curve:\t%s\n",
810 gnutls_ecc_curve_get_name(curve));
813 print_head(outfile, "private key", k->size, cprint);
814 print_hex_datum(outfile, k, cprint);
816 print_head(outfile, "x", x->size, cprint);
817 print_hex_datum(outfile, x, cprint);
818 print_head(outfile, "y", y->size, cprint);
819 print_hex_datum(outfile, y, cprint);
824 print_rsa_pkey(FILE * outfile, gnutls_datum_t * m, gnutls_datum_t * e,
825 gnutls_datum_t * d, gnutls_datum_t * p, gnutls_datum_t * q,
826 gnutls_datum_t * u, gnutls_datum_t * exp1,
827 gnutls_datum_t * exp2, int cprint)
829 print_head(outfile, "modulus", m->size, cprint);
830 print_hex_datum(outfile, m, cprint);
831 print_head(outfile, "public exponent", e->size, cprint);
832 print_hex_datum(outfile, e, cprint);
834 print_head(outfile, "private exponent", d->size, cprint);
835 print_hex_datum(outfile, d, cprint);
836 print_head(outfile, "prime1", p->size, cprint);
837 print_hex_datum(outfile, p, cprint);
838 print_head(outfile, "prime2", q->size, cprint);
839 print_hex_datum(outfile, q, cprint);
840 print_head(outfile, "coefficient", u->size, cprint);
841 print_hex_datum(outfile, u, cprint);
843 print_head(outfile, "exp1", exp1->size, cprint);
844 print_hex_datum(outfile, exp1, cprint);
845 print_head(outfile, "exp2", exp2->size, cprint);
846 print_hex_datum(outfile, exp2, cprint);
851 void _pubkey_info(FILE * outfile,
852 gnutls_certificate_print_formats_t format,
853 gnutls_pubkey_t pubkey)
861 ret = gnutls_pubkey_print(pubkey, format, &data);
863 fprintf(stderr, "pubkey_print error: %s\n",
864 gnutls_strerror(ret));
868 fprintf(outfile, "%s\n", data.data);
869 gnutls_free(data.data);
873 gnutls_pubkey_export(pubkey, GNUTLS_X509_FMT_PEM, lbuffer,
876 fprintf(stderr, "export error: %s\n", gnutls_strerror(ret));
880 fprintf(outfile, "\n%s\n", lbuffer);
884 print_dh_info(FILE * outfile, gnutls_datum_t * p, gnutls_datum_t * g,
885 unsigned int q_bits, int cprint)
890 "\n /* recommended key length: %d bytes */\n\n",
894 "\nRecommended key length: %d bits\n\n",
898 print_head(outfile, "generator", g->size, cprint);
899 print_hex_datum(outfile, g, cprint);
901 print_head(outfile, "prime", p->size, cprint);
902 print_hex_datum(outfile, p, cprint);
907 void dh_info(FILE * infile, FILE * outfile, common_info_st * ci)
909 gnutls_datum_t params;
912 gnutls_dh_params_t dh_params;
914 unsigned int q_bits = 0;
918 if (gnutls_dh_params_init(&dh_params) < 0) {
919 fprintf(stderr, "Error in dh parameter initialization\n");
923 params.data = (void *) fread_file(infile, &size);
927 gnutls_dh_params_import_pkcs3(dh_params, ¶ms,
930 fprintf(stderr, "Error parsing dh params: %s\n",
931 gnutls_strerror(ret));
935 ret = gnutls_dh_params_export_raw(dh_params, &p, &g, &q_bits);
937 fprintf(stderr, "Error exporting parameters: %s\n",
938 gnutls_strerror(ret));
942 if (ci->outcert_format == GNUTLS_X509_FMT_PEM)
943 print_dh_info(outfile, &p, &g, q_bits, ci->cprint);
945 if (!ci->cprint) { /* generate a PKCS#3 structure */
946 size_t len = lbuffer_size;
949 gnutls_dh_params_export_pkcs3(dh_params,
954 if (ci->outcert_format == GNUTLS_X509_FMT_PEM) {
955 fprintf(outfile, "\n%s", lbuffer);
957 fwrite(lbuffer, 1, len, outfile);
960 fprintf(stderr, "Error: %s\n",
961 gnutls_strerror(ret));
965 gnutls_dh_params_deinit(dh_params);
968 /* If how is zero then the included parameters are used.
970 int generate_prime(FILE * outfile, int how, common_info_st * info)
973 gnutls_dh_params_t dh_params;
975 int bits = get_bits(GNUTLS_PK_DH, info->bits, info->sec_param, 1);
976 unsigned int q_bits = 0;
980 gnutls_dh_params_init(&dh_params);
983 fprintf(stderr, "Generating DH parameters (%d bits)...\n",
985 fprintf(stderr, "(might take long time)\n");
987 fprintf(stderr, "Retrieving DH parameters...\n");
990 ret = gnutls_dh_params_generate2(dh_params, bits);
993 "Error generating parameters: %s\n",
994 gnutls_strerror(ret));
999 gnutls_dh_params_export_raw(dh_params, &p, &g,
1002 fprintf(stderr, "Error exporting parameters: %s\n",
1003 gnutls_strerror(ret));
1009 p = gnutls_srp_1024_group_prime;
1010 g = gnutls_srp_1024_group_generator;
1012 } else if (bits <= 1536) {
1013 p = gnutls_srp_1536_group_prime;
1014 g = gnutls_srp_1536_group_generator;
1016 } else if (bits <= 2048) {
1017 p = gnutls_srp_2048_group_prime;
1018 g = gnutls_srp_2048_group_generator;
1020 } else if (bits <= 3072) {
1021 p = gnutls_srp_3072_group_prime;
1022 g = gnutls_srp_3072_group_generator;
1025 p = gnutls_srp_4096_group_prime;
1026 g = gnutls_srp_4096_group_generator;
1030 ret = gnutls_dh_params_import_raw(dh_params, &p, &g);
1032 fprintf(stderr, "Error exporting parameters: %s\n",
1033 gnutls_strerror(ret));
1038 "Parameters unavailable as SRP is disabled.\n");
1043 print_dh_info(outfile, &p, &g, q_bits, info->cprint);
1045 if (!info->cprint) { /* generate a PKCS#3 structure */
1046 size_t len = lbuffer_size;
1049 gnutls_dh_params_export_pkcs3(dh_params,
1050 GNUTLS_X509_FMT_PEM,
1054 fprintf(outfile, "\n%s", lbuffer);
1056 fprintf(stderr, "Error: %s\n",
1057 gnutls_strerror(ret));
1062 gnutls_dh_params_deinit(dh_params);