]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Make private exponent optional in gnutls_privkey_import_rsa_raw().
authorNikolay Sivov <nsivov@codeweavers.com>
Sun, 6 Sep 2020 20:42:33 +0000 (23:42 +0300)
committerNikolay Sivov <nsivov@codeweavers.com>
Sun, 6 Sep 2020 20:43:30 +0000 (23:43 +0300)
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
lib/nettle/pk.c
lib/privkey_raw.c
lib/x509/privkey.c
tests/key-import-export.c

index 1a30607a6782e14565debe337ef88542969e2a52..0c91aac493577bf492c622217b6c651bd3038500 100644 (file)
@@ -3306,6 +3306,37 @@ fail:
        return ret;
 }
 
+static int calc_rsa_priv(gnutls_pk_params_st * params)
+{
+       bigint_t lcm, p1, q1;
+       int ret;
+
+       params->params[RSA_PRIV] = NULL;
+
+       ret = _gnutls_mpi_init_multi(&params->params[RSA_PRIV], &lcm, &p1, &q1, NULL);
+       if (ret < 0)
+               return gnutls_assert_val(ret);
+
+       /* lcm(p - 1, q - 1) */
+       mpz_sub_ui(p1, params->params[RSA_PRIME1], 1);
+       mpz_sub_ui(q1, params->params[RSA_PRIME2], 1);
+       mpz_lcm(lcm, p1, q1);
+
+       zrelease_mpi_key(&p1);
+       zrelease_mpi_key(&q1);
+
+       /* d = e^{-1} (mod lcm) */
+       ret = mpz_invert(params->params[RSA_PRIV], params->params[RSA_PUB], lcm);
+
+       zrelease_mpi_key(&lcm);
+
+       if (ret == 0) {
+               zrelease_mpi_key(&params->params[RSA_PRIV]);
+               return GNUTLS_E_INVALID_REQUEST;
+       }
+
+       return 0;
+}
 
 static int
 wrap_nettle_pk_fixup(gnutls_pk_algorithm_t algo,
@@ -3320,6 +3351,13 @@ wrap_nettle_pk_fixup(gnutls_pk_algorithm_t algo,
        if (algo == GNUTLS_PK_RSA) {
                struct rsa_private_key priv;
 
+               if (params->params[RSA_PRIV] == NULL) {
+                       ret = calc_rsa_priv(params);
+                       if (ret < 0)
+                               return gnutls_assert_val(ret);
+                       params->params_nr++;
+               }
+
                /* do not trust the generated values. Some old private keys
                 * generated by us have mess on the values. Those were very
                 * old but it seemed some of the shipped example private
index 5f1dc8c26ce7b95570fc1dc4c9bc40e718cfa5a4..27327fc6d129cdff19218e14dbae026bc7a76dc6 100644 (file)
@@ -324,7 +324,7 @@ gnutls_privkey_export_gost_raw2(gnutls_privkey_t key,
  * @key: The structure to store the parsed key
  * @m: holds the modulus
  * @e: holds the public exponent
- * @d: holds the private exponent
+ * @d: holds the private exponent (optional)
  * @p: holds the first prime (p)
  * @q: holds the second prime (q)
  * @u: holds the coefficient (optional)
index 3852064648fd3c53bf1c6447809921623b16427a..020453cc1797f797f9e30ba5b0192b302cb68331 100644 (file)
@@ -900,13 +900,15 @@ gnutls_x509_privkey_import_rsa_raw2(gnutls_x509_privkey_t key,
        }
        key->params.params_nr++;
 
-       siz = d->size;
-       if (_gnutls_mpi_init_scan_nz(&key->params.params[RSA_PRIV], d->data, siz)) {
-               gnutls_assert();
-               ret = GNUTLS_E_MPI_SCAN_FAILED;
-               goto cleanup;
+       if (d) {
+               siz = d->size;
+               if (_gnutls_mpi_init_scan_nz(&key->params.params[RSA_PRIV], d->data, siz)) {
+                       gnutls_assert();
+                       ret = GNUTLS_E_MPI_SCAN_FAILED;
+                       goto cleanup;
+               }
+               key->params.params_nr++;
        }
-       key->params.params_nr++;
 
        siz = p->size;
        if (_gnutls_mpi_init_scan_nz(&key->params.params[RSA_PRIME1], p->data, siz)) {
index e28b21a4f25685360f5aeadc7ec840dc449b7b86..fc6c25e6a70959116e38ad06691293e6aa9e1e0f 100644 (file)
@@ -367,6 +367,38 @@ int check_privkey_import_export(void)
                gnutls_privkey_deinit(key);
        }
 
+       /* Optional private exponent */
+       ret = gnutls_privkey_init(&key);
+       if (ret < 0)
+               fail("error\n");
+
+       ret = gnutls_privkey_import_rsa_raw(key, &_rsa_m, &_rsa_e, NULL, &_rsa_p, &_rsa_q, NULL, NULL, NULL);
+       if (ret < 0)
+               fail("error\n");
+
+       ret = gnutls_privkey_export_rsa_raw2(key, &m, &e, &d, &p, &q, &u, &e1, &e2, 0);
+       if (ret < 0)
+               fail("error\n");
+
+       CMP("m", &m, rsa_m);
+       CMP("e", &e, rsa_e);
+       CMP("d", &d, rsa_d);
+       CMP("p", &p, rsa_p);
+       CMP("q", &q, rsa_q);
+       CMP("u", &u, rsa_u);
+       CMP("e1", &e1, rsa_e1);
+       CMP("e2", &e2, rsa_e2);
+       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(e1.data);
+       gnutls_free(e2.data);
+
+       gnutls_privkey_deinit(key);
+
        ret = gnutls_privkey_init(&key);
        if (ret < 0)
                fail("error\n");