summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <ueno@gnu.org>2020-09-20 15:34:26 +0000
committerDaiki Ueno <ueno@gnu.org>2020-09-20 15:34:26 +0000
commita431b6e3c032fa47ecc3c233babcad602056b892 (patch)
tree0bef17baa89b1d5e1b51bc7d42353c62bd8f3b18
parent5666374674f96e9e69d0c34c3a27318a4a90005d (diff)
parent81b0a397a3382bb7257a39cc886b1a1f7607c072 (diff)
downloadgnutls-a431b6e3c032fa47ecc3c233babcad602056b892.tar.gz
Merge branch 'rsa_privkey_prive' into 'master'
Make private exponent optional in gnutls_privkey_import_rsa_raw() See merge request gnutls/gnutls!1323
-rw-r--r--lib/nettle/pk.c66
-rw-r--r--lib/privkey_raw.c2
-rw-r--r--lib/x509/privkey.c14
-rw-r--r--tests/key-import-export.c32
4 files changed, 93 insertions, 21 deletions
diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
index e9a380857c..0c91aac493 100644
--- a/lib/nettle/pk.c
+++ b/lib/nettle/pk.c
@@ -146,12 +146,12 @@ static void
_rsa_params_to_privkey(const gnutls_pk_params_st * pk_params,
struct rsa_private_key *priv)
{
- memcpy(priv->d, pk_params->params[2], SIZEOF_MPZT);
- memcpy(priv->p, pk_params->params[3], SIZEOF_MPZT);
- memcpy(priv->q, pk_params->params[4], SIZEOF_MPZT);
- memcpy(priv->c, pk_params->params[5], SIZEOF_MPZT);
- memcpy(priv->a, pk_params->params[6], SIZEOF_MPZT);
- memcpy(priv->b, pk_params->params[7], SIZEOF_MPZT);
+ memcpy(priv->d, pk_params->params[RSA_PRIV], SIZEOF_MPZT);
+ memcpy(priv->p, pk_params->params[RSA_PRIME1], SIZEOF_MPZT);
+ memcpy(priv->q, pk_params->params[RSA_PRIME2], SIZEOF_MPZT);
+ memcpy(priv->c, pk_params->params[RSA_COEF], SIZEOF_MPZT);
+ memcpy(priv->a, pk_params->params[RSA_E1], SIZEOF_MPZT);
+ memcpy(priv->b, pk_params->params[RSA_E2], SIZEOF_MPZT);
/* we do not rsa_private_key_prepare() because it involves a multiplication.
* we call it once when we import the parameters */
priv->size =
@@ -2511,14 +2511,14 @@ wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo,
params->params_nr++;
}
- mpz_set(TOMPZ(params->params[0]), pub.n);
- mpz_set(TOMPZ(params->params[1]), pub.e);
- mpz_set(TOMPZ(params->params[2]), priv.d);
- mpz_set(TOMPZ(params->params[3]), priv.p);
- mpz_set(TOMPZ(params->params[4]), priv.q);
- mpz_set(TOMPZ(params->params[5]), priv.c);
- mpz_set(TOMPZ(params->params[6]), priv.a);
- mpz_set(TOMPZ(params->params[7]), priv.b);
+ mpz_set(TOMPZ(params->params[RSA_MODULUS]), pub.n);
+ mpz_set(TOMPZ(params->params[RSA_PUB]), pub.e);
+ mpz_set(TOMPZ(params->params[RSA_PRIV]), priv.d);
+ mpz_set(TOMPZ(params->params[RSA_PRIME1]), priv.p);
+ mpz_set(TOMPZ(params->params[RSA_PRIME2]), priv.q);
+ mpz_set(TOMPZ(params->params[RSA_COEF]), priv.c);
+ mpz_set(TOMPZ(params->params[RSA_E1]), priv.a);
+ mpz_set(TOMPZ(params->params[RSA_E2]), priv.b);
ret = 0;
@@ -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
diff --git a/lib/privkey_raw.c b/lib/privkey_raw.c
index 5f1dc8c26c..27327fc6d1 100644
--- a/lib/privkey_raw.c
+++ b/lib/privkey_raw.c
@@ -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)
diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c
index 3852064648..020453cc17 100644
--- a/lib/x509/privkey.c
+++ b/lib/x509/privkey.c
@@ -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)) {
diff --git a/tests/key-import-export.c b/tests/key-import-export.c
index e28b21a4f2..fc6c25e6a7 100644
--- a/tests/key-import-export.c
+++ b/tests/key-import-export.c
@@ -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");