]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
certtool: the --generate-dh-params option can be combined with --provable
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Thu, 11 Feb 2016 10:00:15 +0000 (11:00 +0100)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Thu, 11 Feb 2016 10:08:27 +0000 (11:08 +0100)
This however, will generate provable DSA parameters and import them
as DH parameters.

Resolves #72

src/Makefile.am
src/certtool-common.c
src/certtool-common.h
src/certtool.c
src/common.h

index 162664cba15cb041d0ab9e797be69aaf5316da1c..1901a767099bc9f8426e223c7e82710d59f8bf7e 100644 (file)
@@ -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)
index 63e4f1f93666339da4e616575e9e4f79012b48d9..6729681d187ada7cf2ffc4f83459422c488a90a3 100644 (file)
@@ -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;
index 1ba6b10fce721a73d478c00db441668a8afb8e37..8bd5355bce5da817279f492cdae73482f47626c0 100644 (file)
@@ -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);
index dd410b6569a860298231d28254a980d849fc21b9..22dada32ca5524d6819bc8f4849e9ec74585a02c 100644 (file)
@@ -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,
index 4024d5455e0cbbcfb6c706161307ae93e82f4e78..7c14434b9586016823f8a595b125259fc7463c26 100644 (file)
@@ -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