summaryrefslogtreecommitdiff
path: root/cipher/pubkey.c
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2013-04-05 18:08:36 +0200
committerWerner Koch <wk@gnupg.org>2013-04-05 18:08:51 +0200
commitfe91a642c7c257aca095b96406fbcace88fa3df4 (patch)
tree962ace0df029de0035f8acaba0d63b33ddede654 /cipher/pubkey.c
parentf23a068bcb6ec9788710698578d8be0a2a006dbc (diff)
downloadlibgcrypt-fe91a642c7c257aca095b96406fbcace88fa3df4.tar.gz
Make the Q parameter optional for ECC signing.
* cipher/ecc.c (ecc_sign): Remove the need for Q. * cipher/pubkey.c (sexp_elements_extract_ecc): Make Q optional for a private key. (sexp_to_key): Add optional arg R_IS_ECC. (gcry_pk_sign): Do not call gcry_pk_get_nbits for ECC keys. * tests/pubkey.c (die): Make sure to print a LF. (check_ecc_sample_key): New. (main): Call new test. -- Q is the actual public key which is not used for signing. Thus we can make it optional and even speed up the signing by parsing less stuff. Note: There seems to be a memory leak somewhere. Running tests/pubkey with just the new test enabled shows it. Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'cipher/pubkey.c')
-rw-r--r--cipher/pubkey.c46
1 files changed, 31 insertions, 15 deletions
diff --git a/cipher/pubkey.c b/cipher/pubkey.c
index c4be81c6..cd07d177 100644
--- a/cipher/pubkey.c
+++ b/cipher/pubkey.c
@@ -1858,7 +1858,8 @@ sexp_elements_extract (gcry_sexp_t key_sexp, const char *element_names,
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, pk_extra_spec_t *extraspec)
+ gcry_mpi_t *elements, pk_extra_spec_t *extraspec,
+ int want_private)
{
gcry_err_code_t err = 0;
@@ -1939,8 +1940,13 @@ sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names,
for (name = element_names, idx = 0; *name; name++, idx++)
if (!elements[idx])
{
- err = GPG_ERR_NO_OBJ;
- goto leave;
+ if (want_private && *name == 'q')
+ ; /* Q is optional. */
+ else
+ {
+ err = GPG_ERR_NO_OBJ;
+ goto leave;
+ }
}
leave:
@@ -1994,7 +2000,7 @@ sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names,
*/
static gcry_err_code_t
sexp_to_key (gcry_sexp_t sexp, int want_private, const char *override_elems,
- gcry_mpi_t **retarray, gcry_module_t *retalgo)
+ gcry_mpi_t **retarray, gcry_module_t *retalgo, int *r_is_ecc)
{
gcry_err_code_t err = 0;
gcry_sexp_t list, l2;
@@ -2060,7 +2066,8 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, const char *override_elems,
if (!err)
{
if (is_ecc)
- err = sexp_elements_extract_ecc (list, elems, array, extraspec);
+ err = sexp_elements_extract_ecc (list, elems, array, extraspec,
+ want_private);
else
err = sexp_elements_extract (list, elems, array, pubkey->name);
}
@@ -2079,6 +2086,8 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, const char *override_elems,
{
*retarray = array;
*retalgo = module;
+ if (r_is_ecc)
+ *r_is_ecc = is_ecc;
}
return err;
@@ -2854,7 +2863,7 @@ gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey)
REGISTER_DEFAULT_PUBKEYS;
/* Get the key. */
- rc = sexp_to_key (s_pkey, 0, NULL, &pkey, &module);
+ rc = sexp_to_key (s_pkey, 0, NULL, &pkey, &module, NULL);
if (rc)
goto leave;
@@ -3027,7 +3036,7 @@ gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey)
REGISTER_DEFAULT_PUBKEYS;
- rc = sexp_to_key (s_skey, 1, NULL, &skey, &module_key);
+ rc = sexp_to_key (s_skey, 1, NULL, &skey, &module_key, NULL);
if (rc)
goto leave;
@@ -3149,13 +3158,14 @@ gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
const char *algo_name, *algo_elems;
struct pk_encoding_ctx ctx;
int i;
+ int is_ecc;
gcry_err_code_t rc;
*r_sig = NULL;
REGISTER_DEFAULT_PUBKEYS;
- rc = sexp_to_key (s_skey, 1, NULL, &skey, &module);
+ rc = sexp_to_key (s_skey, 1, NULL, &skey, &module, &is_ecc);
if (rc)
goto leave;
@@ -3168,8 +3178,10 @@ gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
algo_elems = pubkey->elements_sig;
/* Get the stuff we want to sign. Note that pk_get_nbits does also
- work on a private key. */
- init_encoding_ctx (&ctx, PUBKEY_OP_SIGN, gcry_pk_get_nbits (s_skey));
+ work on a private key. We don't need the number of bits for ECC
+ here, thus set it to 0 so that we don't need to parse it. */
+ init_encoding_ctx (&ctx, PUBKEY_OP_SIGN,
+ is_ecc? 0 : gcry_pk_get_nbits (s_skey));
rc = sexp_data_to_mpi (s_hash, &hash, &ctx);
if (rc)
goto leave;
@@ -3287,7 +3299,7 @@ gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey)
REGISTER_DEFAULT_PUBKEYS;
- rc = sexp_to_key (s_pkey, 0, NULL, &pkey, &module_key);
+ rc = sexp_to_key (s_pkey, 0, NULL, &pkey, &module_key, NULL);
if (rc)
goto leave;
@@ -3360,7 +3372,7 @@ gcry_pk_testkey (gcry_sexp_t s_key)
REGISTER_DEFAULT_PUBKEYS;
/* Note we currently support only secret key checking. */
- rc = sexp_to_key (s_key, 1, NULL, &key, &module);
+ rc = sexp_to_key (s_key, 1, NULL, &key, &module, NULL);
if (! rc)
{
rc = pubkey_check_secret_key (module->mod_id, key);
@@ -3689,9 +3701,13 @@ gcry_pk_get_nbits (gcry_sexp_t key)
REGISTER_DEFAULT_PUBKEYS;
- rc = sexp_to_key (key, 0, NULL, &keyarr, &module);
+ /* FIXME: Parsing KEY is often too much overhead. For example for
+ ECC we would only need to look at P and stop parsing right
+ away. */
+
+ rc = sexp_to_key (key, 0, NULL, &keyarr, &module, NULL);
if (rc == GPG_ERR_INV_OBJ)
- rc = sexp_to_key (key, 1, NULL, &keyarr, &module);
+ rc = sexp_to_key (key, 1, NULL, &keyarr, &module, NULL);
if (rc)
return 0; /* Error - 0 is a suitable indication for that. */
@@ -3862,7 +3878,7 @@ gcry_pk_get_curve (gcry_sexp_t key, int iterator, unsigned int *r_nbits)
/* 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, "pabgn", &pkey, &module))
+ if (sexp_to_key (key, want_private, "pabgn", &pkey, &module, NULL))
goto leave;
}
else