]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
gnutls_privkey_generate2: accept DH parameters
authorDaiki Ueno <ueno@gnu.org>
Thu, 31 Aug 2023 00:21:23 +0000 (09:21 +0900)
committerDaiki Ueno <ueno@gnu.org>
Thu, 31 Aug 2023 12:39:46 +0000 (21:39 +0900)
This adds a new GNUTLS_KEYGEN_DH type for gnutls_keygen_data_st, so
gnutls_privkey_generate2 can use pre-generated DH parameters instead
of newly generated ones.

Signed-off-by: Daiki Ueno <ueno@gnu.org>
lib/includes/gnutls/x509.h
lib/x509/key_encode.c
lib/x509/privkey.c

index 08ee980f73ea56d7438562a67ba3da7bc608c647..af1127a4dcf81110c4733b0e26c7473dc25b9767 100644 (file)
@@ -1145,13 +1145,15 @@ void gnutls_x509_privkey_set_flags(gnutls_x509_privkey_t key,
  * @GNUTLS_KEYGEN_SEED: Specifies the seed to be used in key generation.
  * @GNUTLS_KEYGEN_DIGEST: The size field specifies the hash algorithm to be used in key generation.
  * @GNUTLS_KEYGEN_SPKI: data points to a %gnutls_x509_spki_t structure; it is not used after the key generation call.
+ * @GNUTLS_KEYGEN_DH: data points to a %gnutls_dh_params_t structure; it is not used after the key generation call.
  *
  * Enumeration of different key generation data options.
  */
 typedef enum {
        GNUTLS_KEYGEN_SEED = 1,
        GNUTLS_KEYGEN_DIGEST = 2,
-       GNUTLS_KEYGEN_SPKI = 3
+       GNUTLS_KEYGEN_SPKI = 3,
+       GNUTLS_KEYGEN_DH = 4
 } gnutls_keygen_types_t;
 
 typedef struct {
index 0d26d3ce36e7e5ce4d04c107fe1bd23e608d174a..4de02b244c4e944f4dce233d4465c0e4228e37f1 100644 (file)
@@ -1032,6 +1032,9 @@ int _gnutls_asn1_encode_privkey(asn1_node *c2, gnutls_pk_params_st *params)
        case GNUTLS_PK_GOST_12_256:
        case GNUTLS_PK_GOST_12_512:
                return _gnutls_asn1_encode_gost(c2, params);
+       case GNUTLS_PK_DH:
+               /* DH keys are only exportable in PKCS#8 format */
+               return GNUTLS_E_INVALID_REQUEST;
        default:
                return GNUTLS_E_UNIMPLEMENTED_FEATURE;
        }
index 1a0f688027ee870707bac95c1768a18eb53d54e3..a7804ccabef33ede9776d234c38ef939b712a953 100644 (file)
@@ -1780,7 +1780,8 @@ int gnutls_x509_privkey_generate2(gnutls_x509_privkey_t key,
 {
        int ret;
        unsigned i;
-       gnutls_x509_spki_t tpki = NULL;
+       gnutls_x509_spki_t spki = NULL;
+       gnutls_dh_params_t dh_params = NULL;
 
        if (key == NULL) {
                gnutls_assert();
@@ -1790,14 +1791,27 @@ int gnutls_x509_privkey_generate2(gnutls_x509_privkey_t key,
        gnutls_pk_params_init(&key->params);
 
        for (i = 0; i < data_size; i++) {
-               if (data[i].type == GNUTLS_KEYGEN_SEED &&
-                   data[i].size < sizeof(key->params.seed)) {
-                       key->params.seed_size = data[i].size;
-                       memcpy(key->params.seed, data[i].data, data[i].size);
-               } else if (data[i].type == GNUTLS_KEYGEN_DIGEST) {
+               switch (data[i].type) {
+               case GNUTLS_KEYGEN_SEED:
+                       if (data[i].size < sizeof(key->params.seed)) {
+                               key->params.seed_size = data[i].size;
+                               memcpy(key->params.seed, data[i].data,
+                                      data[i].size);
+                       }
+                       break;
+               case GNUTLS_KEYGEN_DIGEST:
                        key->params.palgo = data[i].size;
-               } else if (data[i].type == GNUTLS_KEYGEN_SPKI) {
-                       tpki = (void *)data[i].data;
+                       break;
+               case GNUTLS_KEYGEN_SPKI:
+                       spki = (void *)data[i].data;
+                       break;
+               case GNUTLS_KEYGEN_DH:
+                       if (algo != GNUTLS_PK_DH) {
+                               return gnutls_assert_val(
+                                       GNUTLS_E_INVALID_REQUEST);
+                       }
+                       dh_params = (void *)data[i].data;
+                       break;
                }
        }
 
@@ -1841,10 +1855,22 @@ int gnutls_x509_privkey_generate2(gnutls_x509_privkey_t key,
 
        key->params.algo = algo;
 
-       ret = _gnutls_pk_generate_params(algo, bits, &key->params);
-       if (ret < 0) {
-               gnutls_assert();
-               return ret;
+       /* DH params are given, no need to regenerate */
+       if (algo == GNUTLS_PK_DH && dh_params != NULL) {
+               key->params.params[DH_P] =
+                       _gnutls_mpi_copy(dh_params->params[0]);
+               key->params.params[DH_Q] =
+                       _gnutls_mpi_copy(dh_params->params[2]);
+               key->params.params[DH_G] =
+                       _gnutls_mpi_copy(dh_params->params[1]);
+               /* X and Y will be added by _gnutls_pk_generate_keys */
+               key->params.params_nr = 3;
+       } else {
+               ret = _gnutls_pk_generate_params(algo, bits, &key->params);
+               if (ret < 0) {
+                       gnutls_assert();
+                       return ret;
+               }
        }
 
        if (algo == GNUTLS_PK_RSA_PSS && (flags & GNUTLS_PRIVKEY_FLAG_CA) &&
@@ -1883,18 +1909,21 @@ int gnutls_x509_privkey_generate2(gnutls_x509_privkey_t key,
                goto cleanup;
        }
 
-       if (tpki) {
-               ret = gnutls_x509_privkey_set_spki(key, tpki, 0);
+       if (spki) {
+               ret = gnutls_x509_privkey_set_spki(key, spki, 0);
                if (ret < 0) {
                        gnutls_assert();
                        goto cleanup;
                }
        }
 
-       ret = _gnutls_asn1_encode_privkey(&key->key, &key->params);
-       if (ret < 0) {
-               gnutls_assert();
-               goto cleanup;
+       /* DH keys are only exportable in PKCS#8 format */
+       if (algo != GNUTLS_PK_DH) {
+               ret = _gnutls_asn1_encode_privkey(&key->key, &key->params);
+               if (ret < 0) {
+                       gnutls_assert();
+                       goto cleanup;
+               }
        }
 
        return 0;