From 9ea615f14905e3a764dca0ae1ec73ab6671d844a Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 5 Dec 2007 09:50:50 +0000 Subject: Fixed an internal bug in rsa.c Allow to decryption/signing using a minimal RSA key. --- cipher/ChangeLog | 11 +++++++++++ cipher/pubkey.c | 44 +++++++++++++++++++++++++++++++++----------- cipher/rsa.c | 20 +++++++++++--------- 3 files changed, 55 insertions(+), 20 deletions(-) (limited to 'cipher') diff --git a/cipher/ChangeLog b/cipher/ChangeLog index 90fc43a4..f81c5da0 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -1,3 +1,14 @@ +2007-12-05 Werner Koch + + * rsa.c (secret): Fixed condition test for using CRT. Reported by + Dean Scarff. Fixes bug#864. + (_gcry_rsa_check_secret_key): Return an erro if the optional + parameters are missing. + * pubkey.c (sexp_elements_extract): Add arg ALGO_NAME. Changed all + callers to pass NULL. Add hack to allow for optional RSA + parameters. + (sexp_to_key): Pass algo name to sexp_elements_extract. + 2007-12-03 Werner Koch * random.c (gcry_random_add_bytes): Implement it. diff --git a/cipher/pubkey.c b/cipher/pubkey.c index 91fbfd4b..fc57b40a 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -751,9 +751,9 @@ pubkey_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data, /* Internal function. */ static gcry_err_code_t sexp_elements_extract (gcry_sexp_t key_sexp, const char *element_names, - gcry_mpi_t *elements) + gcry_mpi_t *elements, const char *algo_name) { - gcry_err_code_t err = GPG_ERR_NO_ERROR; + gcry_err_code_t err = 0; int i, idx; const char *name; gcry_sexp_t list; @@ -761,17 +761,41 @@ sexp_elements_extract (gcry_sexp_t key_sexp, const char *element_names, for (name = element_names, idx = 0; *name && !err; name++, idx++) { list = gcry_sexp_find_token (key_sexp, name, 1); - if (! list) - err = GPG_ERR_NO_OBJ; + if (!list) + elements[idx] = NULL; else { elements[idx] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG); gcry_sexp_release (list); - if (! elements[idx]) + if (!elements[idx]) err = GPG_ERR_INV_OBJ; } } + if (!err) + { + /* Check that all elements are available. */ + for (name = element_names, idx = 0; *name; name++, idx++) + if (!elements[idx]) + break; + if (*name) + { + err = GPG_ERR_NO_OBJ; + /* Some are missing. Before bailing out we test for + optional parameters. */ + if (algo_name && !strcmp (algo_name, "RSA") + && !strcmp (element_names, "nedpqu") ) + { + /* This is RSA. Test whether we got N, E and D and that + the optional P, Q and U are all missing. */ + if (elements[0] && elements[1] && elements[2] + && !elements[3] && !elements[4] && !elements[5]) + err = 0; + } + } + } + + if (err) { for (i = 0; i < idx; i++) @@ -884,8 +908,6 @@ sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names, * NOTE: we look through the list to find a list beginning with * "private-key" or "public-key" - the first one found is used. * - * FIXME: Allow for encrypted secret keys here. - * * Returns: A pointer to an allocated array of MPIs if the return value is * zero; the caller has to release this array. * @@ -959,7 +981,7 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray, if (is_ecc) err = sexp_elements_extract_ecc (list, elems, array); else - err = sexp_elements_extract (list, elems, array); + err = sexp_elements_extract (list, elems, array, pubkey->name); } gcry_sexp_release (list); @@ -1048,7 +1070,7 @@ sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray, err = gpg_err_code_from_errno (errno); if (!err) - err = sexp_elements_extract (list, elems, array); + err = sexp_elements_extract (list, elems, array, NULL); gcry_sexp_release (l2); gcry_sexp_release (list); @@ -1190,7 +1212,7 @@ sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_module_t *retalgo, goto leave; } - err = sexp_elements_extract (list, elems, array); + err = sexp_elements_extract (list, elems, array, NULL); leave: gcry_sexp_release (list); @@ -1921,7 +1943,7 @@ gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey) Test a key. This may be used either for a public or a secret key to see whether - internal structre is valid. + the internal structure is okay. Returns: 0 or an errorcode. diff --git a/cipher/rsa.c b/cipher/rsa.c index 7d5fd4c0..fe545c7a 100644 --- a/cipher/rsa.c +++ b/cipher/rsa.c @@ -1,6 +1,6 @@ /* rsa.c - RSA function - * Copyright (C) 1997, 1998, 1999 by Werner Koch (dd9jn) - * Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 1997, 1998, 1999 by Werner Koch (dd9jn) + * Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -15,8 +15,7 @@ * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * License along with this program; if not, see . */ /* This code uses an algorithm protected by U.S. Patent #4,405,829 @@ -357,7 +356,7 @@ stronger_key_check ( RSA_secret_key *skey ) static void secret(gcry_mpi_t output, gcry_mpi_t input, RSA_secret_key *skey ) { - if (!skey->p && !skey->q && !skey->u) + if (!skey->p || !skey->q || !skey->u) { mpi_powm (output, input, skey->d, skey->n); } @@ -488,7 +487,10 @@ _gcry_rsa_check_secret_key( int algo, gcry_mpi_t *skey ) sk.q = skey[4]; sk.u = skey[5]; - if (! check_secret_key (&sk)) + if (!sk.p || !sk.q || !sk.u) + err = GPG_ERR_NO_OBJ; /* To check the key we need the optional + parameters. */ + else if (!check_secret_key (&sk)) err = GPG_ERR_PUBKEY_ALGO; return err; @@ -529,9 +531,9 @@ _gcry_rsa_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data, sk.n = skey[0]; sk.e = skey[1]; sk.d = skey[2]; - sk.p = skey[3]; - sk.q = skey[4]; - sk.u = skey[5]; + sk.p = skey[3]; /* Optional. */ + sk.q = skey[4]; /* Optional. */ + sk.u = skey[5]; /* Optional. */ y = gcry_mpi_snew (gcry_mpi_get_nbits (sk.n)); -- cgit v1.2.1