diff options
author | Moritz Schulte <mo@g10code.com> | 2003-04-27 19:18:27 +0000 |
---|---|---|
committer | Moritz Schulte <mo@g10code.com> | 2003-04-27 19:18:27 +0000 |
commit | 55ddea17ae11d69b6fc1a4ff402e5e5b011d28af (patch) | |
tree | b6bf227e7f8b88d0f6d317101490f694566da71c /cipher | |
parent | 5238a4c07992095083091dd1d52fd81502f141b9 (diff) | |
download | libgcrypt-55ddea17ae11d69b6fc1a4ff402e5e5b011d28af.tar.gz |
2003-04-27 Moritz Schulte <moritz@g10code.com>
* pubkey.c (gcry_pubkey_register_default): New macro
`pubkey_use_dummy', use it.
* elgamal.c (elg_names): New variable.
(pubkey_spec_elg): Include elg_names.
* dsa.c (dsa_names): New variable.
(pubkey_spec_dsa): Include dsa_names.
* rsa.c (rsa_names): New variable.
(pubkey_spec_rsa): Include rsa_names.
* pubkey.c (gcry_pubkey_lookup_func_name): Compare name also with
the names listed in `sexp_names'.
2003-04-24 Moritz Schulte <moritz@g10code.com>
* pubkey.c (sexp_to_key): New variables: module, pubkey. Adjusted
to new module interface.
(sexp_to_key): Changend type of argument `retalgo' from `int *' to
`GcryModule **'. Adjusted all callers. Removed argument:
r_algotblidx.
(sexp_to_sig): Changend type of argument `retalgo' from `int *' to
`GcryModule **'. Adjusted all callers.
(sexp_to_enc): Likewise.
(pubkey_get_npkey, pubkey_get_nskey, pubkey_get_nsig,
pubkey_get_nenc): Use strlen to find out the number.
* rsa.c: Adjust pubkey_spec_rsa to new internal interface.
* dsa.c: Likewise.
* elgamal.c: Likewise.
Diffstat (limited to 'cipher')
-rw-r--r-- | cipher/dsa.c | 10 | ||||
-rw-r--r-- | cipher/elgamal.c | 12 | ||||
-rw-r--r-- | cipher/pubkey.c | 1468 | ||||
-rw-r--r-- | cipher/rsa.c | 10 |
4 files changed, 796 insertions, 704 deletions
diff --git a/cipher/dsa.c b/cipher/dsa.c index b2adae4e..4bc2cd03 100644 --- a/cipher/dsa.c +++ b/cipher/dsa.c @@ -448,9 +448,17 @@ _gcry_dsa_get_nbits( int algo, MPI *pkey ) return mpi_get_nbits( pkey[0] ); } +static char *dsa_names[] = + { + "dsa", + "openpgp-dsa", + NULL, + }; + GcryPubkeySpec pubkey_spec_dsa = { - "DSA", GCRY_PK_DSA, 4, 5, 0, 2, + "DSA", dsa_names, GCRY_PK_DSA, + "pqgy", "pqgyx", "", "rs", "pqgy", GCRY_PK_USAGE_SIGN, _gcry_dsa_generate, _gcry_dsa_check_secret_key, diff --git a/cipher/elgamal.c b/cipher/elgamal.c index f9e63966..e9a4804e 100644 --- a/cipher/elgamal.c +++ b/cipher/elgamal.c @@ -625,9 +625,19 @@ _gcry_elg_get_nbits( int algo, MPI *pkey ) return mpi_get_nbits( pkey[0] ); } +static char *elg_names[] = + { + "elg", + "openpgp-elg", + "openpgp-elg-sig", + NULL, + }; + + GcryPubkeySpec pubkey_spec_elg = { - "ELG", GCRY_PK_ELG, 3, 4, 2, 2, + "ELG", elg_names, GCRY_PK_ELG, + "pgy", "pgyx", "ab", "rs", "pgy", GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR, _gcry_elg_generate, _gcry_elg_check_secret_key, diff --git a/cipher/pubkey.c b/cipher/pubkey.c index a041fac9..5a4a91b6 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -32,58 +32,10 @@ /* FIXME: use set_lasterr() */ -static struct -{ - const char* name; - int algo; - const char* common_elements; - const char* public_elements; - const char* secret_elements; - const char* grip_elements; -} algo_info_table[] = { - { "dsa" , GCRY_PK_DSA , "pqgy", "", "x", "pqgy" }, - { "rsa" , GCRY_PK_RSA , "ne", "", "dpqu", "n" }, - { "elg" , GCRY_PK_ELG , "pgy", "", "x", "pgy" }, - { "openpgp-dsa", GCRY_PK_DSA , "pqgy", "", "x", "pqgy" }, - { "openpgp-rsa", GCRY_PK_RSA , "ne", "", "dpqu" "n"}, - { "openpgp-elg", GCRY_PK_ELG_E , "pgy", "", "x", "pgy" }, - { "openpgp-elg-sig", GCRY_PK_ELG , "pgy", "", "x", "pgy" }, - { "oid.1.2.840.113549.1.1.1", - GCRY_PK_RSA , "ne", "", "dpqu", "n" }, - { NULL } -}; - -static struct { - const char* name; int algo; - const char* elements; -} sig_info_table[] = { - { "dsa" , GCRY_PK_DSA , "rs" }, - { "rsa" , GCRY_PK_RSA , "s" }, - { "elg" , GCRY_PK_ELG , "rs" }, - { "openpgp-dsa" , GCRY_PK_DSA , "rs" }, - { "openpgp-rsa" , GCRY_PK_RSA , "s" }, - { "openpgp-elg-sig" , GCRY_PK_ELG , "rs" }, - { "oid.1.2.840.113549.1.1.1", GCRY_PK_RSA , "s" }, - { NULL } -}; - -static struct { - const char* name; int algo; - const char* elements; -} enc_info_table[] = { - { "elg" , GCRY_PK_ELG , "ab" }, - { "rsa" , GCRY_PK_RSA , "a" }, - { "openpgp-rsa" , GCRY_PK_RSA , "a" }, - { "openpgp-elg" , GCRY_PK_ELG_E , "ab" }, - { "openpgp-elg-sig", GCRY_PK_ELG , "ab" }, - { "oid.1.2.840.113549.1.1.1", GCRY_PK_RSA , "a" }, - { NULL } -}; - -static int pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey, int flags); -static int pubkey_sign( int algo, MPI *resarr, MPI hash, MPI *skey ); -static int pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey, - int (*cmp)(void *, MPI), void *opaque ); +static int pubkey_decrypt (int algo, MPI *result, MPI *data, MPI *skey, int flags); +static int pubkey_sign (int algo, MPI *resarr, MPI hash, MPI *skey); +static int pubkey_verify (int algo, MPI hash, MPI *data, MPI *pkey, + int (*cmp) (void *, MPI), void *opaque); /* This is the list of the default public-key ciphers included in libgcrypt. */ @@ -169,7 +121,7 @@ dummy_sign (int id, MPI *resarr, MPI data, MPI *skey) static int dummy_verify (int id, MPI hash, MPI *data, MPI *pkey, - int (*cmp)(void *, MPI), void *opaquev) + int (*cmp) (void *, MPI), void *opaquev) { log_bug ("no verify() for %d\n", id); return GCRYERR_INV_PK_ALGO; @@ -182,7 +134,6 @@ dummy_get_nbits (int id, MPI *pkey) return 0; } - /* Internal function. Register all the pubkeys included in PUBKEY_TABLE. Returns zero on success or an error code. */ static void @@ -192,24 +143,20 @@ gcry_pubkey_register_default (void) for (i = 0; (! err) && pubkey_table[i].pubkey; i++) { - if (! pubkey_table[i].pubkey->generate) - pubkey_table[i].pubkey->generate = dummy_generate; - if (! pubkey_table[i].pubkey->check_secret_key) - pubkey_table[i].pubkey->check_secret_key = dummy_check_secret_key; - if (! pubkey_table[i].pubkey->encrypt) - pubkey_table[i].pubkey->encrypt = dummy_encrypt; - if (! pubkey_table[i].pubkey->decrypt) - pubkey_table[i].pubkey->decrypt = dummy_decrypt; - if (! pubkey_table[i].pubkey->sign) - pubkey_table[i].pubkey->sign = dummy_sign; - if (! pubkey_table[i].pubkey->verify) - pubkey_table[i].pubkey->verify = dummy_verify; - if (! pubkey_table[i].pubkey->get_nbits) - pubkey_table[i].pubkey->get_nbits = dummy_get_nbits; +#define pubkey_use_dummy(func) \ + if (! pubkey_table[i].pubkey->func) \ + pubkey_table[i].pubkey->func = dummy_##func; + + pubkey_use_dummy (generate); + pubkey_use_dummy (check_secret_key); + pubkey_use_dummy (encrypt); + pubkey_use_dummy (decrypt); + pubkey_use_dummy (sign); + pubkey_use_dummy (verify); + pubkey_use_dummy (get_nbits); err = _gcry_module_add (&pubkeys_registered, - (void *) pubkey_table[i].pubkey, - NULL); + (void *) pubkey_table[i].pubkey, NULL); } if (err) @@ -232,8 +179,13 @@ gcry_pubkey_lookup_func_name (void *spec, void *data) { GcryPubkeySpec *pubkey = (GcryPubkeySpec *) spec; char *name = (char *) data; + char **sexp_names = pubkey->sexp_names; + int ret = stricmp (name, pubkey->name); + + while (ret && *sexp_names) + ret = stricmp (name, *sexp_names++); - return (! stricmp (pubkey->name, name)); + return ! ret; } /* Internal function. Lookup a pubkey entry by it's ID. */ @@ -436,7 +388,7 @@ pubkey_get_npkey (int id) pubkey = gcry_pubkey_lookup_id (id); if (pubkey) { - npkey = ((GcryPubkeySpec *) pubkey->spec)->npkey; + npkey = strlen (((GcryPubkeySpec *) pubkey->spec)->elements_pkey); _gcry_module_release (pubkey); } ath_mutex_unlock (&pubkeys_registered_lock); @@ -459,7 +411,7 @@ pubkey_get_nskey (int id) pubkey = gcry_pubkey_lookup_id (id); if (pubkey) { - nskey = ((GcryPubkeySpec *) pubkey->spec)->nskey; + nskey = strlen (((GcryPubkeySpec *) pubkey->spec)->elements_skey); _gcry_module_release (pubkey); } ath_mutex_unlock (&pubkeys_registered_lock); @@ -482,7 +434,7 @@ pubkey_get_nsig (int id) pubkey = gcry_pubkey_lookup_id (id); if (pubkey) { - nsig = ((GcryPubkeySpec *) pubkey->spec)->nsig; + nsig = strlen (((GcryPubkeySpec *) pubkey->spec)->elements_sig); _gcry_module_release (pubkey); } ath_mutex_unlock (&pubkeys_registered_lock); @@ -505,7 +457,7 @@ pubkey_get_nenc (int id) pubkey = gcry_pubkey_lookup_id (id); if (pubkey) { - nenc = ((GcryPubkeySpec *) pubkey->spec)->nenc; + nenc = strlen (((GcryPubkeySpec *) pubkey->spec)->elements_enc); _gcry_module_release (pubkey); } ath_mutex_unlock (&pubkeys_registered_lock); @@ -579,8 +531,6 @@ pubkey_encrypt (int id, MPI *resarr, MPI data, MPI *pkey, log_mpidump (" data:", data); } - REGISTER_DEFAULT_PUBKEYS; - ath_mutex_lock (&pubkeys_registered_lock); module = gcry_pubkey_lookup_id (id); if (module) @@ -629,8 +579,6 @@ pubkey_decrypt (int id, MPI *result, MPI *data, MPI *skey, log_mpidump (" data:", data[i]); } - REGISTER_DEFAULT_PUBKEYS; - ath_mutex_lock (&pubkeys_registered_lock); module = gcry_pubkey_lookup_id (id); if (module) @@ -674,8 +622,6 @@ pubkey_sign (int id, MPI *resarr, MPI data, MPI *skey) log_mpidump(" data:", data ); } - REGISTER_DEFAULT_PUBKEYS; - ath_mutex_lock (&pubkeys_registered_lock); module = gcry_pubkey_lookup_id (id); if (module) @@ -720,8 +666,6 @@ pubkey_verify (int id, MPI hash, MPI *data, MPI *pkey, log_mpidump (" hash:", hash); } - REGISTER_DEFAULT_PUBKEYS; - ath_mutex_lock (&pubkeys_registered_lock); module = gcry_pubkey_lookup_id (id); if (module) @@ -804,18 +748,18 @@ sexp_elements_extract (GCRY_SEXP key_sexp, const char *element_names, * The <mpi> are expected to be in GCRYMPI_FMT_USG */ static int -sexp_to_key( GCRY_SEXP sexp, int want_private, MPI **retarray, - int *retalgo, int *r_algotblidx) +sexp_to_key (GCRY_SEXP sexp, int want_private, MPI **retarray, + GcryModule **retalgo) { GCRY_SEXP list, l2; const char *name; - const char *s; size_t n; - int i; int algo; - const char *elems1, *elems2; + const char *elems; GCRY_MPI *array; int err = 0; + GcryModule *module; + GcryPubkeySpec *pubkey; /* check that the first element is valid */ list = gcry_sexp_find_token( sexp, want_private? "private-key" @@ -830,55 +774,70 @@ sexp_to_key( GCRY_SEXP sexp, int want_private, MPI **retarray, gcry_sexp_release ( list ); return GCRYERR_INV_OBJ; /* invalid structure of object */ } - for(i=0; (s=algo_info_table[i].name); i++ ) { - if( strlen(s) == n && !memcmp( s, name, n ) ) - break; + + { + char *name_terminated = gcry_xmalloc (n + 1); + strncpy (name_terminated, name, n); + name_terminated[n] = 0; + + ath_mutex_lock (&pubkeys_registered_lock); + module = gcry_pubkey_lookup_name (name_terminated); + ath_mutex_unlock (&pubkeys_registered_lock); + + free (name_terminated); } - if( !s ) { - gcry_sexp_release ( list ); + + if (! module) + { + gcry_sexp_release (list); return GCRYERR_INV_PK_ALGO; /* unknown algorithm */ - } - if (r_algotblidx) - *r_algotblidx = i; - algo = algo_info_table[i].algo; - elems1 = algo_info_table[i].common_elements; - elems2 = want_private? algo_info_table[i].secret_elements - : algo_info_table[i].public_elements; - array = gcry_calloc( strlen(elems1)+strlen(elems2)+1, sizeof *array ); - if( !array ) { - gcry_sexp_release ( list ); - return GCRYERR_NO_MEM; - } + } + else + pubkey = (GcryPubkeySpec *) module->spec; + + algo = pubkey->id; + elems = want_private ? pubkey->elements_skey : pubkey->elements_pkey; + array = gcry_calloc (strlen (elems) + 1, sizeof (*array)); + if (! array) + err = GCRYERR_NO_MEM; - err = sexp_elements_extract (list, elems1, array); if (! err) - err = sexp_elements_extract (list, elems2, array + strlen (elems1)); - - gcry_sexp_release (list); + err = sexp_elements_extract (list, elems, array); + + if (list) + gcry_sexp_release (list); if (err) - gcry_free (array); + { + 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 = algo; + *retalgo = module; } return err; } static int -sexp_to_sig( GCRY_SEXP sexp, MPI **retarray, int *retalgo) +sexp_to_sig (GCRY_SEXP sexp, MPI **retarray, + GcryModule **retalgo) { GCRY_SEXP list, l2; const char *name; - const char *s; size_t n; - int i; int algo; const char *elems; GCRY_MPI *array; int err = 0; + GcryModule *module; + GcryPubkeySpec *pubkey; /* check that the first element is valid */ list = gcry_sexp_find_token( sexp, "sig-val" , 0 ); @@ -894,31 +853,52 @@ sexp_to_sig( GCRY_SEXP sexp, MPI **retarray, int *retalgo) gcry_sexp_release ( list ); return GCRYERR_INV_OBJ; /* invalid structure of object */ } - for(i=0; (s=sig_info_table[i].name); i++ ) { - if( strlen(s) == n && !memcmp( s, name, n ) ) - break; + + { + char *name_terminated = gcry_xmalloc (n + 1); + strncpy (name_terminated, name, n); + name_terminated[n] = 0; + + ath_mutex_lock (&pubkeys_registered_lock); + module = gcry_pubkey_lookup_name (name_terminated); + ath_mutex_unlock (&pubkeys_registered_lock); + + free (name_terminated); } - if( !s ) { - gcry_sexp_release ( list ); + + if (! module) + { + gcry_sexp_release (list); return GCRYERR_INV_PK_ALGO; /* unknown algorithm */ - } - algo = sig_info_table[i].algo; - elems = sig_info_table[i].elements; - array = gcry_calloc( (strlen(elems)+1) , sizeof *array ); - if( !array ) { - gcry_sexp_release ( list ); - return GCRYERR_NO_MEM; - } + } + else + pubkey = (GcryPubkeySpec *) module->spec; - err = sexp_elements_extract (list, elems, array); - gcry_sexp_release (list); + algo = pubkey->id; + elems = pubkey->elements_sig; + array = gcry_calloc (strlen (elems) + 1 , sizeof (*array)); + if (! array) + err = GCRYERR_NO_MEM; + + if (! err) + err = sexp_elements_extract (list, elems, array); + + if (list) + gcry_sexp_release (list); if (err) - gcry_free (array); + { + ath_mutex_lock (&pubkeys_registered_lock); + _gcry_module_release (module); + ath_mutex_unlock (&pubkeys_registered_lock); + + if (array) + gcry_free (array); + } else { *retarray = array; - *retalgo = algo; + *retalgo = module; } return err; @@ -938,109 +918,137 @@ sexp_to_sig( GCRY_SEXP sexp, MPI **retarray, int *retalgo) * RET_MODERN is set to true when at least an empty flags list has been found. */ static int -sexp_to_enc( GCRY_SEXP sexp, MPI **retarray, int *retalgo, - int *ret_modern, int *ret_want_pkcs1, - int *flags) +sexp_to_enc (GCRY_SEXP sexp, MPI **retarray, GcryModule **retalgo, + int *ret_modern, int *ret_want_pkcs1, int *flags) { - GCRY_SEXP list, l2; - const char *name; - const char *s; - size_t n; - int i; - int algo; - int parsed_flags = 0; - const char *elems; - GCRY_MPI *array; - int err = 0; + GCRY_SEXP list = NULL, l2 = NULL; + GcryPubkeySpec *pubkey = NULL; + GcryModule *module = NULL; + const char *name; + size_t n; + int parsed_flags = 0; + const char *elems; + GCRY_MPI *array = NULL; + int err = 0; - *ret_want_pkcs1 = 0; - *ret_modern = 0; - /* check that the first element is valid */ - list = gcry_sexp_find_token( sexp, "enc-val" , 0 ); - if( !list ) - return GCRYERR_INV_OBJ; /* Does not contain a encrypted value object */ - l2 = gcry_sexp_nth (list, 1); - if (!l2 ) { - gcry_sexp_release (list); - return GCRYERR_NO_OBJ; /* no cdr for the data object */ + *ret_want_pkcs1 = 0; + *ret_modern = 0; + + /* check that the first element is valid */ + list = gcry_sexp_find_token (sexp, "enc-val" , 0); + if (! list) + err = GCRYERR_INV_OBJ; /* Does not contain an encrypted value object */ + + if (! err) + { + l2 = gcry_sexp_nth (list, 1); + if (! l2) + err = GCRYERR_NO_OBJ; /* no cdr for the data object */ } - name = gcry_sexp_nth_data (l2, 0, &n); - if (!name) { - gcry_sexp_release (l2); - gcry_sexp_release (list); - return GCRYERR_INV_OBJ; /* invalid structure of object */ + + if (! err) + { + /* Extract the name of the algorithm. */ + name = gcry_sexp_nth_data (l2, 0, &n); + if (! name) + err = GCRYERR_INV_OBJ; /* invalid structure of object */ } - if ( n == 5 && !memcmp (name, "flags", 5)) { + + if ((! err) && (n == 5) && (! memcmp (name, "flags", 5))) + { /* There is a flags element - process it */ const char *s; + int i; *ret_modern = 1; - for (i=gcry_sexp_length (l2)-1; i > 0; i--) + for (i = gcry_sexp_length (l2) - 1; i > 0 && (! err); i--) { s = gcry_sexp_nth_data (l2, i, &n); - if (!s) + if (! s) ; /* not a data element - ignore */ - else if ( n == 3 && !memcmp (s, "raw", 3)) + else if (n == 3 && ! memcmp (s, "raw", 3)) ; /* just a dummy because it is the default */ - else if ( n == 5 && !memcmp (s, "pkcs1", 5)) + else if (n == 5 && ! memcmp (s, "pkcs1", 5)) *ret_want_pkcs1 = 1; - else if ( n == 11 && !memcmp (s, "no-blinding", 11)) + else if (n == 11 && ! memcmp (s, "no-blinding", 11)) parsed_flags |= PUBKEY_FLAG_NO_BLINDING; else - { - gcry_sexp_release (l2); - gcry_sexp_release (list); - return GCRYERR_INV_FLAG; - } - } - + err = GCRYERR_INV_FLAG; + } + } + + if (! err) + { /* Get the next which has the actual data */ gcry_sexp_release (l2); l2 = gcry_sexp_nth (list, 2); - if (!l2 ) { - gcry_sexp_release (list); - return GCRYERR_NO_OBJ; /* no cdr for the data object */ - } - name = gcry_sexp_nth_data (l2, 0, &n); - if (!name) { - gcry_sexp_release (l2); - gcry_sexp_release (list); - return GCRYERR_INV_OBJ; /* invalid structure of object */ - } + if (! l2) + err = GCRYERR_NO_OBJ; /* no cdr for the data object */ } - gcry_sexp_release (list); - list = l2; l2 = NULL; - - for(i=0; (s=enc_info_table[i].name); i++ ) { - if( strlen(s) == n && !memcmp( s, name, n ) ) - break; + + if (! err) + { + name = gcry_sexp_nth_data (l2, 0, &n); + if (! name) + err = GCRYERR_INV_OBJ; /* invalid structure of object */ + else + { + gcry_sexp_release (list); + list = l2; + l2 = NULL; + } } - if( !s ) { - gcry_sexp_release (list); - return GCRYERR_INV_PK_ALGO; /* unknown algorithm */ + + if (! err) + { + char *name_terminated = gcry_xmalloc (n + 1); + strncpy (name_terminated, name, n); + name_terminated[n] = 0; + + ath_mutex_lock (&pubkeys_registered_lock); + module = gcry_pubkey_lookup_name (name_terminated); + ath_mutex_unlock (&pubkeys_registered_lock); + + free (name_terminated); + + if (! module) + err = GCRYERR_INV_PK_ALGO; /* unknown algorithm */ + else + pubkey = (GcryPubkeySpec *) module->spec; } - algo = enc_info_table[i].algo; - elems = enc_info_table[i].elements; - array = gcry_calloc( (strlen(elems)+1) , sizeof *array ); - if( !array ) { - gcry_sexp_release ( list ); - return GCRYERR_NO_MEM; + if (! err) + { + elems = pubkey->elements_enc; + array = gcry_calloc (strlen (elems) + 1, sizeof (*array)); + if (! array) + err = GCRYERR_NO_MEM; } + if (! err) err = sexp_elements_extract (list, elems, array); + + if (list) gcry_sexp_release (list); + if (l2) + gcry_sexp_release (l2); - if (err) - gcry_free (array); - else - { - *retarray = array; - *retalgo = algo; - *flags = parsed_flags; - } + if (err) + { + ath_mutex_lock (&pubkeys_registered_lock); + _gcry_module_release (module); + ath_mutex_unlock (&pubkeys_registered_lock); + if (array) + gcry_free (array); + } + else + { + *retarray = array; + *retalgo = module; + *flags = parsed_flags; + } - return err; + return err; } /* Take the hash value and convert into an MPI, suitable for for @@ -1313,115 +1321,104 @@ sexp_data_to_mpi (GcrySexp input, unsigned int nbits, GcryMPI *ret_mpi, int gcry_pk_encrypt (GCRY_SEXP *r_ciph, GCRY_SEXP s_data, GCRY_SEXP s_pkey) { - MPI *pkey, data, *ciph; - const char *key_algo_name, *algo_name, *algo_elems; - int i, rc, algo, flags; - - *r_ciph = NULL; - /* get the key */ - rc = sexp_to_key( s_pkey, 0, &pkey, &algo, &i); - if( rc ) - return rc; - key_algo_name = algo_info_table[i].name; - assert (key_algo_name); - - /* get the name and the required size of the return value */ - for(i=0; (algo_name = enc_info_table[i].name); i++ ) { - if( enc_info_table[i].algo == algo ) - break; - } - /* get the name and the required size of the result array. We - compare using the algorithm name and not the algo number - this way - we get the correct name for the return value */ - for(i=0; (algo_name = enc_info_table[i].name); i++ ) { - if( !strcmp (algo_name, key_algo_name) ) - break; - } - if( !algo_name ) { - release_mpi_array( pkey ); - gcry_free (pkey); - return GCRYERR_INV_PK_ALGO; - } - algo_elems = enc_info_table[i].elements; - - /* get the stuff we want to encrypt */ - rc = sexp_data_to_mpi (s_data, gcry_pk_get_nbits (s_pkey), &data, 1, - &flags); - if (rc) { - release_mpi_array( pkey ); - gcry_free (pkey); - return GCRYERR_INV_OBJ; - } - - /* Now we can encrypt data to ciph */ - ciph = gcry_xcalloc( (strlen(algo_elems)+1) , sizeof *ciph ); - rc = pubkey_encrypt( algo, ciph, data, pkey, flags ); - release_mpi_array( pkey ); - gcry_free (pkey); pkey = NULL; - mpi_free( data ); - if( rc ) { - release_mpi_array( ciph ); - gcry_free( ciph ); - return rc; - } - - /* We did it. Now build the return list */ - { - char *string, *p; - size_t nelem, needed= strlen(algo_name) + 30; - - /* FIXME, this calculation needs to be cleaned up. - -moritz */ - - /* count elements, so that we can allocate enough space */ - for(nelem=0; algo_elems[nelem]; nelem++ ) - needed += 10; /* 6 + a safety margin */ - /* build the string */ - string = p = gcry_xmalloc ( needed ); - p = stpcpy ( p, "(enc-val(flags " ); - if (flags & PUBKEY_FLAG_NO_BLINDING) - p = stpcpy (p, "no-blinding"); - p = stpcpy (p, ")("); - p = stpcpy ( p, algo_name ); - for(i=0; algo_elems[i]; i++ ) { - *p++ = '('; - *p++ = algo_elems[i]; - p = stpcpy ( p, "%m)" ); - } - strcpy ( p, "))" ); - /* and now the ugly part: we don't have a function to - * pass an array to a format string, so we have to do it this way :-( - */ - switch ( nelem ) { - case 1: rc = gcry_sexp_build ( r_ciph, NULL, string, - ciph[0] - ); break; - case 2: rc = gcry_sexp_build ( r_ciph, NULL, string, - ciph[0], ciph[1] - ); break; - case 3: rc = gcry_sexp_build ( r_ciph, NULL, string, - ciph[0], ciph[1], ciph[2] - ); break; - case 4: rc = gcry_sexp_build ( r_ciph, NULL, string, - ciph[0], ciph[1], ciph[2], ciph[3] - ); break; - case 5: rc = gcry_sexp_build ( r_ciph, NULL, string, - ciph[0], ciph[1], ciph[2], ciph[3], ciph[4] - ); break; - case 6: rc = gcry_sexp_build ( r_ciph, NULL, string, - ciph[0], ciph[1], ciph[2], ciph[3], ciph[4], ciph[5] - ); break; - default: BUG (); - } - if ( rc ) - BUG (); - gcry_free ( string ); + MPI *pkey = NULL, data = NULL, *ciph = NULL; + const char *algo_name, *algo_elems; + int rc, flags; + GcryPubkeySpec *pubkey = NULL; + GcryModule *module = NULL; + + REGISTER_DEFAULT_PUBKEYS; + + *r_ciph = NULL; + /* get the key */ + rc = sexp_to_key (s_pkey, 0, &pkey, &module); + if (! rc) + { + assert (module); + pubkey = (GcryPubkeySpec *) module->spec; + algo_name = pubkey->name; + algo_elems = pubkey->elements_enc; + + /* get the stuff we want to encrypt */ + rc = sexp_data_to_mpi (s_data, gcry_pk_get_nbits (s_pkey), &data, 1, + &flags); + } + + if (! rc) + { + /* Now we can encrypt data to ciph */ + ciph = gcry_xcalloc (strlen (algo_elems) + 1, sizeof (*ciph)); + rc = pubkey_encrypt (pubkey->id, ciph, data, pkey, flags); + mpi_free (data); + } + + /* We did it. Now build the return list */ + if (! rc) + { + char *string, *p; + int i; + size_t nelem = strlen (algo_elems); + size_t needed = 18 + (nelem * 5); + if (flags & PUBKEY_FLAG_NO_BLINDING) + needed += 12; /* FIXME, verify calculation? */ + + /* Build the string. */ + string = p = gcry_xmalloc (needed); + p = stpcpy ( p, "(enc-val(flags" ); + if (flags & PUBKEY_FLAG_NO_BLINDING) + p = stpcpy (p, " no-blinding"); + p = stpcpy (p, ")("); + p = stpcpy ( p, algo_name ); + for(i=0; algo_elems[i]; i++ ) { + *p++ = '('; + *p++ = algo_elems[i]; + p = stpcpy ( p, "%m)" ); + } + strcpy ( p, "))" ); + + /* and now the ugly part: we don't have a function to + * pass an array to a format string, so we have to do it this way :-( + */ + switch ( nelem ) { + case 1: rc = gcry_sexp_build ( r_ciph, NULL, string, + ciph[0] + ); break; + case 2: rc = gcry_sexp_build ( r_ciph, NULL, string, + ciph[0], ciph[1] + ); break; + case 3: rc = gcry_sexp_build ( r_ciph, NULL, string, + ciph[0], ciph[1], ciph[2] + ); break; + case 4: rc = gcry_sexp_build ( r_ciph, NULL, string, + ciph[0], ciph[1], ciph[2], ciph[3] + ); break; + case 5: rc = gcry_sexp_build ( r_ciph, NULL, string, + ciph[0], ciph[1], ciph[2], ciph[3], ciph[4] + ); break; + case 6: rc = gcry_sexp_build ( r_ciph, NULL, string, + ciph[0], ciph[1], ciph[2], ciph[3], ciph[4], ciph[5] + ); break; + default: BUG (); + } + if (rc) + BUG (); + gcry_free (string); } - release_mpi_array( ciph ); - gcry_free( ciph ); + if (ciph) + { + release_mpi_array (ciph); + gcry_free (ciph); + } - return 0; + if (module) + { + ath_mutex_lock (&pubkeys_registered_lock); + _gcry_module_release (module); + ath_mutex_unlock (&pubkeys_registered_lock); + } + + return rc; } /**************** @@ -1448,56 +1445,73 @@ gcry_pk_encrypt (GCRY_SEXP *r_ciph, GCRY_SEXP s_data, GCRY_SEXP s_pkey) * or if the flags list is used (even if empty) a real S-expression: * (value PLAIN). */ int -gcry_pk_decrypt( GCRY_SEXP *r_plain, GCRY_SEXP s_data, GCRY_SEXP s_skey ) +gcry_pk_decrypt (GCRY_SEXP *r_plain, GCRY_SEXP s_data, GCRY_SEXP s_skey) { - MPI *skey, *data, plain; - int rc, algo, dataalgo, modern, want_pkcs1, flags; - - *r_plain = NULL; - rc = sexp_to_key( s_skey, 1, &skey, &algo, NULL ); - if( rc ) { - return rc; - } - rc = sexp_to_enc( s_data, &data, &dataalgo, &modern, &want_pkcs1, - &flags ); - if( rc ) { - release_mpi_array( skey ); - gcry_free (skey); - return rc; - } - if( algo != dataalgo ) { - release_mpi_array( skey ); - gcry_free (skey); - release_mpi_array( data ); - gcry_free (data); - return GCRYERR_CONFLICT; /* key algo does not match data algo */ - } - - rc = pubkey_decrypt( algo, &plain, data, skey, flags ); - if( rc ) { - release_mpi_array( skey ); - gcry_free (skey); - release_mpi_array( data ); - gcry_free (data); - return GCRYERR_GENERAL; /* decryption failed */ - } - - if (!modern) { - if ( gcry_sexp_build( r_plain, NULL, "%m", plain ) ) - BUG (); + MPI *skey = NULL, *data = NULL, plain = NULL; + int rc, modern, want_pkcs1, flags; + GcryModule *module_enc = NULL, *module_key = NULL; + GcryPubkeySpec *pubkey = NULL; + + REGISTER_DEFAULT_PUBKEYS; + + *r_plain = NULL; + rc = sexp_to_key (s_skey, 1, &skey, &module_key); + + if (! rc) + rc = sexp_to_enc (s_data, &data, &module_enc, &modern, &want_pkcs1, &flags); + + if (! rc) + { + if (((GcryPubkeySpec *) module_key->spec)->id + != ((GcryPubkeySpec *) module_enc->spec)->id) + rc = GCRYERR_CONFLICT; /* key algo does not match data algo */ + else + pubkey = (GcryPubkeySpec *) module_key->spec; } - else { - if ( gcry_sexp_build( r_plain, NULL, "(value %m)", plain ) ) - BUG (); + + if (! rc) + rc = pubkey_decrypt (pubkey->id, &plain, data, skey, flags); + + if (! rc) + { + if (! modern) + { + if (gcry_sexp_build (r_plain, NULL, "%m", plain)) + BUG (); + } + else + { + if (gcry_sexp_build (r_plain, NULL, "(value %m)", plain)) + BUG (); + } } - - mpi_free( plain ); - release_mpi_array( data ); - gcry_free (data); - release_mpi_array( skey ); - gcry_free (skey); - return 0; + if (skey) + { + release_mpi_array (skey); + gcry_free (skey); + } + + if (plain) + mpi_free (plain); + + if (data) + { + release_mpi_array (data); + gcry_free (data); + } + + if (module_key || module_enc) + { + ath_mutex_lock (&pubkeys_registered_lock); + if (module_key) + _gcry_module_release (module_key); + if (module_enc) + _gcry_module_release (module_enc); + ath_mutex_unlock (&pubkeys_registered_lock); + } + + return rc; } @@ -1528,152 +1542,163 @@ gcry_pk_decrypt( GCRY_SEXP *r_plain, GCRY_SEXP s_data, GCRY_SEXP s_skey ) * (<param_namen> <mpi>) * )) */ int -gcry_pk_sign( GCRY_SEXP *r_sig, GCRY_SEXP s_hash, GCRY_SEXP s_skey ) +gcry_pk_sign (GCRY_SEXP *r_sig, GCRY_SEXP s_hash, GCRY_SEXP s_skey) { - MPI *skey, hash; - MPI *result; - int i, algo, rc; - const char *key_algo_name, *algo_name, *algo_elems; - - *r_sig = NULL; - rc = sexp_to_key( s_skey, 1, &skey, &algo, &i); - if( rc ) - return rc; - key_algo_name = algo_info_table[i].name; - assert (key_algo_name); - - /* get the name and the required size of the result array. We - compare using the algorithm name and not the algo number - this way - we get the correct name for the return value */ - for(i=0; (algo_name = sig_info_table[i].name); i++ ) { - if( !strcmp (algo_name, key_algo_name) ) - break; - } - if( !algo_name ) { - release_mpi_array( skey ); - gcry_free (skey); - return -4; /* oops: unknown algorithm */ - } - assert (sig_info_table[i].algo == algo); - algo_elems = sig_info_table[i].elements; - - /* get the stuff we want to sign */ - /* Note that pk_get_nbits does also work on a private key */ - rc = sexp_data_to_mpi (s_hash, gcry_pk_get_nbits (s_skey), &hash, 0, NULL); - if (rc) { - release_mpi_array( skey ); - gcry_free (skey); - return rc; - } - result = gcry_xcalloc( (strlen(algo_elems)+1) , sizeof *result ); - rc = pubkey_sign( algo, result, hash, skey ); - release_mpi_array( skey ); - gcry_free (skey); skey = NULL; - mpi_free( hash ); - if( rc ) { - gcry_free( result ); - return rc; - } - - { - char *string, *p; - size_t nelem, needed= strlen(algo_name) + 20; - - /* count elements, so that we can allocate enough space */ - for(nelem=0; algo_elems[nelem]; nelem++ ) - needed += 10; /* 6 + a safety margin */ - /* build the string */ - string = p = gcry_xmalloc ( needed ); - p = stpcpy ( p, "(sig-val(" ); - p = stpcpy ( p, algo_name ); - for(i=0; algo_elems[i]; i++ ) { - *p++ = '('; - *p++ = algo_elems[i]; - p = stpcpy ( p, "%m)" ); + MPI *skey = NULL, hash = NULL, *result = NULL; + GcryPubkeySpec *pubkey = NULL; + GcryModule *module = NULL; + const char *key_algo_name, *algo_name, *algo_elems; + int i, rc; + + + REGISTER_DEFAULT_PUBKEYS; + + *r_sig = NULL; + rc = sexp_to_key (s_skey, 1, &skey, &module); + + if (! rc) + { + assert (module); + pubkey = (GcryPubkeySpec *) module->spec; + algo_name = key_algo_name = pubkey->name; + + algo_elems = pubkey->elements_sig; + + /* get the stuff we want to sign */ + /* Note that pk_get_nbits does also work on a private key */ + rc = sexp_data_to_mpi (s_hash, gcry_pk_get_nbits (s_skey), &hash, 0, NULL); + } + + if (! rc) + { + result = gcry_xcalloc (strlen (algo_elems) + 1, sizeof (*result)); + rc = pubkey_sign (pubkey->id, result, hash, skey); + } + + if (! rc) + { + char *string, *p; + size_t nelem, needed = strlen (algo_name) + 20; + + nelem = strlen (algo_elems); + + /* count elements, so that we can allocate enough space */ + needed += 10 * nelem; + + /* build the string */ + string = p = gcry_xmalloc (needed); + p = stpcpy (p, "(sig-val("); + p = stpcpy (p, algo_name); + for(i = 0; algo_elems[i]; i++) + { + *p++ = '('; + *p++ = algo_elems[i]; + p = stpcpy (p, "%m)"); } - strcpy ( p, "))" ); - /* and now the ugly part: we don't have a function to - * pass an array to a format string, so we have to do it this way :-( - */ - switch ( nelem ) { - case 1: rc = gcry_sexp_build ( r_sig, NULL, string, - result[0] - ); break; - case 2: rc = gcry_sexp_build ( r_sig, NULL, string, - result[0], result[1] - ); break; - case 3: rc = gcry_sexp_build ( r_sig, NULL, string, - result[0], result[1], result[2] - ); break; - case 4: rc = gcry_sexp_build ( r_sig, NULL, string, - result[0], result[1], result[2], result[3] - ); break; - case 5: rc = gcry_sexp_build ( r_sig, NULL, string, - result[0], result[1], result[2], result[3], result[4] - ); break; - case 6: rc = gcry_sexp_build ( r_sig, NULL, string, - result[0], result[1], result[2], result[3], result[4], result[5] - ); break; - default: BUG (); + strcpy (p, "))"); + + /* and now the ugly part: we don't have a function to + * pass an array to a format string, so we have to do it this way :-( + */ + switch (nelem) + { + case 1: rc = gcry_sexp_build ( r_sig, NULL, string, + result[0] + ); break; + case 2: rc = gcry_sexp_build ( r_sig, NULL, string, + result[0], result[1] + ); break; + case 3: rc = gcry_sexp_build ( r_sig, NULL, string, + result[0], result[1], result[2] + ); break; + case 4: rc = gcry_sexp_build ( r_sig, NULL, string, + result[0], result[1], result[2], result[3] + ); break; + case 5: rc = gcry_sexp_build ( r_sig, NULL, string, + result[0], result[1], result[2], result[3], result[4] + ); break; + case 6: rc = gcry_sexp_build ( r_sig, NULL, string, + result[0], result[1], result[2], result[3], result[4], result[5] + ); break; + default: BUG (); } - if ( rc ) - BUG (); - gcry_free ( string ); + if (rc) + BUG (); + gcry_free (string); } - release_mpi_array( result ); - gcry_free( result ); - return 0; + if (skey) + { + release_mpi_array (skey); + gcry_free (skey); + } + + if (hash) + mpi_free (hash); + + if (result) + gcry_free (result); + + return rc; } /**************** - * Verify a sgnature. Caller has to supply the public key pkey, - * the signature sig and his hashvalue data. Public key has to be - * a standard public key given as an S-Exp, sig is a S-Exp as returned - * from gcry_pk_sign and data must be an S-Exp like the one in sign too. + * Verify a signature. Caller has to supply the public key pkey, the + * signature sig and his hashvalue data. Public key has to be a + * standard public key given as an S-Exp, sig is a S-Exp as returned + * from gcry_pk_sign and data must be an S-Exp like the one in sign + * too. */ int -gcry_pk_verify( GCRY_SEXP s_sig, GCRY_SEXP s_hash, GCRY_SEXP s_pkey ) +gcry_pk_verify (GCRY_SEXP s_sig, GCRY_SEXP s_hash, GCRY_SEXP s_pkey) { - MPI *pkey, hash, *sig; - int algo, sigalgo; - int rc; - - rc = sexp_to_key( s_pkey, 0, &pkey, &algo, NULL ); - if( rc ) - return rc; - rc = sexp_to_sig( s_sig, &sig, &sigalgo ); - if( rc ) { - release_mpi_array( pkey ); - gcry_free (pkey); - return rc; - } - if( algo != sigalgo ) { - release_mpi_array( pkey ); - gcry_free (pkey); - release_mpi_array( sig ); - gcry_free (sig); - return GCRYERR_CONFLICT; /* algo does not match */ - } + GcryModule *module_key = NULL, *module_sig = NULL; + MPI *pkey = NULL, hash = NULL, *sig = NULL; + int rc; + + REGISTER_DEFAULT_PUBKEYS; + + rc = sexp_to_key (s_pkey, 0, &pkey, &module_key); + if (! rc) + rc = sexp_to_sig (s_sig, &sig, &module_sig); + + if ((! rc) + && (((GcryPubkeySpec *) module_key->spec)->id + != ((GcryPubkeySpec *) module_sig->spec)->id)) + rc = GCRYERR_CONFLICT; + if (! rc) rc = sexp_data_to_mpi (s_hash, gcry_pk_get_nbits (s_pkey), &hash, 0, 0); - if (rc) { - release_mpi_array( pkey ); - gcry_free (pkey); - release_mpi_array( sig ); - gcry_free (sig); - return rc; - } - - rc = pubkey_verify( algo, hash, sig, pkey, NULL, NULL ); - release_mpi_array( pkey ); - gcry_free (pkey); - release_mpi_array( sig ); - gcry_free (sig); - mpi_free(hash); - - return rc; + + if (! rc) + rc = pubkey_verify (((GcryPubkeySpec *) module_key->spec)->id, + hash, sig, pkey, NULL, NULL); + + if (pkey) + { + release_mpi_array (pkey); + gcry_free (pkey); + } + if (sig) + { + release_mpi_array (sig); + gcry_free (sig); + } + if (hash) + mpi_free (hash); + + if (module_key || module_sig) + { + ath_mutex_lock (&pubkeys_registered_lock); + if (module_key) + _gcry_module_release (module_key); + if (module_sig) + _gcry_module_release (module_sig); + ath_mutex_unlock (&pubkeys_registered_lock); + } + + return rc; } @@ -1686,21 +1711,21 @@ gcry_pk_verify( GCRY_SEXP s_sig, GCRY_SEXP s_hash, GCRY_SEXP s_pkey ) * s_key = <key-as-defined-in-sexp_to_key> */ int -gcry_pk_testkey( GCRY_SEXP s_key ) +gcry_pk_testkey (GCRY_SEXP s_key) { - MPI *key; - int rc, algo; - - /* Note we currently support only secret key checking */ - rc = sexp_to_key( s_key, 1, &key, &algo, NULL ); - if( rc ) { - return rc; + GcryModule *module = NULL; + MPI *key = NULL; + int rc; + + /* Note we currently support only secret key checking */ + rc = sexp_to_key (s_key, 1, &key, &module); + if (! rc) + { + rc = pubkey_check_secret_key (((GcryPubkeySpec *) module->spec)->id, key); + release_mpi_array (key); + gcry_free (key); } - - rc = pubkey_check_secret_key( algo, key ); - release_mpi_array( key ); - gcry_free (key); - return rc; + return rc; } @@ -1739,181 +1764,210 @@ gcry_pk_testkey( GCRY_SEXP s_key ) * ) */ int -gcry_pk_genkey( GCRY_SEXP *r_key, GCRY_SEXP s_parms ) +gcry_pk_genkey (GCRY_SEXP *r_key, GCRY_SEXP s_parms) { - GCRY_SEXP list, l2; - const char *name; - const char *s, *s2; - size_t n; - int rc, i; - const char *algo_name; - int algo; - char sec_elems[20], pub_elems[20]; - GCRY_MPI skey[10], *factors; - unsigned int nbits; - unsigned long use_e; + GcryPubkeySpec *pubkey = NULL; + GcryModule *module = NULL; + GCRY_SEXP list = NULL, l2 = NULL; + const char *name; + size_t n; + int rc = 0, i; + const char *algo_name = NULL; + int algo; + const char *sec_elems = NULL, *pub_elems = NULL; + GCRY_MPI skey[10] = { NULL }, *factors = NULL; + unsigned int nbits = 0; + unsigned long use_e = 0; - *r_key = NULL; - list = gcry_sexp_find_token( s_parms, "genkey", 0 ); - if( !list ) - return GCRYERR_INV_OBJ; /* Does not contain genkey data */ - l2 = gcry_sexp_cadr( list ); - gcry_sexp_release ( list ); - list = l2; - if( !list ) - return GCRYERR_NO_OBJ; /* no cdr for the genkey */ - name = gcry_sexp_nth_data( list, 0, &n ); - if( !name ) { - gcry_sexp_release ( list ); - return GCRYERR_INV_OBJ; /* algo string missing */ - } - for(i=0; (s=algo_info_table[i].name); i++ ) { - if( strlen(s) == n && !memcmp( s, name, n ) ) - break; - } - if( !s ) { - gcry_sexp_release ( list ); - return GCRYERR_INV_PK_ALGO; /* unknown algorithm */ - } + REGISTER_DEFAULT_PUBKEYS; - algo = algo_info_table[i].algo; - algo_name = algo_info_table[i].name; - - s = algo_info_table[i].common_elements; - s2 = algo_info_table[i].public_elements; - if( strlen( s ) + strlen( s2 ) > DIM( pub_elems ) ) - return GCRYERR_INTERNAL; /* check bound failed */ - strcpy( pub_elems, s ); - strcat( pub_elems, s2 ); - - s = algo_info_table[i].common_elements; - s2 = algo_info_table[i].secret_elements; - if( strlen( s ) + strlen( s2 ) > DIM( sec_elems ) ) - return GCRYERR_INTERNAL; /* check bound failed */ - strcpy( sec_elems, s ); - strcat( sec_elems, s2 ); - - l2 = gcry_sexp_find_token (list, "rsa-use-e", 0); - if (l2) - { - char buf[50]; - - name = gcry_sexp_nth_data (l2, 1, &n); - if (!name || n >= DIM (buf)-1 ) - { - gcry_sexp_release (l2); - gcry_sexp_release (list); - return GCRYERR_INV_OBJ; /* no value or value too large */ - } - - memcpy (buf, name, n); - buf[n] = 0; - use_e = strtoul (buf, NULL, 0); - gcry_sexp_release (l2); - } - else - use_e = 65537; /* not given, use the value generated by old versions. */ + *r_key = NULL; + list = gcry_sexp_find_token (s_parms, "genkey", 0); + if (! list) + rc = GCRYERR_INV_OBJ; /* Does not contain genkey data */ - l2 = gcry_sexp_find_token( list, "nbits", 0 ); - gcry_sexp_release ( list ); - list = l2; - if( !list ) - return GCRYERR_NO_OBJ; /* no nbits parameter */ - name = gcry_sexp_nth_data( list, 1, &n ); - if( !name ) { - gcry_sexp_release ( list ); - return GCRYERR_INV_OBJ; /* nbits without a cdr */ + if (! rc) + { + l2 = gcry_sexp_cadr (list); + gcry_sexp_release (list); + list = l2; + l2 = NULL; + if (! list) + rc = GCRYERR_NO_OBJ; /* no cdr for the genkey */ } + + if (! rc) { - char *p = gcry_xmalloc(n+1); - memcpy(p, name, n ); - p[n] = 0; - nbits = (unsigned int)strtol( p, NULL, 0 ); - gcry_free( p ); + name = gcry_sexp_nth_data (list, 0, &n); + if (! name) + rc = GCRYERR_INV_OBJ; /* algo string missing */ } - gcry_sexp_release ( list ); - rc = pubkey_generate( algo, nbits, use_e, skey, &factors ); - if( rc ) { - return rc; + if (! rc) + { + char *name_terminated = gcry_xmalloc (n + 1); + strncpy (name_terminated, name, n); + name_terminated[n] = 0; + + ath_mutex_unlock (&pubkeys_registered_lock); + module = gcry_pubkey_lookup_name (name_terminated); + ath_mutex_unlock (&pubkeys_registered_lock); + + free (name_terminated); + + if (! module) + rc = GCRYERR_INV_PK_ALGO; /* unknown algorithm */ + else + { + pubkey = (GcryPubkeySpec *) module->spec; + algo = pubkey->id; + algo_name = pubkey->name; + pub_elems = pubkey->elements_pkey; + sec_elems = pubkey->elements_skey; + } + } + + if (! rc) + { + l2 = gcry_sexp_find_token (list, "rsa-use-e", 0); + if (l2) + { + char buf[50]; + + name = gcry_sexp_nth_data (l2, 1, &n); + gcry_sexp_release (l2); + l2 = NULL; + if ((! name) || (n >= DIM (buf) - 1)) + rc = GCRYERR_INV_OBJ; /* no value or value too large */ + else + { + memcpy (buf, name, n); + buf[n] = 0; + use_e = strtoul (buf, NULL, 0); + } + } + else + use_e = 65537; /* not given, use the value generated by old versions. */ } + if (! rc) { - char *string, *p; - size_t nelem=0, needed=0; - GCRY_MPI mpis[30]; + l2 = gcry_sexp_find_token (list, "nbits", 0); + gcry_sexp_release (list); + list = l2; + l2 = NULL; + if (! list) + rc = GCRYERR_NO_OBJ; /* no nbits parameter */ + else + { + name = gcry_sexp_nth_data (list, 1, &n); + if (! name) + rc = GCRYERR_INV_OBJ; /* nbits without a cdr */ + else + { + char *p = gcry_xmalloc (n + 1); + memcpy (p, name, n); + p[n] = 0; + nbits = (unsigned int) strtol (p, NULL, 0); + gcry_free (p); + } + } + } + if (! rc) + rc = pubkey_generate (pubkey->id, nbits, use_e, skey, &factors); - /* count elements, so that we can allocate enough space */ - for(i=0; pub_elems[i]; i++, nelem++ ) - needed += 10; /* 6 + a safety margin */ - for(i=0; sec_elems[i]; i++, nelem++ ) - needed += 10; /* 6 + a safety margin */ - for(i=0; factors[i]; i++, nelem++ ) - needed += 10; /* 6 + a safety margin */ - needed += 2* strlen(algo_name) + 300; - if ( nelem > DIM(mpis) ) - BUG (); + if (! rc) + { + char *string, *p; + size_t nelem=0, needed=0; + GCRY_MPI mpis[30]; + + nelem = strlen (pub_elems) + strlen (sec_elems); + for (i = 0; factors[i]; i++) + nelem++; + needed += nelem * 10; + needed += 2 * strlen (algo_name) + 300; + if (nelem > DIM (mpis)) + BUG (); - /* build the string */ - nelem = 0; - string = p = gcry_xmalloc ( needed ); - p = stpcpy ( p, "(key-data" ); - - p = stpcpy ( p, "(public-key(" ); - p = stpcpy ( p, algo_name ); - for(i=0; pub_elems[i]; i++ ) { - *p++ = '('; - *p++ = pub_elems[i]; - p = stpcpy ( p, "%m)" ); - mpis[nelem++] = skey[i]; + /* build the string */ + nelem = 0; + string = p = gcry_xmalloc (needed); + p = stpcpy (p, "(key-data"); + p = stpcpy (p, "(public-key("); + p = stpcpy (p, algo_name); + for(i = 0; pub_elems[i]; i++) + { + *p++ = '('; + *p++ = pub_elems[i]; + p = stpcpy (p, "%m)"); + mpis[nelem++] = skey[i]; } - p = stpcpy ( p, "))" ); - - p = stpcpy ( p, "(private-key(" ); - p = stpcpy ( p, algo_name ); - for(i=0; sec_elems[i]; i++ ) { - *p++ = '('; - *p++ = sec_elems[i]; - p = stpcpy ( p, "%m)" ); - mpis[nelem++] = skey[i]; + p = stpcpy (p, "))"); + p = stpcpy (p, "(private-key("); + p = stpcpy (p, algo_name); + for (i = 0; sec_elems[i]; i++) + { + *p++ = '('; + *p++ = sec_elems[i]; + p = stpcpy (p, "%m)"); + mpis[nelem++] = skey[i]; } - p = stpcpy ( p, "))" ); - /* Very ugly hack to make release_mpi_array() work FIXME */ - skey[i] = NULL; - - p = stpcpy ( p, "(misc-key-info(pm1-factors" ); - for(i=0; factors[i]; i++ ) { - p = stpcpy ( p, "%m" ); - mpis[nelem++] = factors[i]; + p = stpcpy (p, "))"); + + /* Very ugly hack to make release_mpi_array() work FIXME */ + skey[i] = NULL; + + p = stpcpy (p, "(misc-key-info(pm1-factors"); + for(i = 0; factors[i]; i++) + { + p = stpcpy (p, "%m"); + mpis[nelem++] = factors[i]; } - strcpy ( p, ")))" ); + strcpy (p, ")))"); + + while (nelem < DIM (mpis)) + mpis[nelem++] = NULL; + + /* and now the ugly part: we don't have a function to pass an + * array to a format string, so we have just pass everything we + * have. which normally should be no problem as only those with + * a corresponding %m are used + */ + if (gcry_sexp_build (r_key, NULL, string, + mpis[0], mpis[1], mpis[2], mpis[3], mpis[4], mpis[5], + mpis[6], mpis[7], mpis[8], mpis[9], mpis[10], mpis[11], + mpis[12], mpis[13], mpis[14], mpis[15], mpis[16], mpis[17], + mpis[18], mpis[19], mpis[20], mpis[21], mpis[22], mpis[23], + mpis[24], mpis[25], mpis[26], mpis[27], mpis[28], mpis[29])) + BUG (); + assert (DIM (mpis) == 30); /* ? */ + gcry_free (string); + } - while ( nelem < DIM(mpis) ) - mpis[nelem++] = NULL; + release_mpi_array (skey); + /* no free: skey is a static array */ - /* and now the ugly part: we don't have a function to - * pass an array to a format string, so we have just pass everything - * we have. which normally should be no problem as only those - * with a corresponding %m are used - */ - if ( gcry_sexp_build ( r_key, NULL, string, - mpis[0], mpis[1], mpis[2], mpis[3], mpis[4], mpis[5], - mpis[6], mpis[7], mpis[8], mpis[9], mpis[10], mpis[11], - mpis[12], mpis[13], mpis[14], mpis[15], mpis[16], mpis[17], - mpis[18], mpis[19], mpis[20], mpis[21], mpis[22], mpis[23], - mpis[24], mpis[25], mpis[26], mpis[27], mpis[28], mpis[29] - ) ) - BUG (); - assert ( DIM(mpis) == 30 ); - gcry_free ( string ); + if (factors) + { + release_mpi_array ( factors ); + gcry_free (factors); } - release_mpi_array ( skey ); - /* no free: skey is a static array */ - release_mpi_array ( factors ); - gcry_free (factors); - return 0; + if (l2) + gcry_sexp_release (l2); + if (list) + gcry_sexp_release (list); + + if (module) + { + ath_mutex_lock (&pubkeys_registered_lock); + _gcry_module_release (module); + ath_mutex_unlock (&pubkeys_registered_lock); + } + + return rc; } /**************** @@ -1925,38 +1979,32 @@ gcry_pk_genkey( GCRY_SEXP *r_key, GCRY_SEXP s_parms ) unsigned int gcry_pk_get_nbits (GCRY_SEXP key) { + GcryModule *module = NULL; GcryPubkeySpec *pubkey; - GcryModule *module; - int rc, id; - MPI *keyarr; + MPI *keyarr = NULL; unsigned int nbits = 0; + int rc; - rc = sexp_to_key (key, 0, &keyarr, &id, NULL); + REGISTER_DEFAULT_PUBKEYS; + + rc = sexp_to_key (key, 0, &keyarr, &module); if (rc == GCRYERR_INV_OBJ) - rc = sexp_to_key (key, 1, &keyarr, &id, NULL); + rc = sexp_to_key (key, 1, &keyarr, &module); if (rc) return 0; - - REGISTER_DEFAULT_PUBKEYS; - - ath_mutex_lock (&pubkeys_registered_lock); - module = gcry_pubkey_lookup_id (id); - if (module) + else { pubkey = (GcryPubkeySpec *) module->spec; - nbits = (*pubkey->get_nbits) (id, keyarr); + nbits = (*pubkey->get_nbits) (pubkey->id, keyarr); + + ath_mutex_lock (&pubkeys_registered_lock); _gcry_module_release (module); - goto leave; + ath_mutex_unlock (&pubkeys_registered_lock); } - if (is_RSA (id)) /* we always wanna see the length of a key :-) */ - nbits = mpi_get_nbits (keyarr[0]); - - leave: - ath_mutex_unlock (&pubkeys_registered_lock); - release_mpi_array (keyarr); gcry_free (keyarr); + return nbits; } @@ -1971,61 +2019,75 @@ gcry_pk_get_nbits (GCRY_SEXP key) unsigned char * gcry_pk_get_keygrip (GCRY_SEXP key, unsigned char *array) { - GCRY_SEXP list=NULL, l2; + GCRY_SEXP list = NULL, l2 = NULL; + GcryPubkeySpec *pubkey = NULL; + GcryModule *module = NULL; const char *s, *name; size_t n; - int i, idx; + int idx; int is_rsa; const char *elems; GCRY_MD_HD md = NULL; + REGISTER_DEFAULT_PUBKEYS; + /* check that the first element is valid */ list = gcry_sexp_find_token (key, "public-key", 0); - if (!list) + if (! list) list = gcry_sexp_find_token (key, "private-key", 0); - if (!list) + if (! list) list = gcry_sexp_find_token (key, "protected-private-key", 0); - if (!list) + 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_data( list, 0, &n ); - if (!name) + name = gcry_sexp_nth_data (list, 0, &n); + if (! name) goto fail; /* invalid structure of object */ - for (i=0; (s=algo_info_table[i].name); i++ ) - { - if (strlen(s) == n && !memcmp (s, name, n)) - break; - } - if(!s) + { + char *name_terminated = gcry_xmalloc (n + 1); + strncpy (name_terminated, name, n); + name_terminated[n] = 0; + + ath_mutex_lock (&pubkeys_registered_lock); + module = gcry_pubkey_lookup_name (name_terminated); + ath_mutex_unlock (&pubkeys_registered_lock); + + free (name_terminated); + } + + if (! module) goto fail; /* unknown algorithm */ + else + pubkey = (GcryPubkeySpec *) module->spec; - is_rsa = algo_info_table[i].algo == GCRY_PK_RSA; - elems = algo_info_table[i].grip_elements; - if (!elems) + /* FIXME, special handling should be implemented by the algorithms, + not by the libgcrypt core. */ + is_rsa = pubkey->id == GCRY_PK_RSA; + elems = pubkey->elements_grip; + if (! elems) goto fail; /* no grip parameter */ md = gcry_md_open (GCRY_MD_SHA1, 0); - if (!md) + if (! md) goto fail; - idx = 0; - for (s=elems; *s; s++, idx++) + for (idx = 0, s = elems; *s; s++, idx++) { const char *data; size_t datalen; l2 = gcry_sexp_find_token (list, s, 1); - if (!l2) + if (! l2) goto fail; data = gcry_sexp_nth_data (l2, 1, &datalen); - gcry_sexp_release (l2); - if (!data) + if (! data) goto fail; if (!is_rsa) { @@ -2040,14 +2102,15 @@ gcry_pk_get_keygrip (GCRY_SEXP key, unsigned char *array) required 0 should be prefixed. We hash th raw bytes. For non-RSA we hash S-expressions. */ gcry_md_write (md, data, datalen); + gcry_sexp_release (l2); if (!is_rsa) gcry_md_write (md, ")", 1); } - + if (!array) { array = gcry_malloc (20); - if (!array) + if (! array) goto fail; } memcpy (array, gcry_md_read (md, GCRY_MD_SHA1), 20); @@ -2056,7 +2119,10 @@ gcry_pk_get_keygrip (GCRY_SEXP key, unsigned char *array) return array; fail: - gcry_md_close (md); + if (l2) + gcry_sexp_release (l2); + if (md) + gcry_md_close (md); gcry_sexp_release (list); return NULL; } diff --git a/cipher/rsa.c b/cipher/rsa.c index 9aea3ddd..526686a6 100644 --- a/cipher/rsa.c +++ b/cipher/rsa.c @@ -616,10 +616,18 @@ _gcry_rsa_get_nbits( int algo, MPI *pkey ) return mpi_get_nbits( pkey[0] ); } +static char *rsa_names[] = + { + "rsa", + "openpgp-rsa", + "oid.1.2.840.113549.1.1.1", + NULL, + }; GcryPubkeySpec pubkey_spec_rsa = { - "RSA", GCRY_PK_RSA, 2, 6, 1, 1, + "RSA", rsa_names, GCRY_PK_RSA, + "ne", "nedpqu", "a", "s", "n", GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR, _gcry_rsa_generate, _gcry_rsa_check_secret_key, |