summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2016-02-11 11:00:15 +0100
committerNikos Mavrogiannopoulos <nmav@redhat.com>2016-02-11 11:08:27 +0100
commit0e75df5880c8b03498413d833648881ce904af94 (patch)
tree45d673b0aae7979fd2a98e21e920946d154a7a92
parenta9897e0259be94bbbbb0c570e46e6263472c45d4 (diff)
downloadgnutls-0e75df5880c8b03498413d833648881ce904af94.tar.gz
certtool: the --generate-dh-params option can be combined with --provable
This however, will generate provable DSA parameters and import them as DH parameters. Resolves #72
-rw-r--r--src/Makefile.am2
-rw-r--r--src/certtool-common.c271
-rw-r--r--src/certtool-common.h7
-rw-r--r--src/certtool.c222
-rw-r--r--src/common.h5
5 files changed, 281 insertions, 226 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 162664cba1..1901a76709 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -209,7 +209,7 @@ libcmd_tpmtool_la_LIBADD += $(LTLIBREADLINE) $(INET_PTON_LIB) $(LIB_CLOCK_GETTIM
endif # ENABLE_TROUSERS
-systemkey_SOURCES = systemkey.c certtool-common.c
+systemkey_SOURCES = systemkey.c certtool-common.c common.c
systemkey_LDADD = ../lib/libgnutls.la
systemkey_LDADD += libcmd-systemkey.la $(LIBOPTS) ../gl/libgnu.la gl/libgnu_gpl.la
systemkey_LDADD += $(LTLIBINTL)
diff --git a/src/certtool-common.c b/src/certtool-common.c
index 63e4f1f936..6729681d18 100644
--- a/src/certtool-common.c
+++ b/src/certtool-common.c
@@ -41,6 +41,7 @@
#include "certtool-common.h"
#include "certtool-args.h"
#include "certtool-cfg.h"
+#include "common.h"
#include <minmax.h>
/* Gnulib portability files. */
@@ -1040,6 +1041,221 @@ void dh_info(FILE * infile, FILE * outfile, common_info_st * ci)
gnutls_dh_params_deinit(dh_params);
}
+int cipher_to_flags(const char *cipher)
+{
+ if (cipher == NULL) {
+#ifdef ENABLE_FIPS140
+ return GNUTLS_PKCS_USE_PBES2_AES_128;
+#else /* compatibility mode - most implementations don't support PBES2 with AES */
+ return GNUTLS_PKCS_USE_PKCS12_3DES;
+#endif
+ } else if (strcasecmp(cipher, "3des") == 0) {
+ return GNUTLS_PKCS_USE_PBES2_3DES;
+ } else if (strcasecmp(cipher, "3des-pkcs12") == 0) {
+ return GNUTLS_PKCS_USE_PKCS12_3DES;
+ } else if (strcasecmp(cipher, "arcfour") == 0) {
+ return GNUTLS_PKCS_USE_PKCS12_ARCFOUR;
+ } else if (strcasecmp(cipher, "aes-128") == 0) {
+ return GNUTLS_PKCS_USE_PBES2_AES_128;
+ } else if (strcasecmp(cipher, "aes-192") == 0) {
+ return GNUTLS_PKCS_USE_PBES2_AES_192;
+ } else if (strcasecmp(cipher, "aes-256") == 0) {
+ return GNUTLS_PKCS_USE_PBES2_AES_256;
+ } else if (strcasecmp(cipher, "rc2-40") == 0) {
+ return GNUTLS_PKCS_USE_PKCS12_RC2_40;
+ }
+
+ fprintf(stderr, "unknown cipher %s\n", cipher);
+ exit(1);
+}
+
+static void privkey_info_int(FILE *outfile, common_info_st * cinfo,
+ gnutls_x509_privkey_t key)
+{
+ int ret, key_type;
+ unsigned int bits = 0;
+ size_t size;
+ const char *cprint;
+
+ /* Public key algorithm
+ */
+ fprintf(outfile, "Public Key Info:\n");
+ ret = gnutls_x509_privkey_get_pk_algorithm2(key, &bits);
+ fprintf(outfile, "\tPublic Key Algorithm: ");
+
+ key_type = ret;
+
+ cprint = gnutls_pk_algorithm_get_name(key_type);
+ fprintf(outfile, "%s\n", cprint ? cprint : "Unknown");
+ fprintf(outfile, "\tKey Security Level: %s (%u bits)\n\n",
+ gnutls_sec_param_get_name(gnutls_x509_privkey_sec_param
+ (key)), bits);
+
+ /* Print the raw public and private keys
+ */
+ if (key_type == GNUTLS_PK_RSA) {
+ gnutls_datum_t m, e, d, p, q, u, exp1, exp2;
+
+ ret =
+ gnutls_x509_privkey_export_rsa_raw2(key, &m, &e, &d,
+ &p, &q, &u, &exp1,
+ &exp2);
+ if (ret < 0)
+ fprintf(stderr,
+ "Error in key RSA data export: %s\n",
+ gnutls_strerror(ret));
+ else {
+ print_rsa_pkey(outfile, &m, &e, &d, &p, &q, &u,
+ &exp1, &exp2, cinfo->cprint);
+
+ gnutls_free(m.data);
+ gnutls_free(e.data);
+ gnutls_free(d.data);
+ gnutls_free(p.data);
+ gnutls_free(q.data);
+ gnutls_free(u.data);
+ gnutls_free(exp1.data);
+ gnutls_free(exp2.data);
+ }
+ } else if (key_type == GNUTLS_PK_DSA) {
+ gnutls_datum_t p, q, g, y, x;
+
+ ret =
+ gnutls_x509_privkey_export_dsa_raw(key, &p, &q, &g, &y,
+ &x);
+ if (ret < 0)
+ fprintf(stderr,
+ "Error in key DSA data export: %s\n",
+ gnutls_strerror(ret));
+ else {
+ print_dsa_pkey(outfile, &x, &y, &p, &q, &g,
+ cinfo->cprint);
+
+ gnutls_free(x.data);
+ gnutls_free(y.data);
+ gnutls_free(p.data);
+ gnutls_free(q.data);
+ gnutls_free(g.data);
+ }
+ } else if (key_type == GNUTLS_PK_EC) {
+ gnutls_datum_t y, x, k;
+ gnutls_ecc_curve_t curve;
+
+ ret =
+ gnutls_x509_privkey_export_ecc_raw(key, &curve, &x, &y,
+ &k);
+ if (ret < 0)
+ fprintf(stderr,
+ "Error in key ECC data export: %s\n",
+ gnutls_strerror(ret));
+ else {
+ cprint = gnutls_ecc_curve_get_name(curve);
+ bits = 0;
+
+ print_ecc_pkey(outfile, curve, &k, &x, &y,
+ cinfo->cprint);
+
+ gnutls_free(x.data);
+ gnutls_free(y.data);
+ gnutls_free(k.data);
+ }
+ }
+
+ fprintf(outfile, "\n");
+
+ size = lbuffer_size;
+ ret = gnutls_x509_privkey_get_seed(key, NULL, lbuffer, &size);
+ if (ret >= 0) {
+ fprintf(outfile, "Seed: %s\n",
+ raw_to_string(lbuffer, size));
+ }
+
+ size = lbuffer_size;
+ if ((ret =
+ gnutls_x509_privkey_get_key_id(key, GNUTLS_KEYID_USE_SHA1, lbuffer, &size)) < 0) {
+ fprintf(stderr, "Error in key id calculation: %s\n",
+ gnutls_strerror(ret));
+ } else {
+ gnutls_datum_t art;
+
+ fprintf(outfile, "Public Key ID: %s\n",
+ raw_to_string(lbuffer, size));
+
+ ret =
+ gnutls_random_art(GNUTLS_RANDOM_ART_OPENSSH, cprint,
+ bits, lbuffer, size, &art);
+ if (ret >= 0) {
+ fprintf(outfile, "Public key's random art:\n%s\n",
+ art.data);
+ gnutls_free(art.data);
+ }
+
+ }
+ fprintf(outfile, "\n");
+
+}
+
+void
+print_private_key(FILE *outfile, common_info_st * cinfo, gnutls_x509_privkey_t key)
+{
+ int ret;
+ size_t size;
+
+ if (!key)
+ return;
+
+ if (!cinfo->pkcs8) {
+ /* Only print private key parameters when an unencrypted
+ * format is used */
+ if (cinfo->outcert_format == GNUTLS_X509_FMT_PEM)
+ privkey_info_int(outfile, cinfo, key);
+
+ size = lbuffer_size;
+ ret = gnutls_x509_privkey_export(key, cinfo->outcert_format,
+ lbuffer, &size);
+ if (ret < 0) {
+ fprintf(stderr, "privkey_export: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (cinfo->no_compat == 0 && gnutls_x509_privkey_get_seed(key, NULL, NULL, 0) != GNUTLS_E_INVALID_REQUEST) {
+ gnutls_x509_privkey_set_flags(key, GNUTLS_PRIVKEY_FLAG_EXPORT_COMPAT);
+
+ fwrite(lbuffer, 1, size, outfile);
+
+ size = lbuffer_size;
+ ret = gnutls_x509_privkey_export(key, cinfo->outcert_format,
+ lbuffer, &size);
+ if (ret < 0) {
+ fprintf(stderr, "privkey_export: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+ }
+
+ } else {
+ unsigned int flags = 0;
+ const char *pass;
+
+ pass = get_password(cinfo, &flags, 0);
+ flags |= cipher_to_flags(cinfo->pkcs_cipher);
+
+ size = lbuffer_size;
+ ret =
+ gnutls_x509_privkey_export_pkcs8(key, cinfo->outcert_format,
+ pass, flags, lbuffer,
+ &size);
+ if (ret < 0) {
+ fprintf(stderr, "privkey_export_pkcs8: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+ }
+
+ fwrite(lbuffer, 1, size, outfile);
+}
+
/* If how is zero then the included parameters are used.
*/
int generate_prime(FILE * outfile, int how, common_info_st * info)
@@ -1062,12 +1278,50 @@ int generate_prime(FILE * outfile, int how, common_info_st * info)
fprintf(stderr, "Retrieving DH parameters...\n");
if (how != 0) {
- ret = gnutls_dh_params_generate2(dh_params, bits);
- if (ret < 0) {
- fprintf(stderr,
- "Error generating parameters: %s\n",
- gnutls_strerror(ret));
- exit(1);
+ if (info->provable != 0) {
+ gnutls_x509_privkey_t pkey;
+ unsigned save;
+
+ ret = gnutls_x509_privkey_init(&pkey);
+ if (ret < 0) {
+ fprintf(stderr,
+ "Error initializing key: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_x509_privkey_generate(pkey, GNUTLS_PK_DSA, bits, GNUTLS_PRIVKEY_FLAG_PROVABLE);
+ if (ret < 0) {
+ fprintf(stderr,
+ "Error generating DSA parameters: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (info->outcert_format == GNUTLS_X509_FMT_PEM) {
+ save = info->no_compat;
+ info->no_compat = 1;
+ print_private_key(outfile, info, pkey);
+ info->no_compat = save;
+ }
+
+ ret = gnutls_dh_params_import_dsa(dh_params, pkey);
+ if (ret < 0) {
+ fprintf(stderr,
+ "Error importing DSA parameters: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_x509_privkey_deinit(pkey);
+ } else {
+ ret = gnutls_dh_params_generate2(dh_params, bits);
+ if (ret < 0) {
+ fprintf(stderr,
+ "Error generating parameters: %s\n",
+ gnutls_strerror(ret));
+ exit(1);
+ }
}
ret =
@@ -1080,6 +1334,11 @@ int generate_prime(FILE * outfile, int how, common_info_st * info)
}
} else {
#ifdef ENABLE_SRP
+ if (info->provable != 0) {
+ fprintf(stderr, "The DH parameters obtained via this option are not provable\n");
+ exit(1);
+ }
+
if (bits <= 1024) {
p = gnutls_srp_1024_group_prime;
g = gnutls_srp_1024_group_generator;
diff --git a/src/certtool-common.h b/src/certtool-common.h
index 1ba6b10fce..8bd5355bce 100644
--- a/src/certtool-common.h
+++ b/src/certtool-common.h
@@ -67,8 +67,15 @@ typedef struct common_info {
/* when printing PKCS #11 objects, only print urls */
unsigned int only_urls;
unsigned int verbose;
+
+ /* set to non zero when no compatibility structs need to be exported */
+ unsigned no_compat;
} common_info_st;
+int cipher_to_flags(const char *cipher);
+
+void
+print_private_key(FILE *outfile, common_info_st * cinfo, gnutls_x509_privkey_t key);
gnutls_pubkey_t load_public_key_or_import(int mand,
gnutls_privkey_t privkey,
common_info_st * info);
diff --git a/src/certtool.c b/src/certtool.c
index dd410b6569..22dada32ca 100644
--- a/src/certtool.c
+++ b/src/certtool.c
@@ -52,7 +52,6 @@
static FILE *stdlog = NULL;
-static void privkey_info_int(common_info_st *, gnutls_x509_privkey_t key);
static void print_crl_info(gnutls_x509_crl_t crl, FILE * out);
void pkcs7_info(common_info_st *);
void pkcs7_sign(common_info_st *, unsigned embed);
@@ -195,95 +194,6 @@ generate_private_key_int(common_info_st * cinfo)
return key;
}
-static int cipher_to_flags(const char *cipher)
-{
- if (cipher == NULL) {
-#ifdef ENABLE_FIPS140
- return GNUTLS_PKCS_USE_PBES2_AES_128;
-#else /* compatibility mode - most implementations don't support PBES2 with AES */
- return GNUTLS_PKCS_USE_PKCS12_3DES;
-#endif
- } else if (strcasecmp(cipher, "3des") == 0) {
- return GNUTLS_PKCS_USE_PBES2_3DES;
- } else if (strcasecmp(cipher, "3des-pkcs12") == 0) {
- return GNUTLS_PKCS_USE_PKCS12_3DES;
- } else if (strcasecmp(cipher, "arcfour") == 0) {
- return GNUTLS_PKCS_USE_PKCS12_ARCFOUR;
- } else if (strcasecmp(cipher, "aes-128") == 0) {
- return GNUTLS_PKCS_USE_PBES2_AES_128;
- } else if (strcasecmp(cipher, "aes-192") == 0) {
- return GNUTLS_PKCS_USE_PBES2_AES_192;
- } else if (strcasecmp(cipher, "aes-256") == 0) {
- return GNUTLS_PKCS_USE_PBES2_AES_256;
- } else if (strcasecmp(cipher, "rc2-40") == 0) {
- return GNUTLS_PKCS_USE_PKCS12_RC2_40;
- }
-
- fprintf(stderr, "unknown cipher %s\n", cipher);
- exit(1);
-}
-
-
-static void
-print_private_key(common_info_st * cinfo, gnutls_x509_privkey_t key)
-{
- int ret;
- size_t size;
-
- if (!key)
- return;
-
- if (!cinfo->pkcs8) {
- /* Only print private key parameters when an unencrypted
- * format is used */
- if (outcert_format == GNUTLS_X509_FMT_PEM)
- privkey_info_int(cinfo, key);
-
- size = lbuffer_size;
- ret = gnutls_x509_privkey_export(key, outcert_format,
- lbuffer, &size);
- if (ret < 0) {
- fprintf(stderr, "privkey_export: %s\n",
- gnutls_strerror(ret));
- exit(1);
- }
-
- if (gnutls_x509_privkey_get_seed(key, NULL, NULL, 0) != GNUTLS_E_INVALID_REQUEST) {
- gnutls_x509_privkey_set_flags(key, GNUTLS_PRIVKEY_FLAG_EXPORT_COMPAT);
-
- fwrite(lbuffer, 1, size, outfile);
-
- size = lbuffer_size;
- ret = gnutls_x509_privkey_export(key, outcert_format,
- lbuffer, &size);
- if (ret < 0) {
- fprintf(stderr, "privkey_export: %s\n",
- gnutls_strerror(ret));
- exit(1);
- }
- }
-
- } else {
- unsigned int flags = 0;
- const char *pass;
-
- pass = get_password(cinfo, &flags, 0);
- flags |= cipher_to_flags(cinfo->pkcs_cipher);
-
- size = lbuffer_size;
- ret =
- gnutls_x509_privkey_export_pkcs8(key, outcert_format,
- pass, flags, lbuffer,
- &size);
- if (ret < 0) {
- fprintf(stderr, "privkey_export_pkcs8: %s\n",
- gnutls_strerror(ret));
- exit(1);
- }
- }
-
- fwrite(lbuffer, 1, size, outfile);
-}
static void generate_private_key(common_info_st * cinfo)
{
@@ -291,7 +201,7 @@ static void generate_private_key(common_info_st * cinfo)
key = generate_private_key_int(cinfo);
- print_private_key(cinfo, key);
+ print_private_key(outfile, cinfo, key);
gnutls_x509_privkey_deinit(key);
}
@@ -1944,132 +1854,6 @@ void crq_info(void)
gnutls_x509_crq_deinit(crq);
}
-static void privkey_info_int(common_info_st * cinfo,
- gnutls_x509_privkey_t key)
-{
- int ret, key_type;
- unsigned int bits = 0;
- size_t size;
- const char *cprint;
-
- /* Public key algorithm
- */
- fprintf(outfile, "Public Key Info:\n");
- ret = gnutls_x509_privkey_get_pk_algorithm2(key, &bits);
- fprintf(outfile, "\tPublic Key Algorithm: ");
-
- key_type = ret;
-
- cprint = gnutls_pk_algorithm_get_name(key_type);
- fprintf(outfile, "%s\n", cprint ? cprint : "Unknown");
- fprintf(outfile, "\tKey Security Level: %s (%u bits)\n\n",
- gnutls_sec_param_get_name(gnutls_x509_privkey_sec_param
- (key)), bits);
-
- /* Print the raw public and private keys
- */
- if (key_type == GNUTLS_PK_RSA) {
- gnutls_datum_t m, e, d, p, q, u, exp1, exp2;
-
- ret =
- gnutls_x509_privkey_export_rsa_raw2(key, &m, &e, &d,
- &p, &q, &u, &exp1,
- &exp2);
- if (ret < 0)
- fprintf(stderr,
- "Error in key RSA data export: %s\n",
- gnutls_strerror(ret));
- else {
- print_rsa_pkey(outfile, &m, &e, &d, &p, &q, &u,
- &exp1, &exp2, HAVE_OPT(CPRINT));
-
- gnutls_free(m.data);
- gnutls_free(e.data);
- gnutls_free(d.data);
- gnutls_free(p.data);
- gnutls_free(q.data);
- gnutls_free(u.data);
- gnutls_free(exp1.data);
- gnutls_free(exp2.data);
- }
- } else if (key_type == GNUTLS_PK_DSA) {
- gnutls_datum_t p, q, g, y, x;
-
- ret =
- gnutls_x509_privkey_export_dsa_raw(key, &p, &q, &g, &y,
- &x);
- if (ret < 0)
- fprintf(stderr,
- "Error in key DSA data export: %s\n",
- gnutls_strerror(ret));
- else {
- print_dsa_pkey(outfile, &x, &y, &p, &q, &g,
- HAVE_OPT(CPRINT));
-
- gnutls_free(x.data);
- gnutls_free(y.data);
- gnutls_free(p.data);
- gnutls_free(q.data);
- gnutls_free(g.data);
- }
- } else if (key_type == GNUTLS_PK_EC) {
- gnutls_datum_t y, x, k;
- gnutls_ecc_curve_t curve;
-
- ret =
- gnutls_x509_privkey_export_ecc_raw(key, &curve, &x, &y,
- &k);
- if (ret < 0)
- fprintf(stderr,
- "Error in key ECC data export: %s\n",
- gnutls_strerror(ret));
- else {
- cprint = gnutls_ecc_curve_get_name(curve);
- bits = 0;
-
- print_ecc_pkey(outfile, curve, &k, &x, &y,
- HAVE_OPT(CPRINT));
-
- gnutls_free(x.data);
- gnutls_free(y.data);
- gnutls_free(k.data);
- }
- }
-
- fprintf(outfile, "\n");
-
- size = lbuffer_size;
- ret = gnutls_x509_privkey_get_seed(key, NULL, lbuffer, &size);
- if (ret >= 0) {
- fprintf(outfile, "Seed: %s\n",
- raw_to_string(lbuffer, size));
- }
-
- size = lbuffer_size;
- if ((ret =
- gnutls_x509_privkey_get_key_id(key, GNUTLS_KEYID_USE_SHA1, lbuffer, &size)) < 0) {
- fprintf(stderr, "Error in key id calculation: %s\n",
- gnutls_strerror(ret));
- } else {
- gnutls_datum_t art;
-
- fprintf(outfile, "Public Key ID: %s\n",
- raw_to_string(lbuffer, size));
-
- ret =
- gnutls_random_art(GNUTLS_RANDOM_ART_OPENSSH, cprint,
- bits, lbuffer, size, &art);
- if (ret >= 0) {
- fprintf(outfile, "Public key's random art:\n%s\n",
- art.data);
- gnutls_free(art.data);
- }
-
- }
- fprintf(outfile, "\n");
-
-}
-
void privkey_info(common_info_st * cinfo)
{
gnutls_x509_privkey_t key;
@@ -2110,7 +1894,7 @@ void privkey_info(common_info_st * cinfo)
* to our format. */
cinfo->pkcs8 = 0;
- print_private_key(cinfo, key);
+ print_private_key(outfile, cinfo, key);
ret = gnutls_x509_privkey_verify_params(key);
if (ret < 0)
@@ -2155,7 +1939,7 @@ void generate_request(common_info_st * cinfo)
xkey = generate_private_key_int(cinfo);
- print_private_key(cinfo, xkey);
+ print_private_key(outfile, cinfo, xkey);
ret =
gnutls_privkey_import_x509(pkey, xkey,
diff --git a/src/common.h b/src/common.h
index 4024d5455e..7c14434b95 100644
--- a/src/common.h
+++ b/src/common.h
@@ -18,6 +18,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#ifndef INCLUDE_COMMON_H
+# define INCLUDE_COMMON_H
+
#define SERVER "127.0.0.1"
#include <config.h>
@@ -126,3 +129,5 @@ void set_read_funcs(gnutls_session_t session)
#else
# define set_read_funcs(x)
#endif
+
+#endif