[git] GnuPG - branch, ECC-INTEGRATION-2-1, updated. gnupg-2.1.0beta1-62-gd879c28

by Werner Koch cvs at cvs.gnupg.org
Tue Jan 25 20:52:18 CET 2011


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU Privacy Guard".

The branch, ECC-INTEGRATION-2-1 has been updated
       via  d879c287ac1da7990c97b911018d63410c60433c (commit)
       via  302c5a826c0fd0b2aab85ad3c287b65429db2066 (commit)
       via  638dca5dbc7e119ff5a05dbdb109fbc171624605 (commit)
      from  b9958bba10f40a348d40c173701d15cb6b0a7f66 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit d879c287ac1da7990c97b911018d63410c60433c
Author: Werner Koch <wk at gnupg.org>
Date:   Tue Jan 25 20:28:25 2011 +0100

    Started with some code cleanups in ECDH.
    
    The goal is to have the ECDH code more uniform with the other
    algorithms.  Also make error messages and variable names more similar
    to other places.

diff --git a/g10/ChangeLog b/g10/ChangeLog
index 3ce4d1f..9e1aa01 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -3,6 +3,9 @@
 	* ecdh.c (pk_ecdh_default_params_to_mpi): Remove.
 	(pk_ecdh_default_params): Rewrite.  Factor KEK table out to ..
 	(kek_params_table): .. here.
+	(pk_ecdh_generate_ephemeral_key): New.
+	(pk_ecdh_encrypt): Remove.
+	(pk_ecdh_encrypt_with_shared_point): Make public.
 
 	* pubkey-enc.c (get_it): Fix assertion.
 	Use GPG_ERR_WRONG_SECKEY instead of log_fatal.  Add safety checks
diff --git a/g10/ecdh.c b/g10/ecdh.c
index 1fa36aa..71c32fd 100644
--- a/g10/ecdh.c
+++ b/g10/ecdh.c
@@ -87,20 +87,26 @@ pk_ecdh_default_params (unsigned int qbits, size_t *sizeout)
 }
 
 
-/* Encrypts/decrypts 'data' with a key derived from shared_mpi ECC
- * point using FIPS SP 800-56A compliant method, which is key
- * derivation + key wrapping. The direction is determined by the first
- * parameter (is_encrypt=1 --> this is encryption).  The result is
- * returned in out as a size+value MPI.
- *
- * TODO: memory leaks (x_secret).
+/* Encrypts/decrypts DATA using a key derived from the ECC shared
+   point SHARED_MPI using the FIPS SP 800-56A compliant method
+   key_derivation+key_wrapping.  If IS_ENCRYPT is true the function
+   encrypts; if false, it decrypts.  On success the result is stored
+   at R_RESULT; on failure NULL is stored at R_RESULT and an error
+   code returned. 
+
+   FIXME: explain PKEY and PK_FP.
  */
-static int
+ 
+/*
+   TODO: memory leaks (x_secret).
+*/
+gpg_error_t
 pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi, 
                                    const byte pk_fp[MAX_FINGERPRINT_LEN],
                                    gcry_mpi_t data, gcry_mpi_t *pkey,
-                                   gcry_mpi_t *out)
+                                   gcry_mpi_t *r_result)
 {
+  gpg_error_t err;
   byte *secret_x;
   int secret_x_size;
   byte kdf_params[256];
@@ -108,47 +114,54 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
   int nbits;
   int kdf_hash_algo;
   int kdf_encr_algo;
-  int rc;
 
-  *out = NULL;
+  *r_result = NULL;
 
-  nbits = pubkey_nbits( PUBKEY_ALGO_ECDH, pkey );
+  nbits = pubkey_nbits (PUBKEY_ALGO_ECDH, pkey);
+  if (!nbits)
+    return gpg_error (GPG_ERR_TOO_SHORT);
 
   {
     size_t nbytes;
+
     /* Extract x component of the shared point: this is the actual
-       shared secret */
+       shared secret. */
     nbytes = (mpi_get_nbits (pkey[1] /* public point */)+7)/8;
-    secret_x = xmalloc_secure( nbytes );
-    rc = gcry_mpi_print (GCRYMPI_FMT_USG, secret_x, nbytes,
-                         &nbytes, shared_mpi);
-    if (rc)
+    secret_x = xtrymalloc_secure (nbytes);
+    if (!secret_x)
+      return gpg_error_from_syserror ();
+
+    err = gcry_mpi_print (GCRYMPI_FMT_USG, secret_x, nbytes,
+                          &nbytes, shared_mpi);
+    if (err)
       {
         xfree (secret_x);
-        log_error ("ec ephemeral export of shared point failed: %s\n",
-                   gpg_strerror (rc));
-        return rc;
+        log_error ("ECDH ephemeral export of shared point failed: %s\n",
+                   gpg_strerror (err));
+        return err;
       }
+
+    /* fixme: explain what we are doing.  */
     secret_x_size = (nbits+7)/8; 
     assert (nbytes > secret_x_size);
     memmove (secret_x, secret_x+1, secret_x_size);
     memset (secret_x+secret_x_size, 0, nbytes-secret_x_size);
 
     if (DBG_CIPHER)
-      log_printhex ("ecdh shared secret X is:", secret_x, secret_x_size );
+      log_printhex ("ECDH shared secret X is:", secret_x, secret_x_size );
   }
 
   /*** We have now the shared secret bytes in secret_x. ***/
 
   /* At this point we are done with PK encryption and the rest of the
    * function uses symmetric key encryption techniques to protect the
-   * input 'data'.  The following two sections will simply replace
+   * input DATA.  The following two sections will simply replace
    * current secret_x with a value derived from it.  This will become
    * a KEK.
    */
   {
     IOBUF obuf = iobuf_temp(); 
-    rc = iobuf_write_size_body_mpi ( obuf, pkey[2]  );	/* KEK params */
+    err = iobuf_write_size_body_mpi ( obuf, pkey[2]  );	/* KEK params */
     
     kdf_params_size = iobuf_temp_to_buffer (obuf,
                                             kdf_params, sizeof(kdf_params));
@@ -185,11 +198,11 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
 
     obuf = iobuf_temp();
     /* variable-length field 1, curve name OID */
-    rc = iobuf_write_size_body_mpi ( obuf, pkey[0] );
+    err = iobuf_write_size_body_mpi ( obuf, pkey[0] );
     /* fixed-length field 2 */
     iobuf_put (obuf, PUBKEY_ALGO_ECDH);
     /* variable-length field 3, KDF params */
-    rc = (rc ? rc : iobuf_write_size_body_mpi ( obuf, pkey[2] ));
+    err = (err ? err : iobuf_write_size_body_mpi ( obuf, pkey[2] ));
     /* fixed-length field 4 */
     iobuf_write (obuf, "Anonymous Sender    ", 20);
     /* fixed-length field 5, recipient fp */
@@ -198,8 +211,8 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
     kdf_params_size = iobuf_temp_to_buffer (obuf,
                                             kdf_params, sizeof(kdf_params));
     iobuf_close (obuf);
-    if (rc)
-      return rc;
+    if (err)
+      return err;
 
     if(DBG_CIPHER)
       log_printhex ("ecdh KDF message params are:",
@@ -211,10 +224,10 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
     gcry_md_hd_t h;
     int old_size;
 
-    rc = gcry_md_open (&h, kdf_hash_algo, 0);
-    if(rc)
+    err = gcry_md_open (&h, kdf_hash_algo, 0);
+    if(err)
   	log_bug ("gcry_md_open failed for algo %d: %s",
-			kdf_hash_algo, gpg_strerror (gcry_error(rc)));
+			kdf_hash_algo, gpg_strerror (gcry_error(err)));
     gcry_md_write(h, "\x00\x00\x00\x01", 4);	/* counter = 1 */
     gcry_md_write(h, secret_x, secret_x_size);	/* x of the point X */
     gcry_md_write(h, kdf_params, kdf_params_size);	/* KDF parameters */
@@ -248,22 +261,22 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
 
     gcry_mpi_t result;
 
-    rc = gcry_cipher_open (&hd, kdf_encr_algo, GCRY_CIPHER_MODE_AESWRAP, 0);
-    if (rc)
+    err = gcry_cipher_open (&hd, kdf_encr_algo, GCRY_CIPHER_MODE_AESWRAP, 0);
+    if (err)
       {
         log_error ("ecdh failed to initialize AESWRAP: %s\n",
-                   gpg_strerror (rc));
-        return rc;
+                   gpg_strerror (err));
+        return err;
       }
 
-    rc = gcry_cipher_setkey (hd, secret_x, secret_x_size);
+    err = gcry_cipher_setkey (hd, secret_x, secret_x_size);
     xfree( secret_x );
-    if (rc)
+    if (err)
       {
         gcry_cipher_close (hd);
         log_error ("ecdh failed in gcry_cipher_setkey: %s\n",
-                   gpg_strerror (rc));
-        return rc;
+                   gpg_strerror (err));
+        return err;
       }
 
     data_buf_size = (gcry_mpi_get_nbits(data)+7)/8;
