summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cipher/dsa.c40
-rw-r--r--cipher/ecc-common.h2
-rw-r--r--cipher/ecc-curves.c51
-rw-r--r--cipher/ecc.c134
-rw-r--r--cipher/elgamal.c43
-rw-r--r--cipher/pubkey-util.c12
-rw-r--r--cipher/pubkey.c480
-rw-r--r--cipher/rsa.c46
-rw-r--r--src/cipher-proto.h5
9 files changed, 218 insertions, 595 deletions
diff --git a/cipher/dsa.c b/cipher/dsa.c
index 3dfef07a..f86ff15e 100644
--- a/cipher/dsa.c
+++ b/cipher/dsa.c
@@ -928,27 +928,29 @@ dsa_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
static gcry_err_code_t
-dsa_check_secret_key (int algo, gcry_mpi_t *skey)
+dsa_check_secret_key (gcry_sexp_t keyparms)
{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
- DSA_secret_key sk;
+ gcry_err_code_t rc;
+ DSA_secret_key sk = {NULL, NULL, NULL, NULL, NULL};
- (void)algo;
+ rc = _gcry_pk_util_extract_mpis (keyparms, "pqgyx",
+ &sk.p, &sk.q, &sk.g, &sk.y, &sk.x,
+ NULL);
+ if (rc)
+ goto leave;
- if ((! skey[0]) || (! skey[1]) || (! skey[2]) || (! skey[3]) || (! skey[4]))
- err = GPG_ERR_BAD_MPI;
- else
- {
- sk.p = skey[0];
- sk.q = skey[1];
- sk.g = skey[2];
- sk.y = skey[3];
- sk.x = skey[4];
- if (! check_secret_key (&sk))
- err = GPG_ERR_BAD_SECKEY;
- }
+ if (!check_secret_key (&sk))
+ rc = GPG_ERR_BAD_SECKEY;
- return err;
+ leave:
+ gcry_mpi_release (sk.p);
+ gcry_mpi_release (sk.q);
+ gcry_mpi_release (sk.g);
+ gcry_mpi_release (sk.y);
+ gcry_mpi_release (sk.x);
+ if (DBG_CIPHER)
+ log_debug ("dsa_testkey => %s\n", gpg_strerror (rc));
+ return rc;
}
@@ -976,7 +978,7 @@ dsa_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
rc = _gcry_pk_util_extract_mpis (keyparms, "pqgyx",
&sk.p, &sk.q, &sk.g, &sk.y, &sk.x, NULL);
if (rc)
- return rc;
+ goto leave;
if (DBG_CIPHER)
{
log_mpidump ("dsa_sign p", sk.p);
@@ -1053,7 +1055,7 @@ dsa_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms)
rc = _gcry_pk_util_extract_mpis (s_keyparms, "pqgy",
&pk.p, &pk.q, &pk.g, &pk.y, NULL);
if (rc)
- return rc;
+ goto leave;
if (DBG_CIPHER)
{
log_mpidump ("dsa_verify p", pk.p);
diff --git a/cipher/ecc-common.h b/cipher/ecc-common.h
index cdb1362b..0be1f2c3 100644
--- a/cipher/ecc-common.h
+++ b/cipher/ecc-common.h
@@ -68,7 +68,7 @@ gpg_err_code_t _gcry_ecc_fill_in_curve (unsigned int nbits,
elliptic_curve_t *curve,
unsigned int *r_nbits);
-const char *_gcry_ecc_get_curve (gcry_mpi_t *pkey,
+const char *_gcry_ecc_get_curve (gcry_sexp_t keyparms,
int iterator,
unsigned int *r_nbits);
gcry_err_code_t _gcry_ecc_get_param (const char *name, gcry_mpi_t *pkey);
diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c
index 971dd322..53433a2c 100644
--- a/cipher/ecc-curves.c
+++ b/cipher/ecc-curves.c
@@ -26,8 +26,10 @@
#include "g10lib.h"
#include "mpi.h"
+#include "cipher.h"
#include "context.h"
#include "ec-context.h"
+#include "pubkey-internal.h"
#include "ecc-common.h"
@@ -405,18 +407,20 @@ _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name,
/* Return the name matching the parameters in PKEY. This works only
with curves described by the Weierstrass equation. */
const char *
-_gcry_ecc_get_curve (gcry_mpi_t *pkey, int iterator, unsigned int *r_nbits)
+_gcry_ecc_get_curve (gcry_sexp_t keyparms, int iterator, unsigned int *r_nbits)
{
- gpg_err_code_t err;
+ const char *result = NULL;
elliptic_curve_t E;
+ gcry_mpi_t mpi_g = NULL;
+ gcry_mpi_t tmp = NULL;
int idx;
- gcry_mpi_t tmp;
- const char *result = NULL;
+
+ memset (&E, 0, sizeof E);
if (r_nbits)
*r_nbits = 0;
- if (!pkey)
+ if (!keyparms)
{
idx = iterator;
if (idx >= 0 && idx < DIM (domain_parms))
@@ -428,23 +432,20 @@ _gcry_ecc_get_curve (gcry_mpi_t *pkey, int iterator, unsigned int *r_nbits)
return result;
}
- if (!pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] || !pkey[4])
- return NULL;
- E.model = MPI_EC_WEIERSTRASS;
- E.dialect = ECC_DIALECT_STANDARD;
- E.name = NULL;
- E.p = pkey[0];
- E.a = pkey[1];
- E.b = pkey[2];
- _gcry_mpi_point_init (&E.G);
- err = _gcry_ecc_os2ec (&E.G, pkey[3]);
- if (err)
+ /*
+ * Extract the curve parameters..
+ */
+ if (_gcry_pk_util_extract_mpis (keyparms, "-pabgn",
+ &E.p, &E.a, &E.b, &mpi_g, &E.n,
+ NULL))
+ goto leave;
+ if (mpi_g)
{
- _gcry_mpi_point_free_parts (&E.G);
- return NULL;
+ _gcry_mpi_point_init (&E.G);
+ if (_gcry_ecc_os2ec (&E.G, mpi_g))
+ goto leave;
}
- E.n = pkey[4];
for (idx = 0; domain_parms[idx].desc; idx++)
{
@@ -471,22 +472,26 @@ _gcry_ecc_get_curve (gcry_mpi_t *pkey, int iterator, unsigned int *r_nbits)
tmp = scanval (domain_parms[idx].g_y);
if (!mpi_cmp (tmp, E.G.y))
{
- mpi_free (tmp);
result = domain_parms[idx].desc;
if (r_nbits)
*r_nbits = domain_parms[idx].nbits;
- break;
+ goto leave;
}
}
}
}
}
}
- mpi_free (tmp);
}
+ leave:
+ gcry_mpi_release (tmp);
+ gcry_mpi_release (E.p);
+ gcry_mpi_release (E.a);
+ gcry_mpi_release (E.b);
+ gcry_mpi_release (mpi_g);
_gcry_mpi_point_free_parts (&E.G);
-
+ gcry_mpi_release (E.n);
return result;
}
diff --git a/cipher/ecc.c b/cipher/ecc.c
index 17724e82..bd4d2539 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -1397,66 +1397,106 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
static gcry_err_code_t
-ecc_check_secret_key (int algo, gcry_mpi_t *skey)
+ecc_check_secret_key (gcry_sexp_t keyparms)
{
- gpg_err_code_t err;
+ gcry_err_code_t rc;
+ gcry_sexp_t l1 = NULL;
+ char *curvename = NULL;
+ gcry_mpi_t mpi_g = NULL;
+ gcry_mpi_t mpi_q = NULL;
ECC_secret_key sk;
- (void)algo;
-
- /* FIXME: This check looks a bit fishy: Now long is the array? */
- if (!skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] || !skey[5]
- || !skey[6])
- return GPG_ERR_BAD_MPI;
+ memset (&sk, 0, sizeof sk);
- sk.E.model = MPI_EC_WEIERSTRASS;
- sk.E.p = skey[0];
- sk.E.a = skey[1];
- sk.E.b = skey[2];
- point_init (&sk.E.G);
- err = _gcry_ecc_os2ec (&sk.E.G, skey[3]);
- if (err)
+ /*
+ * Extract the key.
+ */
+ rc = _gcry_pk_util_extract_mpis (keyparms, "-p?a?b?g?n?/q?+d",
+ &sk.E.p, &sk.E.a, &sk.E.b, &mpi_g, &sk.E.n,
+ &mpi_q, &sk.d, NULL);
+ if (rc)
+ goto leave;
+ if (mpi_g)
+ {
+ point_init (&sk.E.G);
+ rc = _gcry_ecc_os2ec (&sk.E.G, mpi_g);
+ if (rc)
+ goto leave;
+ }
+ /* Add missing parameters using the optional curve parameter. */
+ gcry_sexp_release (l1);
+ l1 = gcry_sexp_find_token (keyparms, "curve", 5);
+ if (l1)
{
- point_free (&sk.E.G);
- return err;
+ curvename = gcry_sexp_nth_string (l1, 1);
+ if (curvename)
+ {
+ rc = _gcry_ecc_fill_in_curve (0, curvename, &sk.E, NULL);
+ if (rc)
+ return rc;
+ }
}
- sk.E.n = skey[4];
- point_init (&sk.Q);
- err = _gcry_ecc_os2ec (&sk.Q, skey[5]);
- if (err)
+ /* Guess required fields if a curve parameter has not been given.
+ FIXME: This is a crude hacks. We need to fix that. */
+ if (!curvename)
{
- point_free (&sk.E.G);
- point_free (&sk.Q);
- return err;
+ sk.E.model = MPI_EC_WEIERSTRASS;
+ sk.E.dialect = ECC_DIALECT_STANDARD;
+ }
+ if (DBG_CIPHER)
+ {
+ log_debug ("ecc_testkey inf: %s/%s\n",
+ _gcry_ecc_model2str (sk.E.model),
+ _gcry_ecc_dialect2str (sk.E.dialect));
+ if (sk.E.name)
+ log_debug ("ecc_testkey nam: %s\n", sk.E.name);
+ log_printmpi ("ecc_testkey p", sk.E.p);
+ log_printmpi ("ecc_testkey a", sk.E.a);
+ log_printmpi ("ecc_testkey b", sk.E.b);
+ log_printpnt ("ecc_testkey g", &sk.E.G, NULL);
+ log_printmpi ("ecc_testkey n", sk.E.n);
+ log_printmpi ("ecc_testkey q", mpi_q);
+ if (!fips_mode ())
+ log_printmpi ("ecc_testkey d", sk.d);
+ }
+ if (!sk.E.p || !sk.E.a || !sk.E.b || !sk.E.G.x || !sk.E.n || !sk.d)
+ {
+ rc = GPG_ERR_NO_OBJ;
+ goto leave;
}
- {
- const unsigned char *buf;
- unsigned int n;
-
- gcry_assert (mpi_is_opaque (skey[6]));
+ if (mpi_q)
+ {
+ point_init (&sk.Q);
+ rc = _gcry_ecc_os2ec (&sk.Q, mpi_q);
+ if (rc)
+ goto leave;
+ }
+ else
+ {
+ /* The current test requires Q. */
+ rc = GPG_ERR_NO_OBJ;
+ goto leave;
+ }
- buf = gcry_mpi_get_opaque (skey[6], &n);
- if (!buf)
- err = GPG_ERR_INV_OBJ;
- else
- {
- n = (n + 7)/8;
- sk.d = NULL;
- err = gcry_mpi_scan (&sk.d, GCRYMPI_FMT_USG, buf, n, NULL);
- if (!err)
- {
- if (check_secret_key (&sk))
- err = GPG_ERR_BAD_SECKEY;
- gcry_mpi_release (sk.d);
- sk.d = NULL;
- }
- }
- }
+ if (check_secret_key (&sk))
+ rc = GPG_ERR_BAD_SECKEY;
+ leave:
+ gcry_mpi_release (sk.E.p);
+ gcry_mpi_release (sk.E.a);
+ gcry_mpi_release (sk.E.b);
+ gcry_mpi_release (mpi_g);
point_free (&sk.E.G);
+ gcry_mpi_release (sk.E.n);
+ gcry_mpi_release (mpi_q);
point_free (&sk.Q);
- return err;
+ gcry_mpi_release (sk.d);
+ gcry_free (curvename);
+ gcry_sexp_release (l1);
+ if (DBG_CIPHER)
+ log_debug ("ecc_testkey => %s\n", gpg_strerror (rc));
+ return rc;
}
diff --git a/cipher/elgamal.c b/cipher/elgamal.c
index 7fedc7bf..691e122b 100644
--- a/cipher/elgamal.c
+++ b/cipher/elgamal.c
@@ -730,27 +730,28 @@ elg_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
static gcry_err_code_t
-elg_check_secret_key (int algo, gcry_mpi_t *skey)
+elg_check_secret_key (gcry_sexp_t keyparms)
{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
- ELG_secret_key sk;
-
- (void)algo;
+ gcry_err_code_t rc;
+ ELG_secret_key sk = {NULL, NULL, NULL, NULL};
- if ((! skey[0]) || (! skey[1]) || (! skey[2]) || (! skey[3]))
- err = GPG_ERR_BAD_MPI;
- else
- {
- sk.p = skey[0];
- sk.g = skey[1];
- sk.y = skey[2];
- sk.x = skey[3];
+ rc = _gcry_pk_util_extract_mpis (keyparms, "pgyx",
+ &sk.p, &sk.g, &sk.y, &sk.x,
+ NULL);
+ if (rc)
+ goto leave;
- if (! check_secret_key (&sk))
- err = GPG_ERR_BAD_SECKEY;
- }
+ if (!check_secret_key (&sk))
+ rc = GPG_ERR_BAD_SECKEY;
- return err;
+ leave:
+ gcry_mpi_release (sk.p);
+ gcry_mpi_release (sk.g);
+ gcry_mpi_release (sk.y);
+ gcry_mpi_release (sk.x);
+ if (DBG_CIPHER)
+ log_debug ("elg_testkey => %s\n", gpg_strerror (rc));
+ return rc;
}
@@ -782,7 +783,7 @@ elg_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
/* Extract the key. */
rc = _gcry_pk_util_extract_mpis (keyparms, "pgy", &pk.p, &pk.g, &pk.y, NULL);
if (rc)
- return rc;
+ goto leave;
if (DBG_CIPHER)
{
log_mpidump ("elg_encrypt p", pk.p);
@@ -849,7 +850,7 @@ elg_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
&sk.p, &sk.g, &sk.y, &sk.x,
NULL);
if (rc)
- return rc;
+ goto leave;
if (DBG_CIPHER)
{
log_printmpi ("elg_decrypt p", sk.p);
@@ -942,7 +943,7 @@ elg_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
rc = _gcry_pk_util_extract_mpis (keyparms, "pgyx",
&sk.p, &sk.g, &sk.y, &sk.x, NULL);
if (rc)
- return rc;
+ goto leave;
if (DBG_CIPHER)
{
log_mpidump ("elg_sign p", sk.p);
@@ -1020,7 +1021,7 @@ elg_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms)
rc = _gcry_pk_util_extract_mpis (s_keyparms, "pgy",
&pk.p, &pk.g, &pk.y, NULL);
if (rc)
- return rc;
+ goto leave;
if (DBG_CIPHER)
{
log_mpidump ("elg_verify p", pk.p);
diff --git a/cipher/pubkey-util.c b/cipher/pubkey-util.c
index 9a94fe27..28388027 100644
--- a/cipher/pubkey-util.c
+++ b/cipher/pubkey-util.c
@@ -213,7 +213,7 @@ _gcry_pk_util_get_rsa_use_e (gcry_sexp_t list, unsigned long *r_e)
* parameter "E" again as an unsigned MPI into MPI_E.
*
* The function returns NULL on success. On error an error code is
- * returned and and the passed MPIs have no defined value.
+ * returned and the passed MPIs are either unchanged or set to NULL.
*/
gpg_err_code_t
_gcry_pk_util_extract_mpis (gcry_sexp_t sexp, const char *list, ...)
@@ -275,7 +275,10 @@ _gcry_pk_util_extract_mpis (gcry_sexp_t sexp, const char *list, ...)
else if (!l1)
{
while (idx--)
- gcry_mpi_release (*array[idx]);
+ {
+ gcry_mpi_release (*array[idx]);
+ *array[idx] = NULL;
+ }
return GPG_ERR_NO_OBJ; /* List element not found. */
}
else
@@ -288,7 +291,10 @@ _gcry_pk_util_extract_mpis (gcry_sexp_t sexp, const char *list, ...)
if (!*array[idx])
{
while (idx--)
- gcry_mpi_release (*array[idx]);
+ {
+ gcry_mpi_release (*array[idx]);
+ *array[idx] = NULL;
+ }
return GPG_ERR_INV_OBJ; /* Conversion failed. */
}
}
diff --git a/cipher/pubkey.c b/cipher/pubkey.c
index d7a474d8..c1d8bbc6 100644
--- a/cipher/pubkey.c
+++ b/cipher/pubkey.c
@@ -183,20 +183,6 @@ disable_pubkey_algo (int algo)
-/* Free the MPIs stored in the NULL terminated ARRAY of MPIs and set
- the slots to NULL. */
-static void
-release_mpi_array (gcry_mpi_t *array)
-{
- for (; *array; array++)
- {
- mpi_free(*array);
- *array = NULL;
- }
-}
-
-
-
/*
* Map a string to the pubkey algo
*/
@@ -303,396 +289,7 @@ pubkey_get_nenc (int algo)
}
-static gcry_err_code_t
-pubkey_check_secret_key (int algo, gcry_mpi_t *skey)
-{
- gcry_err_code_t rc;
- gcry_pk_spec_t *spec = spec_from_algo (algo);
-
- if (spec && spec->check_secret_key)
- rc = spec->check_secret_key (algo, skey);
- else if (spec)
- rc = GPG_ERR_NOT_IMPLEMENTED;
- else
- rc = GPG_ERR_PUBKEY_ALGO;
-
- return rc;
-}
-
-
-/* Internal function. */
-static gcry_err_code_t
-sexp_elements_extract (gcry_sexp_t key_sexp, const char *element_names,
- gcry_mpi_t *elements, const char *algo_name, int opaque)
-{
- gcry_err_code_t err = 0;
- int i, idx;
- const char *name;
- gcry_sexp_t list;
-
- for (name = element_names, idx = 0; *name && !err; name++, idx++)
- {
- list = gcry_sexp_find_token (key_sexp, name, 1);
- if (!list)
- elements[idx] = NULL;
- else if (opaque)
- {
- elements[idx] = _gcry_sexp_nth_opaque_mpi (list, 1);
- gcry_sexp_release (list);
- if (!elements[idx])
- err = GPG_ERR_INV_OBJ;
- }
- else
- {
- elements[idx] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
- gcry_sexp_release (list);
- if (!elements[idx])
- err = GPG_ERR_INV_OBJ;
- }
- }
-
- if (!err)
- {
- /* Check that all elements are available. */
- for (name = element_names, i = 0; *name; name++, i++)
- if (!elements[i])
- break;
- if (*name)
- {
- err = GPG_ERR_NO_OBJ;
- /* Some are missing. Before bailing out we test for
- optional parameters. */
- if (algo_name && !strcmp (algo_name, "RSA")
- && !strcmp (element_names, "nedpqu") )
- {
- /* This is RSA. Test whether we got N, E and D and that
- the optional P, Q and U are all missing. */
- if (elements[0] && elements[1] && elements[2]
- && !elements[3] && !elements[4] && !elements[5])
- err = 0;
- }
- }
- }
-
-
- if (err)
- {
- for (i = 0; i < idx; i++)
- if (elements[i])
- mpi_free (elements[i]);
- }
- return err;
-}
-
-
-/* Internal function used for ecc. Note, that this function makes use
- of its intimate knowledge about the ECC parameters from ecc.c. */
-static gcry_err_code_t
-sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names,
- gcry_mpi_t *elements, gcry_pk_spec_t *spec,
- int want_private)
-
-{
- gcry_err_code_t err = 0;
- int idx;
- const char *name;
- gcry_sexp_t list;
-
- /* Clear the array for easier error cleanup. */
- for (name = element_names, idx = 0; *name; name++, idx++)
- elements[idx] = NULL;
- gcry_assert (idx >= 5); /* We know that ECC has at least 5 elements
- (params only) or 6 (full public key). */
- if (idx == 5)
- elements[5] = NULL; /* Extra clear for the params only case. */
-
-
- /* Init the array with the available curve parameters. */
- for (name = element_names, idx = 0; *name && !err; name++, idx++)
- {
- list = gcry_sexp_find_token (key_sexp, name, 1);
- if (!list)
- elements[idx] = NULL;
- else
- {
- switch (idx)
- {
- case 5: /* The public and */
- case 6: /* the secret key must to be passed opaque. */
- elements[idx] = _gcry_sexp_nth_opaque_mpi (list, 1);
- break;
- default:
- elements[idx] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_STD);
- break;
- }
- gcry_sexp_release (list);
- if (!elements[idx])
- {
- err = GPG_ERR_INV_OBJ;
- goto leave;
- }
- }
- }
-
- /* Check whether a curve parameter has been given and then fill any
- missing elements. */
- list = gcry_sexp_find_token (key_sexp, "curve", 5);
- if (list)
- {
- if (spec->get_param)
- {
- char *curve;
- gcry_mpi_t params[6];
-
- for (idx = 0; idx < DIM(params); idx++)
- params[idx] = NULL;
-
- curve = _gcry_sexp_nth_string (list, 1);
- gcry_sexp_release (list);
- if (!curve)
- {
- /* No curve name given (or out of core). */
- err = GPG_ERR_INV_OBJ;
- goto leave;
- }
- err = spec->get_param (curve, params);
- gcry_free (curve);
- if (err)
- goto leave;
-
- for (idx = 0; idx < DIM(params); idx++)
- {
- if (!elements[idx])
- elements[idx] = params[idx];
- else
- mpi_free (params[idx]);
- }
- }
- else
- {
- gcry_sexp_release (list);
- err = GPG_ERR_INV_OBJ; /* "curve" given but ECC not supported. */
- goto leave;
- }
- }
-
- /* Check that all parameters are known. */
- for (name = element_names, idx = 0; *name; name++, idx++)
- if (!elements[idx])
- {
- if (want_private && *name == 'q')
- ; /* Q is optional. */
- else
- {
- err = GPG_ERR_NO_OBJ;
- goto leave;
- }
- }
-
- leave:
- if (err)
- {
- for (name = element_names, idx = 0; *name; name++, idx++)
- if (elements[idx])
- mpi_free (elements[idx]);
- }
- return err;
-}
-
-
-
-/****************
- * Convert a S-Exp with either a private or a public key to our
- * internal format. Currently we do only support the following
- * algorithms:
- * dsa
- * rsa
- * openpgp-dsa
- * openpgp-rsa
- * openpgp-elg
- * openpgp-elg-sig
- * ecdsa
- * ecdh
- * Provide a SE with the first element be either "private-key" or
- * or "public-key". It is followed by a list with its first element
- * be one of the above algorithm identifiers and the remaning
- * elements are pairs with parameter-id and value.
- * NOTE: we look through the list to find a list beginning with
- * "private-key" or "public-key" - the first one found is used.
- *
- * If OVERRIDE_ELEMS is not NULL those elems override the parameter
- * specification taken from the module. This ise used by
- * gcry_pk_get_curve.
- *
- * Returns: A pointer to an allocated array of MPIs if the return value is
- * zero; the caller has to release this array.
- *
- * Example of a DSA public key:
- * (private-key
- * (dsa
- * (p <mpi>)
- * (g <mpi>)
- * (y <mpi>)
- * (x <mpi>)
- * )
- * )
- * The <mpi> are expected to be in GCRYMPI_FMT_USG
- */
-static gcry_err_code_t
-sexp_to_key (gcry_sexp_t sexp, int want_private, int use,
- const char *override_elems,
- gcry_mpi_t **retarray, gcry_pk_spec_t **r_spec, int *r_is_ecc)
-{
- gcry_err_code_t err = 0;
- gcry_sexp_t list, l2;
- char *name;
- const char *elems;
- gcry_mpi_t *array;
- gcry_pk_spec_t *spec;
- int is_ecc;
-
- /* Check that the first element is valid. If we are looking for a
- public key but a private key was supplied, we allow the use of
- the private key anyway. The rationale for this is that the
- private key is a superset of the public key. */
- list = gcry_sexp_find_token (sexp,
- want_private? "private-key":"public-key", 0);
- if (!list && !want_private)
- list = gcry_sexp_find_token (sexp, "private-key", 0);
- if (!list)
- return GPG_ERR_INV_OBJ; /* Does not contain a key object. */
-
- l2 = gcry_sexp_cadr( list );
- gcry_sexp_release ( list );
- list = l2;
- name = _gcry_sexp_nth_string (list, 0);
- if (!name)
- {
- gcry_sexp_release ( list );
- return GPG_ERR_INV_OBJ; /* Invalid structure of object. */
- }
-
- /* Fixme: We should make sure that an ECC key is always named "ecc"
- and not "ecdsa". "ecdsa" should be used for the signature
- itself. We need a function to test whether an algorithm given
- with a key is compatible with an application of the key (signing,
- encryption). For RSA this is easy, but ECC is the first
- algorithm which has many flavours.
-
- We use an ugly hack here to decide whether to use ecdsa or ecdh.
- */
- if (!strcmp (name, "ecc"))
- is_ecc = 2;
- else if (!strcmp (name, "ecdsa") || !strcmp (name, "ecdh"))
- is_ecc = 1;
- else
- is_ecc = 0;
-
- if (is_ecc == 2 && (use & GCRY_PK_USAGE_SIGN))
- spec = spec_from_name ("ecdsa");
- else if (is_ecc == 2 && (use & GCRY_PK_USAGE_ENCR))
- spec = spec_from_name ("ecdh");
- else
- spec = spec_from_name (name);
-
- gcry_free (name);
-
- if (!spec)
- {
- gcry_sexp_release (list);
- return GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */
- }
-
- if (override_elems)
- elems = override_elems;
- else if (want_private)
- elems = spec->elements_skey;
- else
- elems = spec->elements_pkey;
- array = gcry_calloc (strlen (elems) + 1, sizeof (*array));
- if (!array)
- err = gpg_err_code_from_syserror ();
- if (!err)
- {
- if (is_ecc)
- err = sexp_elements_extract_ecc (list, elems, array, spec,
- want_private);
- else
- err = sexp_elements_extract (list, elems, array, spec->name, 0);
- }
-
- gcry_sexp_release (list);
-
- if (err)
- {
- gcry_free (array);
- }
- else
- {
- *retarray = array;
- *r_spec = spec;
- if (r_is_ecc)
- *r_is_ecc = is_ecc;
- }
-
- return err;
-}
-
-
-
-/* FIXME: This is a duplicate. */
-static inline int
-get_hash_algo (const char *s, size_t n)
-{
- static const struct { const char *name; int algo; } hashnames[] = {
- { "sha1", GCRY_MD_SHA1 },
- { "md5", GCRY_MD_MD5 },
- { "sha256", GCRY_MD_SHA256 },
- { "ripemd160", GCRY_MD_RMD160 },
- { "rmd160", GCRY_MD_RMD160 },
- { "sha384", GCRY_MD_SHA384 },
- { "sha512", GCRY_MD_SHA512 },
- { "sha224", GCRY_MD_SHA224 },
- { "md2", GCRY_MD_MD2 },
- { "md4", GCRY_MD_MD4 },
- { "tiger", GCRY_MD_TIGER },
- { "haval", GCRY_MD_HAVAL },
- { NULL, 0 }
- };
- int algo;
- int i;
-
- for (i=0; hashnames[i].name; i++)
- {
- if ( strlen (hashnames[i].name) == n
- && !memcmp (hashnames[i].name, s, n))
- break;
- }
- if (hashnames[i].name)
- algo = hashnames[i].algo;
- else
- {
- /* In case of not listed or dynamically allocated hash
- algorithm we fall back to this somewhat slower
- method. Further, it also allows to use OIDs as
- algorithm names. */
- char *tmpname;
-
- tmpname = gcry_malloc (n+1);
- if (!tmpname)
- algo = 0; /* Out of core - silently give up. */
- else
- {
- memcpy (tmpname, s, n);
- tmpname[n] = 0;
- algo = gcry_md_map_name (tmpname);
- gcry_free (tmpname);
- }
- }
- return algo;
-}
-
-
+
/*
Do a PK encrypt operation
@@ -881,22 +478,25 @@ gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey)
Returns: 0 or an errorcode.
- s_key = <key-as-defined-in-sexp_to_key> */
+ NOTE: We currently support only secret key checking. */
gcry_error_t
gcry_pk_testkey (gcry_sexp_t s_key)
{
- gcry_pk_spec_t *spec = NULL;
- gcry_mpi_t *key = NULL;
gcry_err_code_t rc;
+ gcry_pk_spec_t *spec;
+ gcry_sexp_t keyparms;
- /* Note we currently support only secret key checking. */
- rc = sexp_to_key (s_key, 1, 0, NULL, &key, &spec, NULL);
- if (!rc)
- {
- rc = pubkey_check_secret_key (spec->algo, key);
- release_mpi_array (key);
- gcry_free (key);
- }
+ rc = spec_from_sexp (s_key, 1, &spec, &keyparms);
+ if (rc)
+ goto leave;
+
+ if (spec->check_secret_key)
+ rc = spec->check_secret_key (keyparms);
+ else
+ rc = GPG_ERR_NOT_IMPLEMENTED;
+
+ leave:
+ gcry_sexp_release (keyparms);
return gcry_error (rc);
}
@@ -1124,13 +724,9 @@ gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
const char *
gcry_pk_get_curve (gcry_sexp_t key, int iterator, unsigned int *r_nbits)
{
- gcry_mpi_t *pkey = NULL;
- gcry_sexp_t list = NULL;
- gcry_sexp_t l2;
- char *name = NULL;
const char *result = NULL;
- int want_private = 1;
- gcry_pk_spec_t *spec = NULL;
+ gcry_pk_spec_t *spec;
+ gcry_sexp_t keyparms = NULL;
if (r_nbits)
*r_nbits = 0;
@@ -1139,50 +735,20 @@ gcry_pk_get_curve (gcry_sexp_t key, int iterator, unsigned int *r_nbits)
{
iterator = 0;
- /* Check that the first element is valid. */
- list = gcry_sexp_find_token (key, "public-key", 0);
- if (list)
- want_private = 0;
- if (!list)
- list = gcry_sexp_find_token (key, "private-key", 0);
- if (!list)
- return NULL; /* No public- or private-key object. */
-
- l2 = gcry_sexp_cadr (list);
- gcry_sexp_release (list);
- list = l2;
- l2 = NULL;
-
- name = _gcry_sexp_nth_string (list, 0);
- if (!name)
- goto leave; /* Invalid structure of object. */
-
- /* Get the key. We pass the names of the parameters for
- override_elems; this allows to call this function without the
- actual public key parameter. */
- if (sexp_to_key (key, want_private, 0, "pabgn", &pkey, &spec, NULL))
- goto leave;
+ if (spec_from_sexp (key, 0, &spec, &keyparms))
+ return NULL;
}
else
{
spec = spec_from_name ("ecc");
if (!spec)
- goto leave;
+ return NULL;
}
- if (!spec || !spec->get_curve)
- goto leave;
-
- result = spec->get_curve (pkey, iterator, r_nbits);
+ if (spec->get_curve)
+ result = spec->get_curve (keyparms, iterator, r_nbits);
- leave:
- if (pkey)
- {
- release_mpi_array (pkey);
- gcry_free (pkey);
- }
- gcry_free (name);
- gcry_sexp_release (list);
+ gcry_sexp_release (keyparms);
return result;
}
diff --git a/cipher/rsa.c b/cipher/rsa.c
index 428185bf..fc6bbe5b 100644
--- a/cipher/rsa.c
+++ b/cipher/rsa.c
@@ -836,27 +836,31 @@ rsa_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
static gcry_err_code_t
-rsa_check_secret_key (int algo, gcry_mpi_t *skey)
+rsa_check_secret_key (gcry_sexp_t keyparms)
{
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
- RSA_secret_key sk;
-
- (void)algo;
+ gcry_err_code_t rc;
+ RSA_secret_key sk = {NULL, NULL, NULL, NULL, NULL, NULL};
- sk.n = skey[0];
- sk.e = skey[1];
- sk.d = skey[2];
- sk.p = skey[3];
- sk.q = skey[4];
- sk.u = skey[5];
+ /* To check the key we need the optional parameters. */
+ rc = _gcry_pk_util_extract_mpis (keyparms, "nedpqu",
+ &sk.n, &sk.e, &sk.d, &sk.p, &sk.q, &sk.u,
+ NULL);
+ if (rc)
+ goto leave;
- if (!sk.p || !sk.q || !sk.u)
- err = GPG_ERR_NO_OBJ; /* To check the key we need the optional
- parameters. */
- else if (!check_secret_key (&sk))
- err = GPG_ERR_BAD_SECKEY;
+ if (!check_secret_key (&sk))
+ rc = GPG_ERR_BAD_SECKEY;
- return err;
+ leave:
+ gcry_mpi_release (sk.n);
+ gcry_mpi_release (sk.e);
+ gcry_mpi_release (sk.d);
+ gcry_mpi_release (sk.p);
+ gcry_mpi_release (sk.q);
+ gcry_mpi_release (sk.u);
+ if (DBG_CIPHER)
+ log_debug ("rsa_testkey => %s\n", gpg_strerror (rc));
+ return rc;
}
@@ -887,7 +891,7 @@ rsa_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
/* Extract the key. */
rc = _gcry_pk_util_extract_mpis (keyparms, "ne", &pk.n, &pk.e, NULL);
if (rc)
- return rc;
+ goto leave;
if (DBG_CIPHER)
{
log_mpidump ("rsa_encrypt n", pk.n);
@@ -968,7 +972,7 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
&sk.n, &sk.e, &sk.d, &sk.p, &sk.q, &sk.u,
NULL);
if (rc)
- return rc;
+ goto leave;
if (DBG_CIPHER)
{
log_printmpi ("rsa_decrypt n", sk.n);
@@ -1112,7 +1116,7 @@ rsa_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
&sk.n, &sk.e, &sk.d, &sk.p, &sk.q, &sk.u,
NULL);
if (rc)
- return rc;
+ goto leave;
if (DBG_CIPHER)
{
log_printmpi ("rsa_sign n", sk.n);
@@ -1205,7 +1209,7 @@ rsa_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
/* Extract the key. */
rc = _gcry_pk_util_extract_mpis (keyparms, "ne", &pk.n, &pk.e, NULL);
if (rc)
- return rc;
+ goto leave;
if (DBG_CIPHER)
{
log_printmpi ("rsa_verify n", pk.n);
diff --git a/src/cipher-proto.h b/src/cipher-proto.h
index 0dc83bd1..c7ce9060 100644
--- a/src/cipher-proto.h
+++ b/src/cipher-proto.h
@@ -54,8 +54,7 @@ typedef gcry_err_code_t (*gcry_pk_generate_t) (gcry_sexp_t genparms,
gcry_sexp_t *r_skey);
/* Type for the pk_check_secret_key function. */
-typedef gcry_err_code_t (*gcry_pk_check_secret_key_t) (int algo,
- gcry_mpi_t *skey);
+typedef gcry_err_code_t (*gcry_pk_check_secret_key_t) (gcry_sexp_t keyparms);
/* Type for the pk_encrypt function. */
typedef gcry_err_code_t (*gcry_pk_encrypt_t) (gcry_sexp_t *r_ciph,
@@ -90,7 +89,7 @@ typedef gcry_err_code_t (*pk_get_param_t) (const char *name,
gcry_mpi_t *pkey);
/* The type used to query an ECC curve name. */
-typedef const char *(*pk_get_curve_t)(gcry_mpi_t *pkey, int iterator,
+typedef const char *(*pk_get_curve_t)(gcry_sexp_t keyparms, int iterator,
unsigned int *r_nbits);
/* The type used to query ECC curve parameters by name. */