* rsa.c (generate): New arg USE_E to request a specific public
authorWerner Koch <wk@gnupg.org>
Thu, 23 Jan 2003 13:04:43 +0000 (13:04 +0000)
committerWerner Koch <wk@gnupg.org>
Thu, 23 Jan 2003 13:04:43 +0000 (13:04 +0000)
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.

cipher/ChangeLog
cipher/dsa.c
cipher/dsa.h
cipher/dynload.c
cipher/dynload.h
cipher/elgamal.c
cipher/elgamal.h
cipher/pubkey.c
cipher/rsa.c
cipher/rsa.h

index dac938b..c6f1fff 100644 (file)
@@ -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
index d8ec37b..61d0c37 100644 (file)
@@ -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;
 
index ce8acda..6789ec6 100644 (file)
@@ -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,
index 711468a..4f00a1e 100644 (file)
@@ -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 * ),
index 9c89cc0..9258352 100644 (file)
@@ -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 ),
index d982c6a..ea3a8dd 100644 (file)
@@ -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;
 
index f192022..ae9f296 100644 (file)
@@ -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 );
index 0fb6113..d0a493d 100644 (file)
@@ -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;
     }
index 0487b73..a8097be 100644 (file)
@@ -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;
index e709757..8bd77f6 100644 (file)
@@ -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 );