@@ -282,52 +295,52 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
         
         /* Write data MPI into the end of data_buf. data_buf is size
            aeswrap data.  */
-        rc = gcry_mpi_print (GCRYMPI_FMT_USG, in,
+        err = gcry_mpi_print (GCRYMPI_FMT_USG, in,
                              data_buf_size, &nbytes, data/*in*/);
-        if (rc)
+        if (err)
           {
-            log_error ("ecdh failed to export DEK: %s\n", gpg_strerror (rc));
+            log_error ("ecdh failed to export DEK: %s\n", gpg_strerror (err));
             gcry_cipher_close (hd);
             xfree (data_buf);
-            return rc;
+            return err;
           }
         
         if (DBG_CIPHER)
           log_printhex ("ecdh encrypting  :", in, data_buf_size );
 
-        rc = gcry_cipher_encrypt (hd, data_buf+1, data_buf_size+8,
+        err = gcry_cipher_encrypt (hd, data_buf+1, data_buf_size+8,
                                   in, data_buf_size);
         memset (in, 0, data_buf_size);
         gcry_cipher_close (hd);
-        if (rc)
+        if (err)
           {
             log_error ("ecdh failed in gcry_cipher_encrypt: %s\n",
-                       gpg_strerror (rc));
+                       gpg_strerror (err));
             xfree (data_buf);
-            return rc;
+            return err;
           }
         data_buf[0] = data_buf_size+8;
 
         if (DBG_CIPHER)
          log_printhex ("ecdh encrypted to:", data_buf+1, data_buf[0] );
 
-        rc = gcry_mpi_scan (&result, GCRYMPI_FMT_USG,
+        err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG,
                             data_buf, 1+data_buf[0], NULL); 
         /* (byte)size + aeswrap of DEK */
         xfree( data_buf );
-        if (rc)
+        if (err)
           {
-            log_error ("ecdh failed to create an MPI: %s\n", gpg_strerror (rc));
-            return rc;
+            log_error ("ecdh failed to create an MPI: %s\n", gpg_strerror (err));
+            return err;
           }
         
-        *out = result;
+        *r_result = result;
       }
     else
       {
         byte *in;
         
-        rc = gcry_mpi_print (GCRYMPI_FMT_USG, data_buf, data_buf_size,
+        err = gcry_mpi_print (GCRYMPI_FMT_USG, data_buf, data_buf_size,
                              &nbytes, data/*in*/);
       if (nbytes != data_buf_size || data_buf[0] != data_buf_size-1)
         {
@@ -341,15 +354,15 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
       if (DBG_CIPHER)
         log_printhex ("ecdh decrypting :", data_buf+1, data_buf_size);
       
-      rc = gcry_cipher_decrypt (hd, in, data_buf_size, data_buf+1,
+      err = gcry_cipher_decrypt (hd, in, data_buf_size, data_buf+1,
                                 data_buf_size);
       gcry_cipher_close (hd);
-      if (rc)
+      if (err)
         {
           log_error ("ecdh failed in gcry_cipher_decrypt: %s\n",
-                     gpg_strerror (rc));
+                     gpg_strerror (err));
           xfree (data_buf);
-          return rc;
+          return err;
         }
 
       data_buf_size -= 8;
@@ -365,20 +378,20 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
       /*     return GPG_ERR_BAD_KEY; */
       /*   } */
  
-      rc = gcry_mpi_scan ( &result, GCRYMPI_FMT_USG, in, data_buf_size, NULL);
+      err = gcry_mpi_scan ( &result, GCRYMPI_FMT_USG, in, data_buf_size, NULL);
       xfree (data_buf);
-      if (rc)
+      if (err)
         {
           log_error ("ecdh failed to create a plain text MPI: %s\n",
-                     gpg_strerror (rc));
-          return rc;
+                     gpg_strerror (err));
+          return err;
         }
       
-      *out = result;
+      *r_result = result;
       }
   }
   
-  return rc;
+  return err;
 }
 
 
@@ -405,76 +418,31 @@ gen_k (unsigned nbits)
   return k;
 }
 
-/* Perform ECDH encryption, which involves ECDH key generation.  */
-int
-pk_ecdh_encrypt (gcry_mpi_t *resarr, const byte pk_fp[MAX_FINGERPRINT_LEN],
-                 gcry_mpi_t data, gcry_mpi_t * pkey)
-{
-  gcry_sexp_t s_ciph, s_data, s_pkey;
 
-  int nbits;
-  int rc;
+/* Generate an ephemeral key for the public ECDH key in PKEY.  On
+   success the generated key is stored at R_K; on failure NULL is
+   stored at R_K and an error code returned.  */
+gpg_error_t
+pk_ecdh_generate_ephemeral_key (gcry_mpi_t *pkey, gcry_mpi_t *r_k)
+{
+  unsigned int nbits;
   gcry_mpi_t k;
 
-  nbits = pubkey_nbits (PUBKEY_ALGO_ECDH, pkey);
-
-  /*** Generate an ephemeral key, actually, a scalar. ***/
+  *r_k = NULL;
 
+  nbits = pubkey_nbits (PUBKEY_ALGO_ECDH, pkey);
+  if (!nbits)
+    return gpg_error (GPG_ERR_TOO_SHORT);
   k = gen_k (nbits);
-  if( k == NULL )
+  if (!k)
     BUG ();
 
-  /*** Done with ephemeral key generation. 
-   * Now use ephemeral secret to get the shared secret. ***/
-
-  rc = gcry_sexp_build (&s_pkey, NULL,
-                        "(public-key(ecdh(c%m)(q%m)(p%m)))",
-                        pkey[0], pkey[1], pkey[2]);
-  if (rc)
-    BUG ();
- 
-  /* Put the data into a simple list. */
-  /* Ephemeral scalar goes as data.  */
-  if (gcry_sexp_build (&s_data, NULL, "%m", k))
-    BUG ();
-
-  /* Pass it to libgcrypt. */
-  rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
-  gcry_sexp_release (s_data);
-  gcry_sexp_release (s_pkey);
-  if (rc)
-    return rc;
-
-  /* Finally, perform encryption.  */
-
-  {
-    /* ... and get the shared point/ */
-    gcry_mpi_t shared;
-
-    shared = mpi_from_sexp (s_ciph, "a"); 
-    gcry_sexp_release (s_ciph);
-    /* Ephemeral public key. */
-    resarr[0] = mpi_from_sexp (s_ciph, "b");
-
-    if (DBG_CIPHER)
-      {
-	unsigned char *buffer;
-
-	if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, resarr[0]))
-          BUG ();
-        log_debug("ephemeral key MPI: %s\n", buffer);
-	gcry_free( buffer );
-      }
-    
-    rc = pk_ecdh_encrypt_with_shared_point (1 /*=encrypton*/, shared,
-                                            pk_fp, data, pkey, resarr+1);
-    mpi_release (shared);
-  }
-  
-  return rc;
+  *r_k = k;
+  return 0;
 }
 
 
