summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2007-04-18 12:59:00 +0000
committerWerner Koch <wk@gnupg.org>2007-04-18 12:59:00 +0000
commitf4598e52aeb88c1c7511d6ec106c285c096c8ed2 (patch)
tree7abc3a8711facf8fac5375206c4b30f0ee35ee61
parent591697fc7621e8aa16abb3f60dc297ea9af1048f (diff)
downloadlibgcrypt-f4598e52aeb88c1c7511d6ec106c285c096c8ed2.tar.gz
Enhanced support for ECDSA.
Along with the latest libksba it is now possible for gpgsm to import an ECC certificate.
-rw-r--r--ChangeLog2
-rw-r--r--NEWS1
-rw-r--r--cipher/ChangeLog10
-rw-r--r--cipher/ecc.c49
-rw-r--r--cipher/pubkey.c588
-rw-r--r--doc/gcrypt.texi9
-rw-r--r--src/ChangeLog9
-rw-r--r--src/cipher.h2
-rw-r--r--src/g10lib.h5
-rw-r--r--src/gcrypt.h.in7
-rw-r--r--src/libgcrypt.vers1
-rw-r--r--src/sexp.c183
12 files changed, 496 insertions, 370 deletions
diff --git a/ChangeLog b/ChangeLog
index 290df023..5c2481f6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,6 @@
2007-04-16 Werner Koch <wk@g10code.com>
- * configure.ac: Cehck for sysconf.
+ * configure.ac: Check for sysconf.
* acinclude.m4 (GNUPG_CHECK_MLOCK): Try to use sysconf to get the
page size and use getpagesize only then if available.
diff --git a/NEWS b/NEWS
index 01692ed2..5d5fb552 100644
--- a/NEWS
+++ b/NEWS
@@ -49,6 +49,7 @@ Noteworthy changes in version 1.3.0 (unreleased)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gcry_fast_random_poll NEW
gcry_md_debug NEW
+ gcry_sexp_nth_string NEW
GCRYCTL_FAKED_RANDOM_P NEW
GCRY_MD_SHA224 NEW
GCRY_PK_USAGE_CERT NEW
diff --git a/cipher/ChangeLog b/cipher/ChangeLog
index 7d7a2e34..5538fb18 100644
--- a/cipher/ChangeLog
+++ b/cipher/ChangeLog
@@ -1,3 +1,13 @@
+2007-04-18 Werner Koch <wk@g10code.com>
+
+ * ecc.c (generate_curve): Implement alias mechanism.
+
+ * pubkey.c (sexp_elements_extract_ecc): New.
+ (sexp_to_key): Add special case for ecc.
+ (sexp_to_key, sexp_to_sig, sexp_to_enc, gcry_pk_genkey): Replace
+ name_terminated stuff by a call to _gcry_sexp_nth_string.
+ (gcry_pk_get_keygrip): Ditto.
+
2007-04-16 Werner Koch <wk@g10code.com>
* ecc.c (_gcry_ecc_generate): Renamed DUMMY to CURVE and use it.
diff --git a/cipher/ecc.c b/cipher/ecc.c
index 0012f796..d4a21879 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -363,13 +363,28 @@ static gpg_err_code_t
generate_curve (unsigned int nbits, const char *name,
elliptic_curve_t *curve, unsigned int *r_nbits)
{
- int idx;
+ int idx, aliasno;
if (name)
{
+ /* First check nor native curves. */
for (idx = 0; domain_parms[idx].desc; idx++)
if (!strcmp (name, domain_parms[idx].desc))
break;
+ /* If not found consult the alias table. */
+ if (!domain_parms[idx].desc)
+ {
+ for (aliasno = 0; curve_aliases[aliasno].name; aliasno++)
+ if (!strcmp (name, curve_aliases[aliasno].other))
+ break;
+ if (curve_aliases[aliasno].name)
+ {
+ for (idx = 0; domain_parms[idx].desc; idx++)
+ if (!strcmp (curve_aliases[aliasno].name,
+ domain_parms[idx].desc))
+ break;
+ }
+ }
}
else
{
@@ -888,6 +903,37 @@ _gcry_ecc_generate (int algo, unsigned int nbits, const char *curve,
return 0;
}
+/* Return the parameters of the curve NAME. */
+gcry_err_code_t
+_gcry_ecc_get_param (const char *name, gcry_mpi_t *pkey)
+{
+ gpg_err_code_t err;
+ unsigned int nbits;
+ elliptic_curve_t E;
+ mpi_ec_t ctx;
+ gcry_mpi_t g_x, g_y;
+
+ err = generate_curve (0, name, &E, &nbits);
+ if (err)
+ return err;
+
+ g_x = mpi_new (0);
+ g_y = mpi_new (0);
+ ctx = _gcry_mpi_ec_init (E.p, E.a);
+ if (_gcry_mpi_ec_get_affine (g_x, g_y, &E.G, ctx))
+ log_fatal ("ecc get param: Failed to get affine coordinates\n");
+ _gcry_mpi_ec_free (ctx);
+ point_free (&E.G);
+
+ pkey[0] = E.p;
+ pkey[1] = E.a;
+ pkey[2] = E.b;
+ pkey[3] = ec2os (g_x, g_y, E.p);
+ pkey[4] = E.n;
+ pkey[5] = NULL;
+
+ return 0;
+}
static gcry_err_code_t
ecc_generate (int algo, unsigned int nbits, unsigned long dummy,
@@ -1047,6 +1093,7 @@ ecc_get_nbits (int algo, gcry_mpi_t *pkey)
static const char *ecdsa_names[] =
{
"ecdsa",
+ "ecc",
NULL,
};
diff --git a/cipher/pubkey.c b/cipher/pubkey.c
index dd8330f1..b4a6f3ae 100644
--- a/cipher/pubkey.c
+++ b/cipher/pubkey.c
@@ -1,6 +1,6 @@
/* pubkey.c - pubkey dispatcher
* Copyright (C) 1998, 1999, 2000, 2002, 2003,
- * 2005 Free Software Foundation, Inc.
+ * 2005, 2007 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
*
@@ -781,6 +781,91 @@ sexp_elements_extract (gcry_sexp_t key_sexp, const char *element_names,
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_err_code_t err = 0;
+ int idx;
+ const char *name;
+ gcry_sexp_t list;
+
+ /* Clear the array for easir error cleanup. */
+ for (name = element_names, idx = 0; *name; name++, idx++)
+ elements[idx] = NULL;
+ assert (idx >= 6); /* We know that ECC has at least 6 elements. */
+
+ /* 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
+ {
+ elements[idx] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
+ 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)
+ {
+ char *curve;
+ gcry_mpi_t params[6];
+
+ for (idx = 0; idx < DIM(params); idx++)
+ params[idx] = NULL;
+
+ curve = _gcry_sexp_nth_string (list, 1);
+ if (!curve)
+ {
+ err = GPG_ERR_INV_OBJ; /* No curve name given (or out of core). */
+ goto leave;
+ }
+ err = _gcry_ecc_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]);
+ }
+ }
+
+ /* Check that all parameters are known. */
+ for (name = element_names, idx = 0; *name; name++, idx++)
+ if (!elements[idx])
+ {
+ err = GPG_ERR_NO_OBJ;
+ goto leave;
+ }
+
+ leave:
+ if (err)
+ {
+ for (name = element_names, idx = 0; *name; name++, idx++)
+ if (elements[idx])
+ gcry_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
@@ -791,6 +876,7 @@ sexp_elements_extract (gcry_sexp_t key_sexp, const char *element_names,
* openpgp-rsa
* openpgp-elg
* openpgp-elg-sig
+ * ecdsa
* 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
@@ -818,186 +904,169 @@ static gcry_err_code_t
sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray,
gcry_module_t *retalgo)
{
- gcry_sexp_t list, l2;
- const char *name;
- size_t n;
- const char *elems;
- gcry_mpi_t *array;
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
- gcry_module_t module;
- gcry_pk_spec_t *pubkey;
-
- /* check that the first element is valid */
- list = gcry_sexp_find_token( sexp, want_private? "private-key"
- :"public-key", 0 );
- if( !list )
- return GPG_ERR_INV_OBJ; /* Does not contain a public-
- or private-key object */
- l2 = gcry_sexp_cadr( list );
- gcry_sexp_release ( list );
- list = l2;
- name = gcry_sexp_nth_data( list, 0, &n );
- if( !name ) {
- gcry_sexp_release ( list );
- return GPG_ERR_INV_OBJ; /* invalid structure of object */
- }
-
- {
- char *name_terminated;
-
- name_terminated = gcry_malloc (n + 1);
- if (!name_terminated)
- {
- err = gpg_err_code_from_errno (errno);
- gcry_sexp_release (list);
- return err;
- }
- memcpy (name_terminated, name, n);
- name_terminated[n] = 0;
+ gcry_err_code_t err = 0;
+ gcry_sexp_t list, l2;
+ char *name;
+ const char *elems;
+ gcry_mpi_t *array;
+ gcry_module_t module;
+ gcry_pk_spec_t *pubkey;
+ int is_ecc;
- ath_mutex_lock (&pubkeys_registered_lock);
- module = gcry_pk_lookup_name (name_terminated);
- ath_mutex_unlock (&pubkeys_registered_lock);
+ /* Check that the first element is valid. */
+ list = gcry_sexp_find_token (sexp,
+ want_private? "private-key":"public-key", 0);
+ if (!list)
+ return GPG_ERR_INV_OBJ; /* Does not contain a key object. */
- gcry_free (name_terminated);
+ 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. */
}
- if (! module)
- {
- gcry_sexp_release (list);
- return GPG_ERR_PUBKEY_ALGO; /* unknown algorithm */
- }
- else
- pubkey = (gcry_pk_spec_t *) module->spec;
-
- elems = want_private ? pubkey->elements_skey : pubkey->elements_pkey;
- array = gcry_calloc (strlen (elems) + 1, sizeof (*array));
- if (! array)
- err = gpg_err_code_from_errno (errno);
- if (! err)
- err = sexp_elements_extract (list, elems, array);
-
- if (list)
+ ath_mutex_lock (&pubkeys_registered_lock);
+ module = gcry_pk_lookup_name (name);
+ ath_mutex_unlock (&pubkeys_registered_lock);
+
+ /* 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. */
+ is_ecc = ( !strcmp (name, "ecdsa") || !strcmp (name, "ecc") );
+
+ if (!module)
+ {
gcry_sexp_release (list);
+ return GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */
+ }
+ else
+ pubkey = (gcry_pk_spec_t *) module->spec;
- if (err)
- {
- if (array)
- gcry_free (array);
-
- ath_mutex_lock (&pubkeys_registered_lock);
- _gcry_module_release (module);
- ath_mutex_unlock (&pubkeys_registered_lock);
- }
- else
- {
- *retarray = array;
- *retalgo = module;
- }
+ elems = want_private ? pubkey->elements_skey : pubkey->elements_pkey;
+ array = gcry_calloc (strlen (elems) + 1, sizeof (*array));
+ if (!array)
+ err = gpg_err_code_from_errno (errno);
+ if (!err)
+ {
+ if (is_ecc)
+ err = sexp_elements_extract_ecc (list, elems, array);
+ else
+ err = sexp_elements_extract (list, elems, array);
+ }
+
+ gcry_sexp_release (list);
+
+ if (err)
+ {
+ gcry_free (array);
- return err;
+ ath_mutex_lock (&pubkeys_registered_lock);
+ _gcry_module_release (module);
+ ath_mutex_unlock (&pubkeys_registered_lock);
+ }
+ else
+ {
+ *retarray = array;
+ *retalgo = module;
+ }
+
+ return err;
}
+
static gcry_err_code_t
sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray,
gcry_module_t *retalgo)
{
- gcry_sexp_t list, l2;
- const char *name;
- size_t n;
- const char *elems;
- gcry_mpi_t *array;
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
- gcry_module_t module;
- gcry_pk_spec_t *pubkey;
-
- /* check that the first element is valid */
- list = gcry_sexp_find_token( sexp, "sig-val" , 0 );
- if( !list )
- return GPG_ERR_INV_OBJ; /* Does not contain a signature value object */
- l2 = gcry_sexp_nth (list, 1);
- if(! l2)
- {
- gcry_sexp_release (list);
- return GPG_ERR_NO_OBJ; /* no cadr for the sig object */
- }
- name = gcry_sexp_nth_data( l2, 0, &n );
- if( !name ) {
- gcry_sexp_release ( list );
- gcry_sexp_release ( l2 );
- return GPG_ERR_INV_OBJ; /* invalid structure of object */
- }
- else if (n == 5 && (! memcmp (name, "flags", 5))) {
- /* Skip flags, since they are not used but just here for the
+ gcry_err_code_t err = 0;
+ gcry_sexp_t list, l2;
+ char *name;
+ const char *elems;
+ gcry_mpi_t *array;
+ gcry_module_t module;
+ gcry_pk_spec_t *pubkey;
+
+ /* Check that the first element is valid. */
+ list = gcry_sexp_find_token( sexp, "sig-val" , 0 );
+ if (!list)
+ return GPG_ERR_INV_OBJ; /* Does not contain a signature value object. */
+
+ l2 = gcry_sexp_nth (list, 1);
+ if (!l2)
+ {
+ gcry_sexp_release (list);
+ return GPG_ERR_NO_OBJ; /* No cadr for the sig object. */
+ }
+ name = _gcry_sexp_nth_string (l2, 0);
+ if (!name)
+ {
+ gcry_sexp_release (list);
+ gcry_sexp_release (l2);
+ return GPG_ERR_INV_OBJ; /* Invalid structure of object. */
+ }
+ else if (!strcmp (name, "flags"))
+ {
+ /* Skip flags, since they are not used but here just for the
sake of consistent S-expressions. */
+ gcry_free (name);
gcry_sexp_release (l2);
l2 = gcry_sexp_nth (list, 2);
- if (! l2)
+ if (!l2)
{
gcry_sexp_release (list);
return GPG_ERR_INV_OBJ;
}
- name = gcry_sexp_nth_data (l2, 0, &n);
+ name = _gcry_sexp_nth_string (l2, 0);
}
- {
- char *name_terminated;
-
- name_terminated = gcry_malloc (n + 1);
- if (!name_terminated)
- {
- err = gcry_err_code_from_errno (errno);
- gcry_sexp_release (l2);
- gcry_sexp_release (list);
- return err;
- }
-
- memcpy (name_terminated, name, n);
- name_terminated[n] = 0;
-
- ath_mutex_lock (&pubkeys_registered_lock);
- module = gcry_pk_lookup_name (name_terminated);
- ath_mutex_unlock (&pubkeys_registered_lock);
+ ath_mutex_lock (&pubkeys_registered_lock);
+ module = gcry_pk_lookup_name (name);
+ ath_mutex_unlock (&pubkeys_registered_lock);
+ gcry_free (name);
+ name = NULL;
- gcry_free (name_terminated);
+ if (!module)
+ {
+ gcry_sexp_release (l2);
+ gcry_sexp_release (list);
+ return GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */
}
+ else
+ pubkey = (gcry_pk_spec_t *) module->spec;
- if (! module)
- {
- gcry_sexp_release (l2);
- gcry_sexp_release (list);
- return GPG_ERR_PUBKEY_ALGO; /* unknown algorithm */
- }
- else
- pubkey = (gcry_pk_spec_t *) module->spec;
-
- elems = pubkey->elements_sig;
- array = gcry_calloc (strlen (elems) + 1 , sizeof (*array));
- if (! array)
- err = gpg_err_code_from_errno (errno);
-
- if (! err)
- err = sexp_elements_extract (list, elems, array);
-
- gcry_sexp_release (l2);
- gcry_sexp_release (list);
+ elems = pubkey->elements_sig;
+ array = gcry_calloc (strlen (elems) + 1 , sizeof *array );
+ if (!array)
+ err = gpg_err_code_from_errno (errno);
- if (err)
- {
- ath_mutex_lock (&pubkeys_registered_lock);
- _gcry_module_release (module);
- ath_mutex_unlock (&pubkeys_registered_lock);
+ if (!err)
+ err = sexp_elements_extract (list, elems, array);
- if (array)
- gcry_free (array);
- }
- else
- {
- *retarray = array;
- *retalgo = module;
- }
+ gcry_sexp_release (l2);
+ gcry_sexp_release (list);
- return err;
+ if (err)
+ {
+ ath_mutex_lock (&pubkeys_registered_lock);
+ _gcry_module_release (module);
+ ath_mutex_unlock (&pubkeys_registered_lock);
+
+ gcry_free (array);
+ }
+ else
+ {
+ *retarray = array;
+ *retalgo = module;
+ }
+
+ return err;
}
@@ -1017,45 +1086,45 @@ static gcry_err_code_t
sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_module_t *retalgo,
int *ret_modern, int *ret_want_pkcs1, int *flags)
{
+ gcry_err_code_t err = 0;
gcry_sexp_t list = NULL, l2 = NULL;
gcry_pk_spec_t *pubkey = NULL;
gcry_module_t module = NULL;
- const char *name;
+ char *name = NULL;
size_t n;
int parsed_flags = 0;
const char *elems;
gcry_mpi_t *array = NULL;
- gcry_err_code_t err = GPG_ERR_NO_ERROR;
*ret_want_pkcs1 = 0;
*ret_modern = 0;
- /* check that the first element is valid */
+ /* Check that the first element is valid. */
list = gcry_sexp_find_token (sexp, "enc-val" , 0);
- if (! list)
+ if (!list)
{
- err = GPG_ERR_INV_OBJ; /* Does not contain an encrypted value object */
+ err = GPG_ERR_INV_OBJ; /* Does not contain an encrypted value object. */
goto leave;
}
l2 = gcry_sexp_nth (list, 1);
- if (! l2)
+ if (!l2)
{
- err = GPG_ERR_NO_OBJ; /* no cdr for the data object */
+ err = GPG_ERR_NO_OBJ; /* No cdr for the data object. */
goto leave;
}
/* Extract identifier of sublist. */
- name = gcry_sexp_nth_data (l2, 0, &n);
- if (! name)
+ name = _gcry_sexp_nth_string (l2, 0);
+ if (!name)
{
- err = GPG_ERR_INV_OBJ; /* invalid structure of object */
+ err = GPG_ERR_INV_OBJ; /* Invalid structure of object. */
goto leave;
}
- if ((n == 5) && (! memcmp (name, "flags", 5)))
+ if (!strcmp (name, "flags"))
{
- /* There is a flags element - process it */
+ /* There is a flags element - process it. */
const char *s;
int i;
@@ -1064,10 +1133,10 @@ sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_module_t *retalgo,
{
s = gcry_sexp_nth_data (l2, i, &n);
if (! s)
- ; /* not a data element - ignore */
- else if (n == 3 && ! memcmp (s, "raw", 3))
- ; /* just a dummy because it is the default */
- else if (n == 5 && ! memcmp (s, "pkcs1", 5))
+ ; /* Not a data element - ignore. */
+ else if (n == 3 && !memcmp (s, "raw", 3))
+ ; /* This is just a dummy as it is the default. */
+ else if (n == 5 && !memcmp (s, "pkcs1", 5))
*ret_want_pkcs1 = 1;
else if (n == 11 && ! memcmp (s, "no-blinding", 11))
parsed_flags |= PUBKEY_FLAG_NO_BLINDING;
@@ -1078,20 +1147,21 @@ sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_module_t *retalgo,
}
}
- /* Get the next which has the actual data */
+ /* Get the next which has the actual data. */
gcry_sexp_release (l2);
l2 = gcry_sexp_nth (list, 2);
- if (! l2)
+ if (!l2)
{
- err = GPG_ERR_NO_OBJ; /* no cdr for the data object */
+ err = GPG_ERR_NO_OBJ; /* No cdr for the data object. */
goto leave;
}
/* Extract sublist identifier. */
- name = gcry_sexp_nth_data (l2, 0, &n);
- if (! name)
+ gcry_free (name);
+ name = _gcry_sexp_nth_string (l2, 0);
+ if (!name)
{
- err = GPG_ERR_INV_OBJ; /* invalid structure of object */
+ err = GPG_ERR_INV_OBJ; /* Invalid structure of object. */
goto leave;
}
@@ -1100,35 +1170,20 @@ sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_module_t *retalgo,
l2 = NULL;
}
- {
- char *name_terminated;
-
- name_terminated = gcry_malloc (n + 1);
- if (!name_terminated)
- {
- err = gcry_err_code_from_errno (errno);
- goto leave;
- }
- memcpy (name_terminated, name, n);
- name_terminated[n] = 0;
-
- ath_mutex_lock (&pubkeys_registered_lock);
- module = gcry_pk_lookup_name (name_terminated);
- ath_mutex_unlock (&pubkeys_registered_lock);
-
- gcry_free (name_terminated);
-
- if (! module)
- {
- err = GPG_ERR_PUBKEY_ALGO; /* unknown algorithm */
- goto leave;
- }
- pubkey = (gcry_pk_spec_t *) module->spec;
- }
+ ath_mutex_lock (&pubkeys_registered_lock);
+ module = gcry_pk_lookup_name (name);
+ ath_mutex_unlock (&pubkeys_registered_lock);
+
+ if (!module)
+ {
+ err = GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */
+ goto leave;
+ }
+ pubkey = (gcry_pk_spec_t *) module->spec;
elems = pubkey->elements_enc;
array = gcry_calloc (strlen (elems) + 1, sizeof (*array));
- if (! array)
+ if (!array)
{
err = gpg_err_code_from_errno (errno);
goto leave;
@@ -1137,18 +1192,16 @@ sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_module_t *retalgo,
err = sexp_elements_extract (list, elems, array);
leave:
- if (list)
- gcry_sexp_release (list);
- if (l2)
- gcry_sexp_release (l2);
+ gcry_sexp_release (list);
+ gcry_sexp_release (l2);
+ gcry_free (name);
if (err)
{
ath_mutex_lock (&pubkeys_registered_lock);
_gcry_module_release (module);
ath_mutex_unlock (&pubkeys_registered_lock);
- if (array)
- gcry_free (array);
+ gcry_free (array);
}
else
{
@@ -1820,6 +1873,9 @@ gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey)
if (rc)
goto leave;
+ /* Fixme: Check that the algorithm of S_SIG is compatible to the one
+ of S_PKEY. */
+
if (module_key->mod_id != module_sig->mod_id)
{
rc = GPG_ERR_CONFLICT;
@@ -1929,7 +1985,7 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
gcry_pk_spec_t *pubkey = NULL;
gcry_module_t module = NULL;
gcry_sexp_t list = NULL, l2 = NULL;
- const char *name;
+ char *name = NULL;
size_t n;
gcry_err_code_t rc = GPG_ERR_NO_ERROR;
int i;
@@ -1941,7 +1997,6 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
unsigned long use_e = 0;
unsigned int qbits;
gcry_mpi_t xvalue = NULL;
- char *name_terminated;
char *curve = NULL;
REGISTER_DEFAULT_PUBKEYS;
@@ -1966,29 +2021,21 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
goto leave;
}
- name = gcry_sexp_nth_data (list, 0, &n);
- if (! name)
- {
- rc = GPG_ERR_INV_OBJ; /* Algo string missing. */
- goto leave;
- }
-
- name_terminated = gcry_malloc (n + 1);
- if (!name_terminated)
+ name = _gcry_sexp_nth_string (list, 0);
+ if (!name)
{
- rc = gpg_err_code_from_errno (errno);
+ rc = GPG_ERR_INV_OBJ; /* Algo string missing. */
goto leave;
}
- memcpy (name_terminated, name, n);
- name_terminated[n] = 0;
+
ath_mutex_lock (&pubkeys_registered_lock);
- module = gcry_pk_lookup_name (name_terminated);
+ module = gcry_pk_lookup_name (name);
ath_mutex_unlock (&pubkeys_registered_lock);
- gcry_free (name_terminated);
-
- if (! module)
+ gcry_free (name);
+ name = NULL;
+ if (!module)
{
- rc = GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */
+ rc = GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */
goto leave;
}
@@ -2007,14 +2054,15 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
if (l2)
{
char buf[50];
+ const char *s;
- name = gcry_sexp_nth_data (l2, 1, &n);
- if ((! name) || (n >= DIM (buf) - 1))
+ s = gcry_sexp_nth_data (l2, 1, &n);
+ if ( !s || n >= DIM (buf) - 1 )
{
- rc = GPG_ERR_INV_OBJ; /* No value or value too large. */
+ rc = GPG_ERR_INV_OBJ; /* No value or value too large. */
goto leave;
}
- memcpy (buf, name, n);
+ memcpy (buf, s, n);
buf[n] = 0;
use_e = strtoul (buf, NULL, 0);
gcry_sexp_release (l2);
@@ -2028,14 +2076,15 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
if (l2)
{
char buf[50];
+ const char *s;
- name = gcry_sexp_nth_data (l2, 1, &n);
- if ((! name) || (n >= DIM (buf) - 1))
+ s = gcry_sexp_nth_data (l2, 1, &n);
+ if (!s || n >= DIM (buf) - 1 )
{
- rc = GPG_ERR_INV_OBJ; /* No value or value too large. */
+ rc = GPG_ERR_INV_OBJ; /* No value or value too large. */
goto leave;
}
- memcpy (buf, name, n);
+ memcpy (buf, s, n);
buf[n] = 0;
qbits = (unsigned int)strtoul (buf, NULL, 0);
gcry_sexp_release (l2);
@@ -2060,20 +2109,12 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
l2 = gcry_sexp_find_token (list, "curve", 0);
if (l2)
{
- name = gcry_sexp_nth_data (l2, 1, &n);
- if (!name || n < 1)
- {
- rc = GPG_ERR_INV_OBJ; /* No name or or value too large. */
- goto leave;
- }
- curve = gcry_malloc (n+1);
+ curve = _gcry_sexp_nth_string (l2, 1);
if (!curve)
{
- rc = gpg_err_code_from_syserror ();
+ rc = GPG_ERR_INV_OBJ; /* No curve name or value too large. */
goto leave;
}
- memcpy (curve, name, n);
- curve[n] = 0;
gcry_sexp_release (l2);
l2 = NULL;
}
@@ -2092,23 +2133,18 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
}
if (list)
{
- name = gcry_sexp_nth_data (list, 1, &n);
- if (! name)
- {
- rc = GPG_ERR_INV_OBJ; /* nbits without a cdr. */
- goto leave;
- }
-
- name_terminated = gcry_malloc (n + 1);
- if (!name_terminated)
+ char buf[50];
+ const char *s;
+
+ s = gcry_sexp_nth_data (list, 1, &n);
+ if (!s || n >= DIM (buf) - 1 )
{
- rc = gpg_err_code_from_errno (errno);
+ rc = GPG_ERR_INV_OBJ; /* NBITS given without a cdr. */
goto leave;
}
- memcpy (name_terminated, name, n);
- name_terminated[n] = 0;
- nbits = (unsigned int) strtoul (name_terminated, NULL, 0);
- gcry_free (name_terminated);
+ memcpy (buf, s, n);
+ buf[n] = 0;
+ nbits = (unsigned int)strtoul (buf, NULL, 0);
}
else
nbits = 0;
@@ -2209,6 +2245,7 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
}
leave:
+ gcry_free (name);
gcry_free (curve);
release_mpi_array (skey);
/* Don't free SKEY itself, it is a static array. */
@@ -2286,8 +2323,8 @@ gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
gcry_sexp_t list = NULL, l2 = NULL;
gcry_pk_spec_t *pubkey = NULL;
gcry_module_t module = NULL;
- const char *s, *name;
- size_t n;
+ const char *s;
+ char *name = NULL;
int idx;
int is_rsa;
const char *elems;
@@ -2311,24 +2348,16 @@ gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
list = l2;
l2 = NULL;
- name = gcry_sexp_nth_data (list, 0, &n);
- if (! name)
+ name = _gcry_sexp_nth_string (list, 0);
+ if (!name)
goto fail; /* Invalid structure of object. */
- {
- char *name_terminated = gcry_malloc (n + 1);
- if (!name_terminated)
- goto fail;
- memcpy (name_terminated, name, n);
- name_terminated[n] = 0;
- ath_mutex_lock (&pubkeys_registered_lock);
- module = gcry_pk_lookup_name (name_terminated);
- ath_mutex_unlock (&pubkeys_registered_lock);
- gcry_free (name_terminated);
- }
+ ath_mutex_lock (&pubkeys_registered_lock);
+ module = gcry_pk_lookup_name (name);
+ ath_mutex_unlock (&pubkeys_registered_lock);
- if (! module)
- goto fail; /* unknown algorithm */
+ if (!module)
+ goto fail; /* Unknown algorithm. */
pubkey = (gcry_pk_spec_t *) module->spec;
@@ -2337,7 +2366,7 @@ gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
is_rsa = module->mod_id == GCRY_PK_RSA;
elems = pubkey->elements_grip;
if (! elems)
- goto fail; /* no grip parameter */
+ goto fail; /* No grip parameter. */
if (gcry_md_open (&md, GCRY_MD_SHA1, 0))
goto fail;
@@ -2385,10 +2414,9 @@ gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
return array;
fail:
- if (l2)
- gcry_sexp_release (l2);
- if (md)
- gcry_md_close (md);
+ gcry_free (name);
+ gcry_sexp_release (l2);
+ gcry_md_close (md);
gcry_sexp_release (list);
return NULL;
}
diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index 41379d1a..50e609e0 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -3634,6 +3634,15 @@ printf ("my name is %.*s\n", (int)len, name);
@end example
@end deftypefun
+@deftypefun char *gcry_sexp_nth_string (@w{gcry_sexp_t @var{list}}, @w{int @var{number}})
+
+This function is used to get and convert data from a @var{list}. The
+data is assumed to be a Nul terminated string. The caller must
+release this returned value using @code{gcry_free}. If there is
+no data at the given index, the index represents a list or the value
+can't be converted to a string, @code{NULL} is returned.
+@end deftypefun
+
@deftypefun gcry_mpi_t gcry_sexp_nth_mpi (@w{gcry_sexp_t @var{list}}, @w{int @var{number}}, @w{int @var{mpifmt}})
This function is used to get and convert data from a @var{list}. This
diff --git a/src/ChangeLog b/src/ChangeLog
index 194a941e..47e5bb25 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,12 @@
+2007-04-18 Werner Koch <wk@g10code.com>
+
+ * gcrypt.h.in (gcry_sexp_nth_string): New.
+
+ * sexp.c (gcry_sexp_nth_data): Factored code out to ...
+ (sexp_nth_data): ... new.
+ (gcry_sexp_nth_string): New.
+ (gcry_sexp_nth_mpi): Reimplemented in terms of sexp_ntd_data.
+
2007-04-16 Werner Koch <wk@g10code.com>
* secmem.c (init_pool): Use sysconf() if available to determine
diff --git a/src/cipher.h b/src/cipher.h
index bd0cd747..2c505f78 100644
--- a/src/cipher.h
+++ b/src/cipher.h
@@ -57,6 +57,8 @@ void _gcry_register_pk_ecc_progress (gcry_handler_progress_t cbc,
gcry_err_code_t _gcry_ecc_generate (int algo, unsigned int nbits,
const char *curve,
gcry_mpi_t *skey, gcry_mpi_t **retfactors);
+gcry_err_code_t _gcry_ecc_get_param (const char *name, gcry_mpi_t *pkey);
+
/*-- primegen.c --*/
void _gcry_register_primegen_progress (gcry_handler_progress_t cb,
diff --git a/src/g10lib.h b/src/g10lib.h
index db6b307e..2844533e 100644
--- a/src/g10lib.h
+++ b/src/g10lib.h
@@ -243,4 +243,9 @@ gcry_err_code_t _gcry_malloc (size_t n, unsigned int flags, void **mem);
#define GCRY_ALLOC_FLAG_SECURE (1 << 0)
+
+/*-- sexp.c --*/
+char *_gcry_sexp_nth_string (const gcry_sexp_t list, int number);
+
+
#endif /* G10LIB_H */
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index feda73aa..a95fa332 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
@@ -472,6 +472,13 @@ gcry_sexp_t gcry_sexp_cadr (const gcry_sexp_t list);
const char *gcry_sexp_nth_data (const gcry_sexp_t list, int number,
size_t *datalen);
+/* This function is used to get and convert data from a LIST. The
+ data is assumed to be a Nul terminated string. The caller must
+ release the returned value using `gcry_free'. If there is no data
+ at the given index, the index represents a list or the value can't
+ be converted to a string, `NULL' is returned. */
+char *gcry_sexp_nth_string (gcry_sexp_t list, int number);
+
/* This function is used to get and convert data from a LIST. This
data is assumed to be an MPI stored in the format described by
MPIFMT and returned as a standard Libgcrypt MPI. The caller must
diff --git a/src/libgcrypt.vers b/src/libgcrypt.vers
index 11639524..227f669d 100644
--- a/src/libgcrypt.vers
+++ b/src/libgcrypt.vers
@@ -82,6 +82,7 @@ GCRYPT_1.2 {
gcry_sexp_new; gcry_sexp_nth; gcry_sexp_nth_data;
gcry_sexp_nth_mpi; gcry_sexp_prepend; gcry_sexp_release;
gcry_sexp_sprint; gcry_sexp_sscan; gcry_sexp_vlist;
+ gcry_sexp_nth_string;
gcry_mpi_add; gcry_mpi_add_ui; gcry_mpi_addm; gcry_mpi_aprint;
gcry_mpi_clear_bit; gcry_mpi_clear_flag; gcry_mpi_clear_highbit;
diff --git a/src/sexp.c b/src/sexp.c
index dab2b548..e88d12c1 100644
--- a/src/sexp.c
+++ b/src/sexp.c
@@ -1,6 +1,6 @@
/* sexp.c - S-Expression handling
* Copyright (C) 1999, 2000, 2001, 2002, 2003,
- * 2004, 2006 Free Software Foundation, Inc.
+ * 2004, 2006, 2007 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
*
@@ -582,116 +582,123 @@ gcry_sexp_car( const gcry_sexp_t list )
return gcry_sexp_nth ( list, 0 );
}
-/****************
- * Get data from the car. The returned value is valid as long as the list
- * is not modified.
- */
-const char *
-gcry_sexp_nth_data( const gcry_sexp_t list, int number, size_t *datalen )
+
+/* Helper to get data from the car. The returned value is valid as
+ long as the list is not modified. */
+static const char *
+sexp_nth_data (const gcry_sexp_t list, int number, size_t *datalen)
{
- const byte *p;
- DATALEN n;
- int level = 0;
+ const byte *p;
+ DATALEN n;
+ int level = 0;
+
+ *datalen = 0;
+ if ( !list )
+ return NULL;
- *datalen = 0;
- if ( !list ) {
- return NULL;
- }
- p = list->d;
- if ( *p == ST_OPEN )
- p++; /* yep, a list */
- else if (number )
- return NULL; /* not a list but an n > 0 element requested */
+ p = list->d;
+ if ( *p == ST_OPEN )
+ p++; /* Yep, a list. */
+ else if (number)
+ return NULL; /* Not a list but N > 0 requested. */
- /* skip n elements */
- while ( number > 0 ) {
- if ( *p == ST_DATA ) {
- memcpy ( &n, ++p, sizeof n );
- p += sizeof n + n;
- p--;
- if ( !level )
- number--;
+ /* Skip over N elements. */
+ while ( number > 0 )
+ {
+ if ( *p == ST_DATA )
+ {
+ memcpy ( &n, ++p, sizeof n );
+ p += sizeof n + n;
+ p--;
+ if ( !level )
+ number--;
}
- else if ( *p == ST_OPEN ) {
- level++;
+ else if ( *p == ST_OPEN )
+ {
+ level++;
}
- else if ( *p == ST_CLOSE ) {
- level--;
- if ( !level )
- number--;
+ else if ( *p == ST_CLOSE )
+ {
+ level--;
+ if ( !level )
+ number--;
}
- else if ( *p == ST_STOP ) {
- return NULL;
+ else if ( *p == ST_STOP )
+ {
+ return NULL;
}
- p++;
+ p++;
}
-
- if ( *p == ST_DATA ) {
- memcpy ( &n, ++p, sizeof n );
- *datalen = n;
- return (const char*)p + sizeof n;
+ /* If this is data, return it. */
+ if ( *p == ST_DATA )
+ {
+ memcpy ( &n, ++p, sizeof n );
+ *datalen = n;
+ return (const char*)p + sizeof n;
}
+
+ return NULL;
+}
+
+/* Get data from the car. The returned value is valid as long as the
+ list is not modified. */
+const char *
+gcry_sexp_nth_data (const gcry_sexp_t list, int number, size_t *datalen )
+{
+ return sexp_nth_data (list, number, datalen);
+}
+
+
+/* Get a string from the car. The returned value is a malloced string
+ and needs to be freed by the caller. */
+char *
+_gcry_sexp_nth_string (const gcry_sexp_t list, int number)
+{
+ const char *s;
+ size_t n;
+ char *buf;
+
+ s = sexp_nth_data (list, number, &n);
+ if (!s || n < 1 || (n+1) < 1)
+ return NULL;
+ buf = gcry_malloc (n+1);
+ if (!buf)
return NULL;
+ memcpy (buf, s, n);
+ buf[n] = 0;
+ return buf;
}
-/****************
+/* Public version of _gcry_sexp_nth_string. */
+char *
+gcry_sexp_nth_string (const gcry_sexp_t list, int number)
+{
+ return _gcry_sexp_nth_string (list, number);
+}
+
+/*
* Get a MPI from the car
*/
gcry_mpi_t
gcry_sexp_nth_mpi( gcry_sexp_t list, int number, int mpifmt )
{
- const byte *p;
- DATALEN n;
- int level = 0;
-
- if ( !list )
- return NULL;
- if ( !mpifmt )
- mpifmt = GCRYMPI_FMT_STD;
+ const char *s;
+ size_t n;
+ gcry_mpi_t a;
- p = list->d;
- if ( *p == ST_OPEN )
- p++; /* yep, a list */
- else if (number )
- return NULL; /* not a list but an n > 0 element requested */
+ if ( !mpifmt )
+ mpifmt = GCRYMPI_FMT_STD;
- /* skip n elements */
- while ( number > 0 ) {
- if ( *p == ST_DATA ) {
- memcpy ( &n, ++p, sizeof n );
- p += sizeof n + n;
- p--;
- if ( !level )
- number--;
- }
- else if ( *p == ST_OPEN ) {
- level++;
- }
- else if ( *p == ST_CLOSE ) {
- level--;
- if ( !level )
- number--;
- }
- else if ( *p == ST_STOP ) {
- return NULL;
- }
- p++;
- }
-
- if ( *p == ST_DATA ) {
- gcry_mpi_t a;
- size_t nbytes;
-
- memcpy ( &n, ++p, sizeof n );
- p += sizeof n;
- nbytes = n;
- if( !gcry_mpi_scan( &a, mpifmt, p, n, &nbytes ) )
- return a;
- }
+ s = sexp_nth_data (list, number, &n);
+ if (!s)
+ return NULL;
+ if ( gcry_mpi_scan ( &a, mpifmt, s, n, NULL ) )
return NULL;
+
+ return a;
}