summaryrefslogtreecommitdiff
path: root/cipher
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2007-12-05 09:50:50 +0000
committerWerner Koch <wk@gnupg.org>2007-12-05 09:50:50 +0000
commit9ea615f14905e3a764dca0ae1ec73ab6671d844a (patch)
tree400ef375c096a9f94ef5fc4a9a4e79e4765fe3a7 /cipher
parent5ff275e82f980bd95edf9764193a8cdd08fe2f99 (diff)
downloadlibgcrypt-9ea615f14905e3a764dca0ae1ec73ab6671d844a.tar.gz
Fixed an internal bug in rsa.c
Allow to decryption/signing using a minimal RSA key.
Diffstat (limited to 'cipher')
-rw-r--r--cipher/ChangeLog11
-rw-r--r--cipher/pubkey.c44
-rw-r--r--cipher/rsa.c20
3 files changed, 55 insertions, 20 deletions
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 <wk@g10code.com>
+
+ * 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 <wk@g10code.com>
* 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 <http://www.gnu.org/licenses/>.
*/
/* 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));