+
 /* Perform ECDH decryption.   */
 int
 pk_ecdh_decrypt (gcry_mpi_t * result, const byte sk_fp[MAX_FINGERPRINT_LEN],
diff --git a/g10/misc.c b/g10/misc.c
index bdd797c..fd00ec6 100644
--- a/g10/misc.c
+++ b/g10/misc.c
@@ -1423,7 +1423,7 @@ pubkey_nbits( int algo, gcry_mpi_t *key )
     int rc, nbits;
     gcry_sexp_t sexp;
 
-#warning Why this assert
+#warning FIXME:  We are mixing OpenPGP And CGrypt Ids
     assert( algo != GCRY_PK_ECDSA && algo != GCRY_PK_ECDH );
 
     if( algo == GCRY_PK_DSA ) {
diff --git a/g10/pkglue.c b/g10/pkglue.c
index f5c8597..3aba4e4 100644
--- a/g10/pkglue.c
+++ b/g10/pkglue.c
@@ -28,6 +28,7 @@
 #include "util.h"
 #include "pkglue.h"
 #include "main.h"
+#include "options.h"
 
 /* FIXME: Better chnage the fucntion name because mpi_ is used by
    gcrypt macros.  */
@@ -156,26 +157,39 @@ pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
       rc = gcry_sexp_build (&s_pkey, NULL,
 			    "(public-key(elg(p%m)(g%m)(y%m)))",
 			    pkey[0], pkey[1], pkey[2]);
+      /* Put DATA into a simplified S-expression.  */
+      if (rc || gcry_sexp_build (&s_data, NULL, "%m", data))
+        BUG ();
+
     }
   else if (algo == GCRY_PK_RSA || algo == GCRY_PK_RSA_E)
     {
       rc = gcry_sexp_build (&s_pkey, NULL,
 			    "(public-key(rsa(n%m)(e%m)))",
 			    pkey[0], pkey[1]);
+      /* Put DATA into a simplified S-expression.  */
+      if (rc || gcry_sexp_build (&s_data, NULL, "%m", data))
+        BUG ();
     }
   else if (algo == PUBKEY_ALGO_ECDH)	
     {
-      return pk_ecdh_encrypt (resarr, pk_fp, data, pkey);
+      gcry_mpi_t k;
+
+      rc = pk_ecdh_generate_ephemeral_key (pkey, &k);
+      if (rc)
+        return rc;
+      
+      /* Now use the ephemeral secret to compute the shared point.  */
+      rc = gcry_sexp_build (&s_pkey, NULL,
+                            "(public-key(ecdh(c%m)(q%m)(p%m)))",
+                            pkey[0], pkey[1], pkey[2]);
+      /* Put K into a simplified S-expression.  */
+      if (rc || gcry_sexp_build (&s_data, NULL, "%m", k))
+        BUG ();
     }
   else
-    return GPG_ERR_PUBKEY_ALGO;
-
-  if (rc)
-    BUG ();
+    return gpg_error (GPG_ERR_PUBKEY_ALGO);
 
-  /* Put the data into a simple list.  */
-  if (gcry_sexp_build (&s_data, NULL, "%m", data))
-    BUG ();
 
   /* Pass it to libgcrypt. */
   rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
@@ -184,12 +198,42 @@ pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
 
   if (rc)
     ;
-  else
-    { /* Add better error handling or make gnupg use S-Exp directly.  */
+  else if (algo == PUBKEY_ALGO_ECDH)	
+    {
+      gcry_mpi_t shared, public, result;
+
+      /* Get the shared point and the ephemeral public key.  */
+      shared = mpi_from_sexp (s_ciph, "a"); 
+      public = mpi_from_sexp (s_ciph, "b");
+      gcry_sexp_release (s_ciph);
+      s_ciph = NULL;
+      if (DBG_CIPHER)
+        {
+          log_debug ("ECDH ephemeral key:");
+          gcry_mpi_dump (public);
+          log_printf ("\n");
+        }
+    
+      result = NULL;
+      rc = pk_ecdh_encrypt_with_shared_point (1 /*=encrypton*/, shared,
+                                              pk_fp, data, pkey, &result);
+      gcry_mpi_release (shared);
+      if (!rc)
+        {
+          resarr[0] = public;
+          resarr[1] = result;
+        }
+      else
+        {
+          gcry_mpi_release (public);
+          gcry_mpi_release (result);
+        }
+    }
+  else /* Elgamal or RSA case.  */
+    { /* Fixme: Add better error handling or make gnupg use
+         S-expressions directly.  */
       resarr[0] = mpi_from_sexp (s_ciph, "a");
-      if (algo != GCRY_PK_RSA 
-          && algo != GCRY_PK_RSA_E
-          && algo != PUBKEY_ALGO_ECDH)
+      if (algo != GCRY_PK_RSA && algo != GCRY_PK_RSA_E)
         resarr[1] = mpi_from_sexp (s_ciph, "b");
     }
 
diff --git a/g10/pkglue.h b/g10/pkglue.h
index b1cfbe5..98d8c14 100644
--- a/g10/pkglue.h
+++ b/g10/pkglue.h
@@ -33,6 +33,13 @@ int pk_check_secret_key (int algo, gcry_mpi_t *skey);
 
 /*-- ecdh.c --*/
 byte *pk_ecdh_default_params (unsigned int qbits, size_t *sizeout);
+gpg_error_t pk_ecdh_generate_ephemeral_key (gcry_mpi_t *pkey, gcry_mpi_t *r_k);
+gpg_error_t pk_ecdh_encrypt_with_shared_point
+/*         */  (int is_encrypt, gcry_mpi_t shared_mpi, 
+                const byte pk_fp[MAX_FINGERPRINT_LEN],
+                gcry_mpi_t data, gcry_mpi_t *pkey,
+                gcry_mpi_t *out);
+
 int pk_ecdh_encrypt (gcry_mpi_t *resarr, const byte pk_fp[MAX_FINGERPRINT_LEN],
                      gcry_mpi_t data, gcry_mpi_t * pkey);
 int pk_ecdh_decrypt (gcry_mpi_t *result, const byte sk_fp[MAX_FINGERPRINT_LEN],

commit 302c5a826c0fd0b2aab85ad3c287b65429db2066
Author: Werner Koch <wk at gnupg.org>
Date:   Tue Jan 25 17:48:51 2011 +0100

    More ECDH code cleanups

diff --git a/g10/ChangeLog b/g10/ChangeLog
index 8011464..3ce4d1f 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,5 +1,9 @@
 2011-01-25  Werner Koch  <wk at g10code.com>
 
+	* ecdh.c (pk_ecdh_default_params_to_mpi): Remove.
+	(pk_ecdh_default_params): Rewrite.  Factor KEK table out to ..
+	(kek_params_table): .. here.
+
 	* pubkey-enc.c (get_it): Fix assertion.
 	Use GPG_ERR_WRONG_SECKEY instead of log_fatal.  Add safety checks
 	for NFRAME.
@@ -14,6 +18,8 @@
 	(pk_ecc_keypair_gen): Fold it into ..
 	(gen_ecc): .. this.
 	(ask_keysize): Use proper rounding for ECC.
+	(pk_ecc_build_key_params): Remove NBITSSTR.
+
 	* verify-stubs.c: Remove.
 
 2011-01-20  Werner Koch  <wk at g10code.com>
diff --git a/g10/ecdh.c b/g10/ecdh.c
index cb251fe..1fa36aa 100644
--- a/g10/ecdh.c
+++ b/g10/ecdh.c
@@ -30,26 +30,15 @@
 #include "main.h"
 #include "options.h"
 
-gcry_mpi_t
-pk_ecdh_default_params_to_mpi (int qbits)
+/* A table with the default KEK parameters used by GnuPG.  */
+static const struct
 {
-  gpg_error_t err;
-  gcry_mpi_t result;
-  /* Defaults are the strongest possible choices. Performance is not
-     an issue here, only interoperability.  */
-  byte kek_params[4] = { 
-	3	/*size of following field*/, 
-	1	/*fixed version for KDF+AESWRAP*/, 
-	DIGEST_ALGO_SHA512	/* KEK MD */, 
-	CIPHER_ALGO_AES256 	/*KEK AESWRAP alg*/
-  };
-  int i;
-
-  static const struct {
-    int qbits;
-    int openpgp_hash_id;
-    int openpgp_cipher_id;
-  } kek_params_table[] = {
+  unsigned int qbits;
+  int openpgp_hash_id;   /* KEK digest algorithm. */
+  int openpgp_cipher_id; /* KEK cipher algorithm. */
+} kek_params_table[] = 
+  /* Note: Must be sorted by ascending values for QBITS.  */
+  {
     { 256, DIGEST_ALGO_SHA256, CIPHER_ALGO_AES    },
     { 384, DIGEST_ALGO_SHA384, CIPHER_ALGO_AES256 },
 
@@ -57,77 +46,44 @@ pk_ecdh_default_params_to_mpi (int qbits)
     { 528, DIGEST_ALGO_SHA512, CIPHER_ALGO_AES256 }
   };
 
-  for (i=0; i<sizeof(kek_params_table)/sizeof(kek_params_table[0]); i++)
-    {
-      if (kek_params_table[i].qbits >= qbits)
-        {
-          kek_params[2] = kek_params_table[i].openpgp_hash_id;
-          kek_params[3] = kek_params_table[i].openpgp_cipher_id;
-          break;
-        }
-    }
-  if (DBG_CIPHER)
-    log_printhex ("ecdh kek params are", kek_params, sizeof(kek_params) );
-
-  err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG,
-                       kek_params, sizeof(kek_params), NULL);
-  if (err)
-    log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err));
-
-  return result;
-}
 
 
 /* Returns allocated (binary) KEK parameters; the size is returned in
- * sizeout.  The caller must free the returned value with xfree.
- * Returns NULL on error.
- */
+   sizeout.  The caller must free the returned value.  Returns NULL
+   and sets ERRNO on error.  */
 byte *
