diff options
-rw-r--r-- | cipher/dsa.c | 40 | ||||
-rw-r--r-- | cipher/ecc-common.h | 2 | ||||
-rw-r--r-- | cipher/ecc-curves.c | 51 | ||||
-rw-r--r-- | cipher/ecc.c | 134 | ||||
-rw-r--r-- | cipher/elgamal.c | 43 | ||||
-rw-r--r-- | cipher/pubkey-util.c | 12 | ||||
-rw-r--r-- | cipher/pubkey.c | 480 | ||||
-rw-r--r-- | cipher/rsa.c | 46 | ||||
-rw-r--r-- | src/cipher-proto.h | 5 |
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. */ |