diff options
author | Werner Koch <wk@gnupg.org> | 2007-04-18 12:59:00 +0000 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2007-04-18 12:59:00 +0000 |
commit | f4598e52aeb88c1c7511d6ec106c285c096c8ed2 (patch) | |
tree | 7abc3a8711facf8fac5375206c4b30f0ee35ee61 | |
parent | 591697fc7621e8aa16abb3f60dc297ea9af1048f (diff) | |
download | libgcrypt-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-- | ChangeLog | 2 | ||||
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | cipher/ChangeLog | 10 | ||||
-rw-r--r-- | cipher/ecc.c | 49 | ||||
-rw-r--r-- | cipher/pubkey.c | 588 | ||||
-rw-r--r-- | doc/gcrypt.texi | 9 | ||||
-rw-r--r-- | src/ChangeLog | 9 | ||||
-rw-r--r-- | src/cipher.h | 2 | ||||
-rw-r--r-- | src/g10lib.h | 5 | ||||
-rw-r--r-- | src/gcrypt.h.in | 7 | ||||
-rw-r--r-- | src/libgcrypt.vers | 1 | ||||
-rw-r--r-- | src/sexp.c | 183 |
12 files changed, 496 insertions, 370 deletions
@@ -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. @@ -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; @@ -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; } |