-pk_ecdh_default_params (int qbits, size_t *sizeout)
+pk_ecdh_default_params (unsigned int qbits, size_t *sizeout)
 {
-  /* Defaults are the strongest possible choices. Performance is not
-     an issue here, only interoperability. */
-  byte kek_params[4] = { 
-	3	/*size of following field*/, 
-	1	/*fixed version for KDF+AESWRAP*/, 
-	DIGEST_ALGO_SHA512	/* KEK MD */, 
-	CIPHER_ALGO_AES256 	/* KEK AESWRAP alg */
-  };
+  byte kek_params[4];
   int i;
-  
-  static const struct {
-    int qbits;
-    int openpgp_hash_id;
-    int openpgp_cipher_id;
-  } kek_params_table[] = {
-    { 256, DIGEST_ALGO_SHA256, CIPHER_ALGO_AES    },
-    { 384, DIGEST_ALGO_SHA384, CIPHER_ALGO_AES256 },
-    /* Note: 528 is 521 rounded to the 8 bit boundary  */
-    { 528, DIGEST_ALGO_SHA512, CIPHER_ALGO_AES256 }	
-  };
-
-  byte *p;
+  byte *buffer;
 
-  *sizeout = 0;
+  kek_params[0] = 3; /* Number of bytes to follow. */
+  kek_params[1] = 1; /* Version for KDF+AESWRAP.   */ 
   
-  for (i=0; i<sizeof(kek_params_table)/sizeof(kek_params_table[0]); i++)
+  /* Search for matching KEK parameter.  Defaults to the strongest
+     possible choices.  Performance is not an issue here, only
+     interoperability.  */
+  for (i=0; i < DIM (kek_params_table); i++)
     {
-      if (kek_params_table[i].qbits >= qbits)
+      if (kek_params_table[i].qbits >= qbits
+          || i+1 == DIM (kek_params_table))
         {
           kek_params[2] = kek_params_table[i].openpgp_hash_id;
           kek_params[3] = kek_params_table[i].openpgp_cipher_id;
           break;
         }
     }
-  if (DBG_CIPHER )
-    log_printhex ("ecdh kek params are", kek_params, sizeof(kek_params));
-
-  p = xtrymalloc (sizeof(kek_params));
-  if (!p)
+  assert (i < DIM (kek_params_table));
+  if (DBG_CIPHER)
+    log_printhex ("ECDH KEK params are", kek_params, sizeof(kek_params) );
+  
+  buffer = xtrymalloc (sizeof(kek_params));
+  if (!buffer)
     return NULL;
-  memcpy (p, kek_params, sizeof(kek_params));
-  *sizeout = sizeof(kek_params);
-  return p;
+  memcpy (buffer, kek_params, sizeof (kek_params));
+  *sizeout = sizeof (kek_params);
+  return buffer;
 }
 
 
