summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cipher/ChangeLog17
-rw-r--r--cipher/dsa.c3
-rw-r--r--cipher/dsa.h3
-rw-r--r--cipher/dynload.c6
-rw-r--r--cipher/dynload.h3
-rw-r--r--cipher/elgamal.c3
-rw-r--r--cipher/elgamal.h3
-rw-r--r--cipher/pubkey.c80
-rw-r--r--cipher/rsa.c41
-rw-r--r--cipher/rsa.h3
10 files changed, 115 insertions, 47 deletions
diff --git a/cipher/ChangeLog b/cipher/ChangeLog
index dac938b0..c6f1fff0 100644
--- a/cipher/ChangeLog
+++ b/cipher/ChangeLog
@@ -1,3 +1,20 @@
+2003-01-23 Werner Koch <wk@gnupg.org>
+
+ * rsa.c (generate): New arg USE_E to request a specific public
+ exponent.
+ (_gcry_rsa_generate): Ditto.
+ * elgamal.c (_gcry_elg_generate): Must add an dummy argument
+ instead of USE_E.
+ * dsa.c (_gcry_dsa_generate): Ditto.
+ * pubkey.c (dummy_generate): Ditto.
+ (pubkey_generate): Add USE_E arg and pass it down.
+ (gcry_pk_genkey): Detect "rsa-use-e" parameter and pass it to generate.
+
+ * pubkey.c (sexp_to_enc): New arg RET_MODERN.
+ (gcry_pk_decrypt): Make use of it to return a real S-expression.
+ Return better error codes.
+ (gcry_pk_verify): Return better error codes.
+
2003-01-21 Werner Koch <wk@gnupg.org>
* random.c (gcry_random_add_bytes): Add QUALITY argument, let
diff --git a/cipher/dsa.c b/cipher/dsa.c
index d8ec37bd..61d0c377 100644
--- a/cipher/dsa.c
+++ b/cipher/dsa.c
@@ -356,7 +356,8 @@ verify(MPI r, MPI s, MPI hash, DSA_public_key *pkey )
*********************************************/
int
-_gcry_dsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
+_gcry_dsa_generate( int algo, unsigned nbits, unsigned long dummy,
+ MPI *skey, MPI **retfactors )
{
DSA_secret_key sk;
diff --git a/cipher/dsa.h b/cipher/dsa.h
index ce8acda3..6789ec6e 100644
--- a/cipher/dsa.h
+++ b/cipher/dsa.h
@@ -20,7 +20,8 @@
#ifndef G10_DSA_H
#define G10_DSA_H
-int _gcry_dsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors );
+int _gcry_dsa_generate( int algo, unsigned int nbits, unsigned long dummy,
+ MPI *skey, MPI **retfactors );
int _gcry_dsa_check_secret_key( int algo, MPI *skey );
int _gcry_dsa_sign( int algo, MPI *resarr, MPI data, MPI *skey );
int _gcry_dsa_verify( int algo, MPI hash, MPI *data, MPI *pkey,
diff --git a/cipher/dynload.c b/cipher/dynload.c
index 711468af..4f00a1e7 100644
--- a/cipher/dynload.c
+++ b/cipher/dynload.c
@@ -218,7 +218,8 @@ _gcry_enum_gnupgext_ciphers( void **enum_context, int *algo,
const char *
_gcry_enum_gnupgext_pubkeys( void **enum_context, int *algo,
int *npkey, int *nskey, int *nenc, int *nsig, int *use,
- int (**generate)( int algo, unsigned nbits, MPI *skey, MPI **retfactors ),
+ int (**generate)( int algo, unsigned int nbits, unsigned long use_e,
+ MPI *skey, MPI **retfactors ),
int (**check_secret_key)( int algo, MPI *skey ),
int (**encryptf)( int algo, MPI *resarr, MPI data, MPI *pkey ),
int (**decryptf)( int algo, MPI *result, MPI *data, MPI *skey ),
@@ -230,7 +231,8 @@ _gcry_enum_gnupgext_pubkeys( void **enum_context, int *algo,
EXTLIST r;
ENUMCONTEXT *ctx;
const char * (*finfo)( int, int *, int *, int *, int *, int *,
- int (**)( int, unsigned, MPI *, MPI **),
+ int (**)( int, unsigned int, unsigned long,
+ MPI *, MPI **),
int (**)( int, MPI * ),
int (**)( int, MPI *, MPI , MPI * ),
int (**)( int, MPI *, MPI *, MPI * ),
diff --git a/cipher/dynload.h b/cipher/dynload.h
index 9c89cc08..9258352d 100644
--- a/cipher/dynload.h
+++ b/cipher/dynload.h
@@ -46,7 +46,8 @@ _gcry_enum_gnupgext_ciphers( void **enum_context, int *algo,
const char *
_gcry_enum_gnupgext_pubkeys( void **enum_context, int *algo,
int *npkey, int *nskey, int *nenc, int *nsig, int *use,
- int (**generate)( int algo, unsigned nbits, MPI *skey, MPI **retfactors ),
+ int (**generate)( int algo, unsigned int nbits, unsigned long use_e,
+ MPI *skey, MPI **retfactors ),
int (**check_secret_key)( int algo, MPI *skey ),
int (**encryptf)( int algo, MPI *resarr, MPI data, MPI *pkey ),
int (**decryptf)( int algo, MPI *result, MPI *data, MPI *skey ),
diff --git a/cipher/elgamal.c b/cipher/elgamal.c
index d982c6a3..ea3a8dd6 100644
--- a/cipher/elgamal.c
+++ b/cipher/elgamal.c
@@ -498,7 +498,8 @@ verify(MPI a, MPI b, MPI input, ELG_public_key *pkey )
*********************************************/
int
-_gcry_elg_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
+_gcry_elg_generate( int algo, unsigned nbits, unsigned long dummy,
+ MPI *skey, MPI **retfactors )
{
ELG_secret_key sk;
diff --git a/cipher/elgamal.h b/cipher/elgamal.h
index f1920229..ae9f296a 100644
--- a/cipher/elgamal.h
+++ b/cipher/elgamal.h
@@ -20,7 +20,8 @@
#ifndef G10_ELGAMAL_H
#define G10_ELGAMAL_H
-int _gcry_elg_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors );
+int _gcry_elg_generate( int algo, unsigned int nbits, unsigned long dummy,
+ MPI *skey, MPI **retfactors );
int _gcry_elg_check_secret_key( int algo, MPI *skey );
int _gcry_elg_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey );
int _gcry_elg_decrypt( int algo, MPI *result, MPI *data, MPI *skey );
diff --git a/cipher/pubkey.c b/cipher/pubkey.c
index 0fb6113b..d0a493de 100644
--- a/cipher/pubkey.c
+++ b/cipher/pubkey.c
@@ -45,7 +45,8 @@ struct pubkey_table_s {
int nenc;
int nsig;
int use;
- int (*generate)( int algo, unsigned nbits, MPI *skey, MPI **retfactors );
+ int (*generate)(int algo, unsigned int nbits, unsigned long use_e,
+ MPI *skey, MPI **retfactors );
int (*check_secret_key)( int algo, MPI *skey );
int (*encrypt)( int algo, MPI *resarr, MPI data, MPI *pkey );
int (*decrypt)( int algo, MPI *result, MPI *data, MPI *skey );
@@ -111,7 +112,8 @@ static int pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey,
int (*cmp)(void *, MPI), void *opaque );
static int
-dummy_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
+dummy_generate( int algo, unsigned int nbits, unsigned long dummy,
+ MPI *skey, MPI **retfactors )
{ log_bug("no generate() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
static int
@@ -488,14 +490,15 @@ pubkey_get_nenc( int algo )
static int
-pubkey_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
+pubkey_generate( int algo, unsigned int nbits, unsigned long use_e,
+ MPI *skey, MPI **retfactors )
{
int i;
do {
for(i=0; pubkey_table[i].name; i++ )
if( pubkey_table[i].algo == algo )
- return (*pubkey_table[i].generate)( algo, nbits,
+ return (*pubkey_table[i].generate)( algo, nbits, use_e,
skey, retfactors );
} while( load_pubkey_modules() );
return GCRYERR_INV_PK_ALGO;
@@ -860,9 +863,11 @@ sexp_to_sig( GCRY_SEXP sexp, MPI **retarray, int *retalgo)
* ...
* (<param_namen> <mpi>)
* ))
+ * 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_want_pkcs1)
+sexp_to_enc( GCRY_SEXP sexp, MPI **retarray, int *retalgo,
+ int *ret_modern, int *ret_want_pkcs1)
{
GCRY_SEXP list, l2;
const char *name;
@@ -874,6 +879,7 @@ sexp_to_enc( GCRY_SEXP sexp, MPI **retarray, int *retalgo, int *ret_want_pkcs1)
GCRY_MPI *array;
*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 )
@@ -893,6 +899,7 @@ sexp_to_enc( GCRY_SEXP sexp, MPI **retarray, int *retalgo, int *ret_want_pkcs1)
/* There is a flags element - process it */
const char *s;
+ *ret_modern = 1;
for (i=gcry_sexp_length (l2)-1; i > 0; i--)
{
s = gcry_sexp_nth_data (l2, i, &n);
@@ -1335,34 +1342,38 @@ gcry_pk_encrypt (GCRY_SEXP *r_ciph, GCRY_SEXP s_data, GCRY_SEXP s_pkey)
/****************
* Do a PK decrypt operation
*
- * Caller has to provide a secret key as the SEXP skey and data in a format
- * as created by gcry_pk_encrypt. Currently the function returns
- * simply a MPI. Later versions of this functions may return a more
- * complex data structure.
- *
+ * Caller has to provide a secret key as the SEXP skey and data in a
+ * format as created by gcry_pk_encrypt. For historic reasons the
+ * function returns simply an MPI as an S-expression part; this is
+ * deprecated and the new method should be used which returns a real
+ * S-expressionl this is selected by adding at least an empt flags
+ * list to S_DATA.
+ *
* Returns: 0 or an errorcode.
*
* s_data = (enc-val
+ * [(flags)]
* (<algo>
* (<param_name1> <mpi>)
* ...
* (<param_namen> <mpi>)
* ))
* s_skey = <key-as-defined-in-sexp_to_key>
- * r_plain= (<mpi>) FIXME: Return a more structered value
- */
+ * r_plain= Either an incomplete S-expression without the parentheses
+ * 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 )
{
MPI *skey, *data, plain;
- int rc, algo, dataalgo, want_pkcs1;
+ int rc, algo, dataalgo, modern, want_pkcs1;
*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, &want_pkcs1 );
+ rc = sexp_to_enc( s_data, &data, &dataalgo, &modern, &want_pkcs1 );
if( rc ) {
release_mpi_array( skey );
gcry_free (skey);
@@ -1373,7 +1384,7 @@ gcry_pk_decrypt( GCRY_SEXP *r_plain, GCRY_SEXP s_data, GCRY_SEXP s_skey )
gcry_free (skey);
release_mpi_array( data );
gcry_free (data);
- return -1; /* fixme: add real errornumber - algo does not match */
+ return GCRYERR_CONFLICT; /* key algo does not match data algo */
}
rc = pubkey_decrypt( algo, &plain, data, skey );
@@ -1382,11 +1393,18 @@ gcry_pk_decrypt( GCRY_SEXP *r_plain, GCRY_SEXP s_data, GCRY_SEXP s_skey )
gcry_free (skey);
release_mpi_array( data );
gcry_free (data);
- return -1; /* fixme: add real errornumber - decryption failed */
+ return GCRYERR_GENERAL; /* decryption failed */
}
- if ( gcry_sexp_build( r_plain, NULL, "%m", plain ) )
+ 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 );
@@ -1550,7 +1568,7 @@ gcry_pk_verify( GCRY_SEXP s_sig, GCRY_SEXP s_hash, GCRY_SEXP s_pkey )
gcry_free (pkey);
release_mpi_array( sig );
gcry_free (sig);
- return -1; /* fixme: add real errornumber - algo does not match */
+ return GCRYERR_CONFLICT; /* algo does not match */
}
rc = sexp_data_to_mpi (s_hash, gcry_pk_get_nbits (s_pkey), &hash, 0);
@@ -1559,7 +1577,7 @@ gcry_pk_verify( GCRY_SEXP s_sig, GCRY_SEXP s_hash, GCRY_SEXP s_pkey )
gcry_free (pkey);
release_mpi_array( sig );
gcry_free (sig);
- return -1; /* fixme: get a real errorcode for this */
+ return rc;
}
rc = pubkey_verify( algo, hash, sig, pkey, NULL, NULL );
@@ -1647,6 +1665,7 @@ gcry_pk_genkey( GCRY_SEXP *r_key, GCRY_SEXP s_parms )
char sec_elems[20], pub_elems[20];
GCRY_MPI skey[10], *factors;
unsigned int nbits;
+ unsigned long use_e;
*r_key = NULL;
list = gcry_sexp_find_token( s_parms, "genkey", 0 );
@@ -1688,6 +1707,27 @@ gcry_pk_genkey( GCRY_SEXP *r_key, GCRY_SEXP s_parms )
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. */
+
l2 = gcry_sexp_find_token( list, "nbits", 0 );
gcry_sexp_release ( list );
list = l2;
@@ -1707,7 +1747,7 @@ gcry_pk_genkey( GCRY_SEXP *r_key, GCRY_SEXP s_parms )
}
gcry_sexp_release ( list );
- rc = pubkey_generate( algo, nbits, skey, &factors );
+ rc = pubkey_generate( algo, nbits, use_e, skey, &factors );
if( rc ) {
return rc;
}
diff --git a/cipher/rsa.c b/cipher/rsa.c
index 0487b736..a8097be2 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 Free Software Foundation, Inc.
+ * Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
*
@@ -51,7 +51,8 @@ typedef struct {
static void test_keys( RSA_secret_key *sk, unsigned nbits );
-static void generate( RSA_secret_key *sk, unsigned nbits );
+static void generate (RSA_secret_key *sk,
+ unsigned int nbits, unsigned long use_e );
static int check_secret_key( RSA_secret_key *sk );
static void public(MPI output, MPI input, RSA_public_key *skey );
static void secret(MPI output, MPI input, RSA_secret_key *skey );
@@ -83,11 +84,15 @@ test_keys( RSA_secret_key *sk, unsigned nbits )
}
/****************
- * Generate a key pair with a key of size NBITS
+ * Generate a key pair with a key of size NBITS.
+ * USE_E = 0 let Libcgrypt decide what exponent to use.
+ * = 1 request the use of a "secure" exponent; this is required by some
+ * specification to be 65537.
+ * > 2 Try starting at this value until a working exponent is found.
* Returns: 2 structures filled with all needed values
*/
static void
-generate( RSA_secret_key *sk, unsigned nbits )
+generate (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e)
{
MPI p, q; /* the two primes */
MPI d; /* the private key */
@@ -140,20 +145,17 @@ generate( RSA_secret_key *sk, unsigned nbits )
e=41 0.75 ms
e=257 0.95 ms
e=65537 1.80 ms
-
- Note: Due to Sphinx requirements we temorrary change the
- exponent until we can rework the interface to provide more
- parameters than just the modulus length. */
+ */
e = mpi_alloc( (32+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB );
- mpi_set_ui (e, 65537);
- if( !gcry_mpi_gcd(t1, e, phi) ) { /* actually never triggered ;-) */
- mpi_set_ui( e, 257);
- if( !gcry_mpi_gcd(t1, e, phi) ) {
- mpi_set_ui( e, 41);
- while( !gcry_mpi_gcd(t1, e, phi) ) /* (while gcd is not 1) */
- mpi_add_ui( e, e, 2);
- }
- }
+ if (!use_e)
+ use_e = 41; /* This is a reasonable secure and fast value */
+ else if (use_e == 1)
+ use_e = 65537; /* A secure value as demanded by Spinx. */
+
+ use_e |= 1; /* make sure this is odd */
+ mpi_set_ui (e, use_e);
+ while (!gcry_mpi_gcd(t1, e, phi)) /* (while gcd is not 1) */
+ mpi_add_ui (e, e, 2);
/* calculate the secret key d = e^1 mod phi */
d = gcry_mpi_snew ( nbits );
@@ -350,14 +352,15 @@ secret(MPI output, MPI input, RSA_secret_key *skey )
*********************************************/
int
-_gcry_rsa_generate (int algo, unsigned int nbits, MPI *skey, MPI **retfactors)
+_gcry_rsa_generate (int algo, unsigned int nbits, unsigned long use_e,
+ MPI *skey, MPI **retfactors)
{
RSA_secret_key sk;
if( !is_RSA(algo) )
return GCRYERR_INV_PK_ALGO;
- generate( &sk, nbits );
+ generate( &sk, nbits, use_e );
skey[0] = sk.n;
skey[1] = sk.e;
skey[2] = sk.d;
diff --git a/cipher/rsa.h b/cipher/rsa.h
index e709757a..8bd77f66 100644
--- a/cipher/rsa.h
+++ b/cipher/rsa.h
@@ -21,7 +21,8 @@
#ifndef G10_RSA_H
#define G10_RSA_H
-int _gcry_rsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors );
+int _gcry_rsa_generate( int algo, unsigned int nbits, unsigned long use_e,
+ MPI *skey, MPI **retfactors );
int _gcry_rsa_check_secret_key( int algo, MPI *skey );
int _gcry_rsa_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey );
int _gcry_rsa_decrypt( int algo, MPI *result, MPI *data, MPI *skey );