diff --git a/g10/keygen.c b/g10/keygen.c
index 366bedf..b42121b 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -1329,7 +1329,7 @@ gen_dsa (unsigned int nbits, KBNODE pub_root,
 
 
 
-/* Create an S-expression string out QBITS, ALGO and the TRANSIENT
+/* Create an S-expression string out of QBITS, ALGO and the TRANSIENT
    flag.  On success a malloced string is returned, on failure NULL
    and ERRNO is set.  */
 static char *
@@ -1337,56 +1337,63 @@ pk_ecc_build_key_params (int qbits, int algo, int transient)
 {
   byte *kek_params = NULL;
   size_t kek_params_size;
-  char nbitsstr[35];
   char qbitsstr[35];
-  char *keyparms;
-  int n;
+  char *result;
+  size_t n;
 
   /* KEK parameters are only needed for long term key generation.  */
   if (!transient && algo == PUBKEY_ALGO_ECDH)
-    kek_params = pk_ecdh_default_params (qbits, &kek_params_size);
+    {
+      kek_params = pk_ecdh_default_params (qbits, &kek_params_size);
+      if (!kek_params)
+        return NULL;
+    }
   else
     kek_params = NULL;
 
-  snprintf (nbitsstr, sizeof nbitsstr, "%u", qbits);
   snprintf (qbitsstr, sizeof qbitsstr, "%u", qbits);
   if (algo == PUBKEY_ALGO_ECDSA || !kek_params)
     {
-      keyparms = xtryasprintf ("(genkey(%s(nbits %zu:%s)"
+      result = xtryasprintf ("(genkey(%s(nbits %zu:%s)"
                                /**/      "(qbits %zu:%s)"
                                /**/      "(transient-key 1:%d)))",
                                algo == PUBKEY_ALGO_ECDSA ? "ecdsa" : "ecdh",
-                               strlen (nbitsstr), nbitsstr,
+                               strlen (qbitsstr), qbitsstr,
                                strlen (qbitsstr), qbitsstr,
                                transient);
     }
   else
     {
-      assert (kek_params);
+      char *tmpstr;
 
-      keyparms = xtryasprintf ("(genkey(ecdh(nbits %zu:%s)"
-                               /**/        "(qbits %zu:%s)"
-                               /**/        "(transient-key 1:%d)"
-                               /**/        "(kek-params %zu:",
-                               strlen (nbitsstr), nbitsstr,
-                               strlen (qbitsstr), qbitsstr,
-                               transient,
-                               kek_params_size);
-      if (keyparms)
+      assert (kek_params);
+      tmpstr = xtryasprintf ("(genkey(ecdh(nbits %zu:%s)"
+                             /**/        "(qbits %zu:%s)"
+                             /**/        "(transient-key 1:%d)"
+                             /**/        "(kek-params %zu:",
+                             strlen (qbitsstr), qbitsstr,
+                             strlen (qbitsstr), qbitsstr,
+                             transient,
+                             kek_params_size);
+      if (!tmpstr)
         {
-          n = strlen (keyparms);
-          keyparms = xtryrealloc (keyparms, n + kek_params_size + 4);
+          xfree (kek_params);
+          return NULL;
         }
-      if (!keyparms)
+      /* Append the binary KEK parmas.  */
+      n = strlen (tmpstr);
+      result = xtryrealloc (tmpstr, n + kek_params_size + 4);
+      if (!result)
         {
+          xfree (tmpstr);
           xfree (kek_params);
           return NULL;
         }
-      memcpy (keyparms+n, kek_params, kek_params_size);
-      xfree (kek_params);
-      memcpy (keyparms+n+kek_params_size, ")))", 4);
+      memcpy (result + n, kek_params, kek_params_size);
+      strcpy (result + n + kek_params_size, ")))");
     }
-  return keyparms;
+  xfree (kek_params);
+  return result;
 }
 
 
diff --git a/g10/pkglue.h b/g10/pkglue.h
index 0ceb43f..b1cfbe5 100644
--- a/g10/pkglue.h
+++ b/g10/pkglue.h
@@ -20,6 +20,7 @@
 #ifndef GNUPG_G10_PKGLUE_H
 #define GNUPG_G10_PKGLUE_H
 
+/*-- pkglue.c --*/
 gcry_mpi_t mpi_from_sexp (gcry_sexp_t sexp, const char * item);
 
 int pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data,
@@ -29,12 +30,13 @@ int pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
                 gcry_mpi_t *pkey);
 int pk_check_secret_key (int algo, gcry_mpi_t *skey);
 
+
+/*-- ecdh.c --*/
+byte *pk_ecdh_default_params (unsigned int qbits, size_t *sizeout);
 int pk_ecdh_encrypt (gcry_mpi_t *resarr, const byte pk_fp[MAX_FINGERPRINT_LEN],
                      gcry_mpi_t data, gcry_mpi_t * pkey);
 int pk_ecdh_decrypt (gcry_mpi_t *result, const byte sk_fp[MAX_FINGERPRINT_LEN],
                      gcry_mpi_t data, gcry_mpi_t shared, gcry_mpi_t * skey);
 
-gcry_mpi_t pk_ecdh_default_params_to_mpi (int qbits);
-byte *pk_ecdh_default_params (int qbits, size_t *sizeout);
 
 #endif /*GNUPG_G10_PKGLUE_H*/

commit 638dca5dbc7e119ff5a05dbdb109fbc171624605
Author: Werner Koch <wk at gnupg.org>
Date:   Tue Jan 25 16:54:18 2011 +0100

    Editorial cleanups of keygen.c
    
    Also fixed a regression introduced by me in pubkey_enc.c.
    Added extra checks.  Removed unused code.

diff --git a/g10/ChangeLog b/g10/ChangeLog
index 4c28363..8011464 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,21 @@
+2011-01-25  Werner Koch  <wk at g10code.com>
+
+	* pubkey-enc.c (get_it): Fix assertion.
+	Use GPG_ERR_WRONG_SECKEY instead of log_fatal.  Add safety checks
+	for NFRAME.
+
+	* main.h (KEYGEN_FLAG_NO_PROTECTION, KEYGEN_FLAG_TRANSIENT_KEY):
+	Move back to ..
+	* keygen.c: .. here.
+	(pk_ecc_keypair_gen): Make static.
+	(common_key_gen): Fold back into ..
+	(common_gen): .. this.
+	(delme__pk_ecc_build_sexp): Remove unused function.
+	(pk_ecc_keypair_gen): Fold it into ..
+	(gen_ecc): .. this.
+	(ask_keysize): Use proper rounding for ECC.
+	* verify-stubs.c: Remove.
+
 2011-01-20  Werner Koch  <wk at g10code.com>
 
 	* keyserver.c: Rewrite most stuff for use with dirmngr.  Get rid
diff --git a/g10/Makefile.am b/g10/Makefile.am
index 5d24702..a28b2ab 100644
--- a/g10/Makefile.am
+++ b/g10/Makefile.am
@@ -111,8 +111,7 @@ gpg2_SOURCES  = gpg.c		\
 
 gpgv2_SOURCES = gpgv.c           \
 	      $(common_source)  \
-	      verify.c          \
-	      verify-stubs.c
+	      verify.c
 
 #gpgd_SOURCES = gpgd.c \
 #	       ks-proto.h \
diff --git a/g10/keygen.c b/g10/keygen.c
index e75da79..366bedf 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -1,6 +1,6 @@
 /* keygen.c - generate a key pair
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- *               2006, 2007, 2009, 2010 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ *               2007, 2009, 2010, 2011  Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -18,7 +18,6 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#warning wk: check these changes.
 #include <config.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -51,6 +50,11 @@
 #define DEFAULT_STD_ALGO    GCRY_PK_RSA
 #define DEFAULT_STD_KEYSIZE 2048
 
+/* Flag bits used during key generation.  */
+#define KEYGEN_FLAG_NO_PROTECTION 1
+#define KEYGEN_FLAG_TRANSIENT_KEY 2
+
+/* Maximum number of supported algorithm preferences.  */
 #define MAX_PREFS 30 
 
 enum para_name {
@@ -1128,16 +1132,17 @@ key_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp,
 }
 
 
+/* Common code for the key generation fucntion gen_xxx.  */
 static int
-common_key_gen (const char *keyparms, int algo, const char *algoelem,
-            int keygen_flags, char **cache_nonce_addr, PKT_public_key **pk_out)
+common_gen (const char *keyparms, int algo, const char *algoelem,
+            kbnode_t pub_root, u32 timestamp, u32 expireval, int is_subkey,
+            int keygen_flags, char **cache_nonce_addr)
 {
   int err;
+  PACKET *pkt;
   PKT_public_key *pk;
   gcry_sexp_t s_key;
 
-  *pk_out = NULL;
-  
   err = agent_genkey (NULL, cache_nonce_addr, keyparms,
                       !!(keygen_flags & KEYGEN_FLAG_NO_PROTECTION), &s_key);
   if (err)
@@ -1154,7 +1159,10 @@ common_key_gen (const char *keyparms, int algo, const char *algoelem,
       return err;
     }
 
+  pk->timestamp = timestamp;
   pk->version = 4;
+  if (expireval) 
+    pk->expiredate = pk->timestamp + expireval;
   pk->pubkey_algo = algo;
 
   err = key_from_sexp (pk->pkey, s_key, "public-key", algoelem);
@@ -1167,45 +1175,21 @@ common_key_gen (const char *keyparms, int algo, const char *algoelem,
     }
   gcry_sexp_release (s_key);
   
-  *pk_out = pk;
+  pkt = xtrycalloc (1, sizeof *pkt);
+  if (!pkt)
+    {
+      err = gpg_error_from_syserror ();
+      free_public_key (pk);
+      return err;
+    }
+
+  pkt->pkttype = is_subkey ? PKT_PUBLIC_SUBKEY : PKT_PUBLIC_KEY;
+  pkt->pkt.public_key = pk;
+  add_kbnode (pub_root, new_kbnode (pkt));
 
   return 0;
 }
 
-/* Common code for the key generation fucntion gen_xxx.  */
-static int
-common_gen (const char *keyparms, int algo, const char *algoelem,
-            kbnode_t pub_root, u32 timestamp, u32 expireval, int is_subkey,
-            int keygen_flags, char **cache_nonce_addr)
-{
-  PKT_public_key *pk;  
-  int err; 
-
-  err = common_key_gen( keyparms, algo, algoelem, keygen_flags, cache_nonce_addr, &pk );
-
-  if( !err )  {
-    PACKET *pkt;
-
-    pk->timestamp = timestamp;
-    if (expireval) 
-      pk->expiredate = pk->timestamp + expireval;
-
-    pkt = xtrycalloc (1, sizeof *pkt);
-    if (!pkt)
-      {
-        err = gpg_error_from_syserror ();
-        free_public_key (pk);
-        return err;
-      }
-
-    pkt->pkttype = is_subkey ? PKT_PUBLIC_SUBKEY : PKT_PUBLIC_KEY;
-    pkt->pkt.public_key = pk;
-
-    add_kbnode (pub_root, new_kbnode (pkt));
-  }
-
-  return err;
-}
 
 /*
  * Generate an Elgamal key.
@@ -1343,40 +1327,14 @@ gen_dsa (unsigned int nbits, KBNODE pub_root,
   return err;
 }
 
-/* Returns allocated ECC key generation S-explression 
-   call gcry_sexp_release ( out ) to free it.
- */
-static int 
-delme__pk_ecc_build_sexp( int qbits, int algo, int is_long_term, gcry_sexp_t *out )  {
-  gcry_mpi_t kek_params;
-  char *kek_params_s;
-  int rc;
 
-  if( is_long_term && algo == PUBKEY_ALGO_ECDH )
-    kek_params = pk_ecdh_default_params_to_mpi( qbits );
-  else
-    kek_params = NULL;
-
-  if( kek_params )  {
-    kek_params_s = mpi2hex( kek_params );
-    mpi_release( kek_params );
-  }
-
-  rc = gcry_sexp_build (out, NULL,
-			algo == PUBKEY_ALGO_ECDSA ? 
-                        "(genkey(ecdsa(nbits %d)(qbits %d)))" : 
-                        "(genkey(ecdh(nbits %d)(qbits %d)(transient-key %d)(kek-params %s)))",
-                        (int)qbits, (int)qbits, (int)(is_long_term==0), kek_params_s);
-  xfree( kek_params_s );
-  if (rc)  {
-    log_debug("ec gen gcry_sexp_build failed: %s\n", gpg_strerror (rc));
-    return rc;
-  }
-  return 0;
-}
 
-static char * 
-pk_ecc_build_key_params( int qbits, int algo, int transient )  {
+/* Create an S-expression string out QBITS, ALGO and the TRANSIENT
+   flag.  On success a malloced string is returned, on failure NULL
+   and ERRNO is set.  */
+static char *
+pk_ecc_build_key_params (int qbits, int algo, int transient)
+{
   byte *kek_params = NULL;
   size_t kek_params_size;
   char nbitsstr[35];
@@ -1384,142 +1342,105 @@ pk_ecc_build_key_params( int qbits, int algo, int transient )  {
   char *keyparms;
   int n;
 
-  /* KEK parameters are only needed for long term key generation */
-  if( !transient && algo == PUBKEY_ALGO_ECDH )
-    kek_params = pk_ecdh_default_params( qbits, &kek_params_size );
+  /* KEK parameters are only needed for long term key generation.  */
+  if (!transient && algo == PUBKEY_ALGO_ECDH)
+    kek_params = pk_ecdh_default_params (qbits, &kek_params_size);
   else
     kek_params = NULL;
 
   snprintf (nbitsstr, sizeof nbitsstr, "%u", qbits);
   snprintf (qbitsstr, sizeof qbitsstr, "%u", qbits);
-  if( algo == PUBKEY_ALGO_ECDSA || kek_params == NULL )
-    keyparms = xtryasprintf (
-		"(genkey(%s(nbits %zu:%s)(qbits %zu:%s)(transient-key 1:%d)))", 
-			   algo == PUBKEY_ALGO_ECDSA ? "ecdsa" : "ecdh",
-                           strlen (nbitsstr), nbitsstr,
-                           strlen (qbitsstr), qbitsstr,
-			   transient );
-  else  {
-    assert( kek_params != NULL );
-    keyparms = xtryasprintf (
-		"(genkey(ecdh(nbits %zu:%s)(qbits %zu:%s)(transient-key 1:%d)(kek-params %u:",
-                           strlen (nbitsstr), nbitsstr,
-                           strlen (qbitsstr), qbitsstr,
-			   transient,
-			   (unsigned)kek_params_size );
-    if( keyparms != NULL )  {
-       n = strlen(keyparms);
-       keyparms = xtryrealloc( keyparms, n + kek_params_size + 4 );
+  if (algo == PUBKEY_ALGO_ECDSA || !kek_params)
+    {
+      keyparms = xtryasprintf ("(genkey(%s(nbits %zu:%s)"
+                               /**/      "(qbits %zu:%s)"
+                               /**/      "(transient-key 1:%d)))",
+                               algo == PUBKEY_ALGO_ECDSA ? "ecdsa" : "ecdh",
+                               strlen (nbitsstr), nbitsstr,
+                               strlen (qbitsstr), qbitsstr,
+                               transient);
     }
-    if( keyparms == NULL )  {
-      xfree( kek_params );
-      return NULL;
+  else
+    {
+      assert (kek_params);
+
+      keyparms = xtryasprintf ("(genkey(ecdh(nbits %zu:%s)"
+                               /**/        "(qbits %zu:%s)"
+                               /**/        "(transient-key 1:%d)"
+                               /**/        "(kek-params %zu:",
+                               strlen (nbitsstr), nbitsstr,
+                               strlen (qbitsstr), qbitsstr,
+                               transient,
+                               kek_params_size);
+      if (keyparms)
+        {
+          n = strlen (keyparms);
+          keyparms = xtryrealloc (keyparms, n + kek_params_size + 4);
+        }
+      if (!keyparms)
+        {
+          xfree (kek_params);
+          return NULL;
+        }
+      memcpy (keyparms+n, kek_params, kek_params_size);
+      xfree (kek_params);
+      memcpy (keyparms+n+kek_params_size, ")))", 4);
     }
-    memcpy( keyparms+n, kek_params, kek_params_size );
-    xfree( kek_params );
-    memcpy( keyparms+n+kek_params_size, ")))", 4 );
-  }
   return keyparms;
 }
 
-/* This common function is used in this file and also to generate ephemeral keys for ECDH.
- * Caller must call free_public_key and free_secret_key */
-int
-pk_ecc_keypair_gen( PKT_public_key **pk_out, int algo, int keygen_flags, char **cache_nonce_addr, unsigned nbits)  {
+
+/*
+ * Generate an ECC key
+ */
+static gpg_error_t
+gen_ecc (int algo, unsigned int nbits, KBNODE pub_root,
+         u32 timestamp, u32 expireval, int is_subkey,
+         int keygen_flags, char **cache_nonce_addr)
+{
   int err;
   unsigned int qbits;
   char *keyparms;
-  // PUBKEY_ALGO_ECDH, PUBKEY_ALGO_ECDSA
-  static const char * const ec_pub_params[2] =  { "cqp",  "cq" };
-  //static const char * const ec_priv_params[2] = { "cqpd", "cqd" };
 
-  assert( algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_ECDH );
-  assert( PUBKEY_ALGO_ECDSA == PUBKEY_ALGO_ECDH + 1 );
+  assert (algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_ECDH);
 
-  *pk_out = NULL;
-
-  if( pubkey_get_npkey (PUBKEY_ALGO_ECDSA) != 2 || pubkey_get_nskey (PUBKEY_ALGO_ECDSA) != 3 ||
-      pubkey_get_npkey (PUBKEY_ALGO_ECDH)  != 3 || pubkey_get_nskey (PUBKEY_ALGO_ECDH)  != 4 )  
-  {
-    log_info(_("incompatible version of gcrypt library (expect named curve logic for ECC)\n") );
-    return GPG_ERR_EPROGMISMATCH;
-  }
+  if (pubkey_get_npkey (PUBKEY_ALGO_ECDSA) != 2
+      || pubkey_get_nskey (PUBKEY_ALGO_ECDSA) != 3
+      || pubkey_get_npkey (PUBKEY_ALGO_ECDH)  != 3
+      || pubkey_get_nskey (PUBKEY_ALGO_ECDH)  != 4)
+    {
+      log_error ("broken version of Libgcrypt\n");
+      return gpg_error (GPG_ERR_INTERNAL);  /* ABI silently changed.  */
+    }
 
-  if ( nbits != 256 && nbits != 384 && nbits != 521 ) 
+  if (nbits != 256 && nbits != 384 && nbits != 521)
     {
-      log_info(_("keysize invalid; using 256 bits instead of passed in %d\n"), nbits );
+      log_info (_("keysize invalid; using %u bits\n"), 256);
+      /* FIXME:  Where do we set it to 256?  */
     }
 
-  /*
-    Figure out a q size based on the key size. See gen_dsa for more details.
-    Due to 8-bit rounding we may get 528 here instead of 521
-  */
+  /* Figure out a Q size based on the key size.  See gen_dsa for more
+     details.  Due to 8-bit rounding we may get 528 here instead of 521. */
   nbits = qbits = (nbits < 521 ? nbits : 521 );
 
-  keyparms = pk_ecc_build_key_params(qbits, algo, !!((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY) && (keygen_flags & KEYGEN_FLAG_NO_PROTECTION)) );
-  if (!keyparms)  {
-    err = gpg_error_from_syserror ();
-      log_error ("ec pk_ecc_build_key_params failed: %s\n", gpg_strerror (err) );
-  }
+  keyparms = pk_ecc_build_key_params
+    (qbits, algo,  !!( (keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
+                       && (keygen_flags & KEYGEN_FLAG_NO_PROTECTION)) );
+  if (!keyparms)
+    {
+      err = gpg_error_from_syserror ();
+      log_error ("ecc pk_ecc_build_key_params failed: %s\n",
+                 gpg_strerror (err));
+    }
   else
     {
-      err = common_key_gen (keyparms, algo, ec_pub_params[algo-PUBKEY_ALGO_ECDH],
-                        keygen_flags, cache_nonce_addr, pk_out);
+      err = common_gen (keyparms, algo,
+                        algo == PUBKEY_ALGO_ECDSA? "cq" : "cqp",
+                        pub_root, timestamp, expireval, is_subkey,
+                        keygen_flags, cache_nonce_addr);
       xfree (keyparms);
     }
 
-#if 0
-  /* always allocase seckey_info for EC keys. TODO: is this needed? */
-  if( *pk_out )  {
-    struct seckey_info *ski;
-
-    (*pk_out)->seckey_info = ski = xtrycalloc (1, sizeof *ski);
-    if (!(*pk_out)->seckey_info)  {
-      free_public_key(*pk_out);
-      *pk_out = NULL;
-      return gpg_error_from_syserror ();
-    }
-
-    ski->is_protected = 0;
-    ski->algo = 0;
-  }
-#endif
-
-  return err;
-}
-
-
-/****************
- * Generate an ECC OpenPGP key
- */
-static gpg_error_t
-gen_ecc (int algo, unsigned int nbits, KBNODE pub_root,
-         u32 timestamp, u32 expireval, int is_subkey, 
-         int keygen_flags, char **cache_nonce_addr)
-{
-  int rc;
-  PACKET *pkt;
-  PKT_public_key *pk;
-
-  rc = pk_ecc_keypair_gen( &pk, algo, keygen_flags, cache_nonce_addr, nbits );
-  if( rc )
-    return rc;
-
-  /* the rest is very similar to common_gen */
-
-  pk->timestamp = timestamp;
-  if (expireval) 
-    pk->expiredate = pk->timestamp + expireval;
-
-  //assert( pk->seckey_info != NULL );
-  /// TODO: the new agent-based model doesn't return private portion here (the pkey array is allocated, but private MPIs are NULL, so this will cause a crash... )
-  ///pk->seckey_info->csum = checksum_mpi ( pk->pkey[algo==PUBKEY_ALGO_ECDSA ? 2 : 3] );	/* corresponds to 'd' in 'cqd' or 'cqpd' */
-
-  pkt = xmalloc_clear(sizeof *pkt);
-  pkt->pkttype = is_subkey ? PKT_PUBLIC_SUBKEY : PKT_PUBLIC_KEY;
-  pkt->pkt.public_key = pk;
-  add_kbnode(pub_root, new_kbnode( pkt ));
-
   return 0;
 }
 
@@ -1755,7 +1676,7 @@ ask_algo (int addmode, int *r_subkey_algo, unsigned int *r_usage)
     }
   
   tty_printf (_("   (%d) ECDSA and ECDH\n"), 9 );
-  
+
   for(;;)
     {
       *r_usage = 0;
@@ -1877,7 +1798,7 @@ ask_keysize (int algo, unsigned int primary_keysize)
   tty_printf(_("%s keys may be between %u and %u bits long.\n"),
 	     openpgp_pk_algo_name (algo), min, max);
 
-  for(;;)
+  for (;;)
     {
       char *prompt, *answer;
 
@@ -1899,28 +1820,34 @@ ask_keysize (int algo, unsigned int primary_keysize)
 	break;
     }
 
-  tty_printf(_("Requested keysize is %u bits\n"), nbits );
+  tty_printf (_("Requested keysize is %u bits\n"), nbits);
 
  leave:
-  if( algo == PUBKEY_ALGO_DSA && (nbits % 64) )
+  if (algo == PUBKEY_ALGO_DSA && (nbits % 64))
     {
-      if( !(algo == PUBKEY_ALGO_ECDSA && nbits==521) )  {
-        nbits = ((nbits + 63) / 64) * 64;
-        if (!autocomp)
-          tty_printf(_("rounded up to %u bits\n"), nbits );
-      }
+      nbits = ((nbits + 63) / 64) * 64;
+      if (!autocomp)
+        tty_printf (_("rounded up to %u bits\n"), nbits);
     }
-  else if( algo == PUBKEY_ALGO_ECDH || algo == PUBKEY_ALGO_ECDSA )  {
-     if( nbits != 256 && nbits != 384 && nbits != 521 )  {
-        nbits = min;
-        tty_printf(_("unsupported ECDH value, corrected to the minimum %u bits\n"), nbits );
-     }
-  }
-  else if( (nbits % 32) )
+  else if (algo == PUBKEY_ALGO_ECDH || algo == PUBKEY_ALGO_ECDSA)
+    {
+      if (nbits != 256 && nbits != 384 && nbits != 521)
+        {
+          if (nbits < 256)
+            nbits = 256;
+          else if (nbits < 384)
+            nbits = 384;
+          else
+            nbits = 521;
+          if (!autocomp)
+            tty_printf (_("rounded to %u bits\n"), nbits);
+        }
+    }
+  else if ((nbits % 32))
     {
       nbits = ((nbits + 31) / 32) * 32;
       if (!autocomp)
-        tty_printf(_("rounded up to %u bits\n"), nbits );
+        tty_printf (_("rounded up to %u bits\n"), nbits );
     }
 
   return nbits;
@@ -2405,7 +2332,7 @@ do_create (int algo, unsigned int nbits, KBNODE pub_root,
   else if (algo == PUBKEY_ALGO_DSA)
     err = gen_dsa (nbits, pub_root, timestamp, expiredate, is_subkey,
                    keygen_flags, cache_nonce_addr);
-  else if( algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_ECDH )
+  else if (algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_ECDH)
     err = gen_ecc (algo, nbits, pub_root, timestamp, expiredate, is_subkey,
                    keygen_flags, cache_nonce_addr);
   else if (algo == PUBKEY_ALGO_RSA)
diff --git a/g10/main.h b/g10/main.h
index 1b6f305..ea1ac2e 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -260,11 +260,6 @@ gpg_error_t generate_card_subkeypair (kbnode_t pub_keyblock,
 int save_unprotected_key_to_card (PKT_public_key *sk, int keyno);
 #endif
 
-#define KEYGEN_FLAG_NO_PROTECTION 1
-#define KEYGEN_FLAG_TRANSIENT_KEY 2
-int pk_ecc_keypair_gen (PKT_public_key **pk_out, int algo,
-                        int keygen_flags, char **cache_nonce_addr,
-                        unsigned nbits);
 
 /*-- openfile.c --*/
 int overwrite_filep( const char *fname );
diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c
index ddca41e..43f5419 100644
--- a/g10/pubkey-enc.c
+++ b/g10/pubkey-enc.c
@@ -145,18 +145,17 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
   gcry_sexp_t s_data;
   char *desc;
   char *keygrip;
-  byte fp[MAX_FINGERPRINT_LEN]; 
+  byte fp[MAX_FINGERPRINT_LEN];
   size_t fpn;
-  const int gcry_pkalgo = map_pk_openpgp_to_gcry( sk->pubkey_algo );
+  const int pkalgo = map_pk_openpgp_to_gcry (sk->pubkey_algo);
 
   /* Get the keygrip.  */
   err = hexkeygrip_from_pk (sk, &keygrip);
   if (err)
     goto leave;
 
-
   /* Convert the data to an S-expression.  */
-  if (gcry_pkalgo == GCRY_PK_ELG ||gcry_pkalgo == GCRY_PK_ELG_E)
+  if (pkalgo == GCRY_PK_ELG || pkalgo == GCRY_PK_ELG_E)
     {
       if (!enc->data[0] || !enc->data[1])
         err = gpg_error (GPG_ERR_BAD_MPI);
@@ -164,7 +163,7 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
         err = gcry_sexp_build (&s_data, NULL, "(enc-val(elg(a%m)(b%m)))", 
                                enc->data[0], enc->data[1]);
     }
-  else if (gcry_pkalgo == GCRY_PK_RSA || gcry_pkalgo == GCRY_PK_RSA_E)
+  else if (pkalgo == GCRY_PK_RSA || pkalgo == GCRY_PK_RSA_E)
     {
       if (!enc->data[0])
         err = gpg_error (GPG_ERR_BAD_MPI);
@@ -172,12 +171,12 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
         err = gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))",
                                enc->data[0]);
     }
-  else if (gcry_pkalgo == GCRY_PK_ECDH )
+  else if (pkalgo == GCRY_PK_ECDH)
     {
       if (!enc->data[0] || !enc->data[1])
         err = gpg_error (GPG_ERR_BAD_MPI);
       else
-        err = gcry_sexp_build (&s_data, NULL, "(enc-val(ecdh(a%m)(b%m)))", 
+        err = gcry_sexp_build (&s_data, NULL, "(enc-val(ecdh(a%m)(b%m)))",
                                enc->data[0], enc->data[1]);
     }
   else
@@ -186,8 +185,9 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
   if (err)
     goto leave;
 
-  fingerprint_from_pk( sk, fp, &fpn );
-  assert( fpn == 20 );
+  /* fixme: only needed for ECDH.  Don't compute always. */
+  fingerprint_from_pk (sk, fp, &fpn);
+  assert (fpn == 20);
 
   /* Decrypt. */
   desc = gpg_format_keydesc (sk, 0, 1);
@@ -222,12 +222,12 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
     {
       gcry_mpi_t shared_mpi;
       gcry_mpi_t decoded;
-      
+
       /* At the beginning the frame are the bytes of shared point MPI.  */
       err = gcry_mpi_scan (&shared_mpi, GCRYMPI_FMT_USG, frame, nframe, NULL);
       if (err)
         {
-          log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err));
+          err = gpg_error (GPG_ERR_WRONG_SECKEY);
           goto leave;
         }
 
@@ -247,13 +247,14 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
 
       /* Allow double padding for the benefit of DEK size concealment.
          Higher than this is wasteful. */
-      if (frame[nframe-1] > 8*2 || nframe <= 8)
+      if (!nframe || frame[nframe-1] > 8*2 || nframe <= 8
+          || frame[nframe-1] > nframe)
         {
           err = gpg_error (GPG_ERR_WRONG_SECKEY);
-          goto leave; 
+          goto leave;
         }
       nframe -= frame[nframe-1]; /* Remove padding.  */
-      assert (n); /* (used just below) */
+      assert (!n); /* (used just below) */
     }
   else
     {
diff --git a/g10/verify-stubs.c b/g10/verify-stubs.c
deleted file mode 100644
index c4c657b..0000000
--- a/g10/verify-stubs.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/* To satisfy the linker for the gpgv target 
- * Copyright (C) 2010 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include "gpg.h"
-#include "main.h"
-
-int
-pk_ecc_keypair_gen (PKT_public_key **pk_out, int algo, int keygen_flags,
-                    char **cache_nonce_addr, unsigned nbits)
-{
-  return GPG_ERR_NOT_IMPLEMENTED;
-}

-----------------------------------------------------------------------

Summary of changes:
 g10/ChangeLog      |   27 ++++
 g10/Makefile.am    |    3 +-
 g10/ecdh.c         |  316 ++++++++++++++++++-----------------------------
 g10/keygen.c       |  348 +++++++++++++++++++++-------------------------------
 g10/main.h         |    5 -
 g10/misc.c         |    2 +-
 g10/pkglue.c       |   70 +++++++++--
 g10/pkglue.h       |   13 ++-
 g10/pubkey-enc.c   |   29 +++--
 g10/verify-stubs.c |   31 -----
 10 files changed, 373 insertions(+), 471 deletions(-)
 delete mode 100644 g10/verify-stubs.c


hooks/post-receive
-- 
The GNU Privacy Guard
http://git.gnupg.org




More information about the Gnupg-commits mailing list