[git] GnuPG - branch, STABLE-BRANCH-1-4, updated. gnupg-1.4.18-43-ge0c13ad

by Werner Koch cvs at cvs.gnupg.org
Mon Feb 23 11:08:32 CET 2015


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, STABLE-BRANCH-1-4 has been updated
       via  e0c13ad5f290aec05706797b8f6c9e13d613eb66 (commit)
       via  6f032181ba78c5eeb14f9aab4307a75bbaf0b115 (commit)
       via  a35ed8af41a91a52e1bbf992522a209f9c27dd55 (commit)
       via  2b2f2767851eccb12e591c7a3fa432e6bf9db8f2 (commit)
       via  cf8d89b0ce69d4cfaa835fab913cc7c77565a75d (commit)
       via  57af33d9e7c9b20b413b96882e670e75a67a5e65 (commit)
       via  7106165fd3161b614445d459df3b333d557d9d02 (commit)
       via  81d3e541326e94d26a953aa70afc3cb149d11ebe (commit)
       via  68f260f77a9e4f5cacf0a58e4f55ddee125d3f00 (commit)
       via  2e8db53854506572e9d5b5908e143b5ca28f30f5 (commit)
       via  27d7addccf782d5cb0084cb17522d712d4a6d6b6 (commit)
       via  20e14e331de4a7e9746650f8b39c1a66d2565c9e (commit)
       via  8baf452bb308a59478c9148109f4c78941170ecc (commit)
       via  ff53cf06e966dce0daba5f2c84e03ab9db2c3c8b (commit)
      from  397987c33233bd672b29e3c607577c8d93ed48ed (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 e0c13ad5f290aec05706797b8f6c9e13d613eb66
Author: Werner Koch <wk at gnupg.org>
Date:   Mon Feb 23 11:04:35 2015 +0100

    Protect against NULL return of mpi_get_opaque.
    
    * g10/seckey-cert.c (do_check): Call BUG for NULL return of
    get_opaque.
    --
    
    This is the suggested addition from commit 6f03218.  We better run
    into an fatal error than into a segv.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c
index cad4e63..4edd74e 100644
--- a/g10/seckey-cert.c
+++ b/g10/seckey-cert.c
@@ -91,8 +91,12 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode,
             u16 csumc = 0;
 
 	    i = pubkey_get_npkey(sk->pubkey_algo);
-	    assert( mpi_is_opaque( sk->skey[i] ) );
-	    p = mpi_get_opaque( sk->skey[i], &ndata );
+	    if (!mpi_is_opaque (sk->skey[i]))
+              p = NULL;
+            else
+              p = mpi_get_opaque (sk->skey[i], &ndata);
+            if (!p)
+              BUG ();
             if ( ndata > 1 )
                 csumc = p[ndata-2] << 8 | p[ndata-1];
 	    data = xmalloc_secure( ndata );
@@ -169,9 +173,12 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode,
                 byte *p;
                 unsigned int ndata;
 
-                assert (mpi_is_opaque (sk->skey[i]));
-                p = mpi_get_opaque (sk->skey[i], &ndata);
-                assert (ndata >= 2);
+                if (!mpi_is_opaque (sk->skey[i]))
+                  p = NULL;
+                else
+                  p = mpi_get_opaque (sk->skey[i], &ndata);
+                if (!p || !(ndata >= 2))
+                  BUG ();
                 assert (ndata == ((p[0] << 8 | p[1]) + 7)/8 + 2);
                 buffer = xmalloc_secure (ndata);
 		cipher_sync (cipher_hd);

commit 6f032181ba78c5eeb14f9aab4307a75bbaf0b115
Author: Daniel Kahn Gillmor <dkg at fifthhorseman.net>
Date:   Sat Feb 21 23:10:37 2015 -0500

    gpg: Fix segv due to NULL value stored as opaque MPI
    
    * g10/build-packet.c (do_secret_key): Check for NULL return from
    gcry_mpi_get_opaque.
    * g10/keyid.c (hash_public_key): Ditto.
    --
    
    This is a backport of 76c8122adfed0f0f443cce7bda702ba2b39661b3 from
    master to the STABLE-BRANCH-1-4
    
    On the STABLE-BRANCH-1-4, we may also want to patch g10/seckey-cert.c,
    but that has not been done in this patch.
    
    This fix extends commmit 0835d2f44ef62eab51fce6a927908f544e01cf8f.
    
      gpg2 --export --no-default-keyring --keyring TESTDATA
    
    With TESTDATA being below after unpacking.
    
    -----BEGIN PGP ARMORED FILE-----
    
    mBMEhdkMmS8BcX8F//8F5voEhQAQmBMEnAAAZwAAo4D/f/8EhQAAAIAEnP8EhQAQ
    iBMEnP8AAAAABf8jIID///8EhQYQmBMEnIUAEIgTBKT/AAAAAAUAACCA/f//BIUA
    EJgTBJx/AP8ABPPzBJx/AP8ABPPz
    =2yE0
    -----END PGP ARMORED FILE-----
    
    Reported-by: Jodie Cunningham
    [dkg: rebased to STABLE-BRANCH-1-4]
    Signed-off-by: Daniel Kahn Gillmor <dkg at fifthhorseman.net>

diff --git a/g10/build-packet.c b/g10/build-packet.c
index 60eb3c8..028d064 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -356,7 +356,8 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
 
 	assert( mpi_is_opaque( sk->skey[npkey] ) );
 	p = mpi_get_opaque( sk->skey[npkey], &ndata );
-	iobuf_write(a, p, ndata );
+        if (p)
+          iobuf_write(a, p, ndata );
     }
     else if( sk->is_protected ) {
         /* The secret key is protected te old v4 way. */
@@ -366,7 +367,8 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
 
             assert (mpi_is_opaque (sk->skey[i]));
             p = mpi_get_opaque (sk->skey[i], &ndata);
-            iobuf_write (a, p, ndata);
+            if (p)
+              iobuf_write (a, p, ndata);
         }
 	write_16(a, sk->csum );
     }
diff --git a/g10/keyid.c b/g10/keyid.c
index ed30cff..a86ac94 100644
--- a/g10/keyid.c
+++ b/g10/keyid.c
@@ -112,13 +112,17 @@ hash_public_key( MD_HANDLE md, PKT_public_key *pk )
   md_putc( md, pk->pubkey_algo );
 
   if(npkey==0 && pk->pkey[0] && mpi_is_opaque(pk->pkey[0]))
-    md_write(md,pp[0],nn[0]);
+    {
+      if (pp[0])
+        md_write(md,pp[0],nn[0]);
+    }
   else
     for(i=0; i < npkey; i++ )
       {
 	md_putc( md, nb[i]>>8);
 	md_putc( md, nb[i] );
-	md_write( md, pp[i], nn[i] );
+        if (pp[i])
+          md_write( md, pp[i], nn[i] );
 	xfree(pp[i]);
       }
 }

commit a35ed8af41a91a52e1bbf992522a209f9c27dd55
Author: Werner Koch <wk at gnupg.org>
Date:   Sat Feb 21 23:10:36 2015 -0500

    gpg: Remove an unused variable.
    
    * g10/import.c (import): Remove need_armor.
    
    [dkg: rebased to STABLE-BRANCH-1-4]
    Signed-off-by: Daniel Kahn Gillmor <dkg at fifthhorseman.net>

diff --git a/g10/import.c b/g10/import.c
index 7050039..4620c5f 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -268,7 +268,6 @@ import (IOBUF inp, const char* fname,struct stats_s *stats,
     PACKET *pending_pkt = NULL;
     KBNODE keyblock = NULL;
     int rc = 0;
-    int need_armor = (!opt.no_armor || r_gpgkeys_err);
     armor_filter_context_t *afx = NULL;
 
     getkey_disable_caches();

commit 2b2f2767851eccb12e591c7a3fa432e6bf9db8f2
Author: Daniel Kahn Gillmor <dkg at fifthhorseman.net>
Date:   Sat Feb 21 23:10:35 2015 -0500

    curl-shim: clean up varargs
    
    * keyserver/curl-shim.c (curl_easy_setopt) : ensure that va_end is
      called.
    
    --
    
    stdarg(3) says:
          Each invocation of va_start() must be matched by a
          corresponding invocation of va_end() in the same function.
    
    Observed by Joshua Rogers <honey at internot.info>
    
    Debian-Bug-Id: #773475
    
    [dkg: rebased to STABLE-BRANCH-1-4]
    Signed-off-by: Daniel Kahn Gillmor <dkg at fifthhorseman.net>

diff --git a/keyserver/curl-shim.c b/keyserver/curl-shim.c
index ce510cb..72c0f04 100644
--- a/keyserver/curl-shim.c
+++ b/keyserver/curl-shim.c
@@ -155,6 +155,8 @@ curl_easy_setopt(CURL *curl,CURLoption option,...)
       break;
     }
 
+  va_end(ap);
+
   return handle_error(curl,CURLE_OK,NULL);
 }
 

commit cf8d89b0ce69d4cfaa835fab913cc7c77565a75d
Author: Werner Koch <wk at gnupg.org>
Date:   Sat Feb 21 23:10:34 2015 -0500

    gpg: Print better diagnostics for keyserver operations.
    
    * g10/armor.c (parse_key_failed_line): New.
    (check_input): Watch out for gpgkeys_ error lines.
    * g10/filter.h (armor_filter_context_t): Add field key_failed_code.
    * g10/import.c (import): Add arg r_gpgkeys_err.
    (import_keys_internal): Ditto.
    (import_keys_stream): Ditto.
    * g10/keyserver.c (keyserver_errstr): New.
    (keyserver_spawn): Detect "KEY " lines while sending.  Get gpgkeys_err
    while receiving keys.
    (keyserver_work): Add kludge for better error messages.
    --
    
    GnuPG-bug-id: 1832
    
    Note that these changes can be backported to 1.4 but they don't make
    sense for 2.1 due to the removal of the keyserver helpers.  The error
    reporting could be improved even more but given that this is an old
    GnuPG branch it is not justified to put too much effort into it.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>
    
    [dkg: rebased to STABLE-BRANCH-1-4]
    Signed-off-by: Daniel Kahn Gillmor <dkg at fifthhorseman.net>

diff --git a/g10/armor.c b/g10/armor.c
index c50525c..4332d70 100644
--- a/g10/armor.c
+++ b/g10/armor.c
@@ -385,6 +385,32 @@ is_armor_header( byte *line, unsigned len )
 }
 
 
+/* Helper to parse a "KEY <keyid> FAILED <code>" line and return the
+   error code.  LINEPTR points right behind "KEY ".  */
+int
+parse_key_failed_line (const void *lineptr, unsigned int len)
+{
+  const byte *line = lineptr;
+  int code = 0;
+
+  for (; len && !spacep (line); len--, line++)
+    ;
+  for (; len && spacep (line); len--, line++)
+    ;
+  if (len > 7 && !memcmp (line, "FAILED ", 7))
+    {
+      line += 7;
+      len -= 7;
+      for (; len && digitp (line); len--, line++)
+        {
+          code *= 10;
+          code += atoi_1 (line);
+        }
+    }
+
+  return code;
+}
+
 
 /****************
  * Parse a header lines
@@ -505,6 +531,17 @@ check_input( armor_filter_context_t *afx, IOBUF a )
     /* find the armor header */
     while(len) {
 	i = is_armor_header( line, len );
+        if (i == -1 && afx->only_keyblocks
+            && !afx->key_failed_code
+            && len > 4 && !memcmp (line, "KEY ", 4))
+          {
+            /* This is probably input from a keyserver helper and we
+               have not yet seen an error line.  */
+            afx->key_failed_code = parse_key_failed_line (line+4, len-4);
+            log_debug ("armor-keys-failed (%.*s) ->%d\n",
+                       (int)len, line,
+                       afx->key_failed_code);
+          }
 	if( i >= 0 && !(afx->only_keyblocks && i != 1 && i != 5 && i != 6 )) {
 	    hdr_line = i;
 	    if( hdr_line == BEGIN_SIGNED_MSG_IDX ) {
diff --git a/g10/filter.h b/g10/filter.h
index 54a4152..f746695 100644
--- a/g10/filter.h
+++ b/g10/filter.h
@@ -40,6 +40,8 @@ typedef struct {
 
     /* these fileds must be initialized to zero */
     int no_openpgp_data;    /* output flag: "No valid OpenPGP data found" */
+    int key_failed_code;    /* Error code from the first gpgkkeys_*
+                               "KEY <keyid> FAILED <err>" line.  */
 
     /* the following fields must be initialized to zero */
     int inp_checked;	    /* set if the input has been checked */
diff --git a/g10/import.c b/g10/import.c
index c9df368..7050039 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -60,7 +60,8 @@ struct stats_s {
 
 static int import( IOBUF inp, const char* fname,struct stats_s *stats,
 		   unsigned char **fpr,size_t *fpr_len,unsigned int options,
-		   import_filter_t filter, void *filter_arg );
+		   import_filter_t filter, void *filter_arg,
+                   int *r_gpgkeys_err);
 static int read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root );
 static void revocation_present(KBNODE keyblock);
 static int import_one(const char *fname, KBNODE keyblock,struct stats_s *stats,
@@ -177,7 +178,8 @@ static int
 import_keys_internal( IOBUF inp, char **fnames, int nnames,
 		      void *stats_handle, unsigned char **fpr, size_t *fpr_len,
 		      unsigned int options,
-		      import_filter_t filter, void *filter_arg)
+		      import_filter_t filter, void *filter_arg,
+                      int *r_gpgkeys_err)
 {
     int i, rc = 0;
     struct stats_s *stats = stats_handle;
@@ -187,7 +189,7 @@ import_keys_internal( IOBUF inp, char **fnames, int nnames,
 
     if (inp) {
         rc = import (inp, "[stream]", stats, fpr, fpr_len, options,
-                     filter, filter_arg);
+                     filter, filter_arg, r_gpgkeys_err);
     }
     else {
         int once = (!fnames && !nnames);
@@ -208,7 +210,7 @@ import_keys_internal( IOBUF inp, char **fnames, int nnames,
 	    else
 	      {
 	        rc = import (inp2, fname, stats, fpr, fpr_len, options,
-                             NULL, NULL);
+                             NULL, NULL, r_gpgkeys_err);
 	        iobuf_close(inp2);
                 /* Must invalidate that ugly cache to actually close it. */
                 iobuf_ioctl (NULL, 2, 0, (char*)fname);
@@ -240,34 +242,42 @@ import_keys( char **fnames, int nnames,
 	     void *stats_handle, unsigned int options )
 {
   import_keys_internal (NULL, fnames, nnames, stats_handle, NULL, NULL,
-                        options, NULL, NULL);
+                        options, NULL, NULL, NULL);
 }
 
+
+/* Import keys from an open stream.  */
 int
 import_keys_stream( IOBUF inp, void *stats_handle,
 		    unsigned char **fpr, size_t *fpr_len,unsigned int options,
-	            import_filter_t filter, void *filter_arg )
+	            import_filter_t filter, void *filter_arg,
+                    int *r_gpgkeys_err)
 {
   return import_keys_internal (inp, NULL, 0, stats_handle, fpr, fpr_len,
-                               options, filter, filter_arg);
+                               options, filter, filter_arg, r_gpgkeys_err);
 }
 
+
+/* Note: If R_GPGKEYS_ERR is not NULL an error code from the keyserver
+   helpers will be stored there.  */
 static int
-import( IOBUF inp, const char* fname,struct stats_s *stats,
-	unsigned char **fpr,size_t *fpr_len,unsigned int options,
-	import_filter_t filter, void *filter_arg)
+import (IOBUF inp, const char* fname,struct stats_s *stats,
+	unsigned char **fpr, size_t *fpr_len, unsigned int options,
+	import_filter_t filter, void *filter_arg, int *r_gpgkeys_err)
 {
     PACKET *pending_pkt = NULL;
     KBNODE keyblock = NULL;
     int rc = 0;
+    int need_armor = (!opt.no_armor || r_gpgkeys_err);
+    armor_filter_context_t *afx = NULL;
 
     getkey_disable_caches();
 
-    if( !opt.no_armor ) { /* armored reading is not disabled */
-	armor_filter_context_t *afx = new_armor_context ();
+    if (!opt.no_armor || r_gpgkeys_err) {
+        /* armored reading is not disabled or enforced. */
+        afx = new_armor_context ();
 	afx->only_keyblocks = 1;
 	push_armor_filter (afx, inp);
-        release_armor_context (afx);
     }
 
     while( !(rc = read_block( inp, &pending_pkt, &keyblock) )) {
@@ -297,6 +307,11 @@ import( IOBUF inp, const char* fname,struct stats_s *stats,
     else if( rc && rc != G10ERR_INV_KEYRING )
 	log_error( _("error reading `%s': %s\n"), fname, g10_errstr(rc));
 
+    if (afx && r_gpgkeys_err)
+      *r_gpgkeys_err = afx->key_failed_code;
+
+    release_armor_context (afx);
+
     return rc;
 }
 
diff --git a/g10/keyserver.c b/g10/keyserver.c
index 810713c..d1ddc99 100644
--- a/g10/keyserver.c
+++ b/g10/keyserver.c
@@ -1040,6 +1040,30 @@ keyserver_retrieval_filter (kbnode_t keyblock, void *opaque)
 }
 
 
+static const char *
+keyserver_errstr (int code)
+{
+  const char *s;
+
+  switch (code)
+    {
+    case KEYSERVER_OK:            s = "success"; break;
+    case KEYSERVER_INTERNAL_ERROR:s = "keyserver helper internal error"; break;
+    case KEYSERVER_NOT_SUPPORTED: s = "keyserver not supported"; break;
+    case KEYSERVER_VERSION_ERROR: s = "keyserver helper version mismatch";break;
+    case KEYSERVER_GENERAL_ERROR: s = "keyserver helper general error"; break;
+    case KEYSERVER_NO_MEMORY:     s = "keyserver helper is out of core"; break;
+    case KEYSERVER_KEY_NOT_FOUND: s = "key not found"; break;
+    case KEYSERVER_KEY_EXISTS:    s = "key exists"; break;
+    case KEYSERVER_KEY_INCOMPLETE:s = "key incomplete (EOF)"; break;
+    case KEYSERVER_UNREACHABLE:   s = "keyserver unreachable"; break;
+    case KEYSERVER_TIMEOUT:       s = "keyserver timeout"; break;
+    default:                      s = "?"; break;
+    }
+  return s;
+}
+
+
 static int
 keyserver_spawn(enum ks_action action,STRLIST list,KEYDB_SEARCH_DESC *desc,
 		int count,int *prog,unsigned char **fpr,size_t *fpr_len,
@@ -1539,8 +1563,11 @@ keyserver_spawn(enum ks_action action,STRLIST list,KEYDB_SEARCH_DESC *desc,
 	plen--;
       ptr[plen]='\0';
 
-      if(*ptr=='\0')
-	break;
+      /* Stop at the first empty line but not if we are sending keys.
+         In the latter case we won't continue reading later and thus
+         we need to watch out for errors right in this loop.  */
+      if(*ptr=='\0' && action != KS_SEND)
+        break;
 
       if(ascii_strncasecmp(ptr,"VERSION ",8)==0)
 	{
@@ -1561,6 +1588,14 @@ keyserver_spawn(enum ks_action action,STRLIST list,KEYDB_SEARCH_DESC *desc,
 	}
       else if(ascii_strncasecmp(ptr,"OPTION OUTOFBAND",16)==0)
 	outofband=1; /* Currently the only OPTION */
+      else if (action == KS_SEND
+               && ascii_strncasecmp(ptr,"KEY ",4)==0)
+        {
+          ret = parse_key_failed_line (ptr+4, strlen (ptr+4));
+          break;  /* We stop at the first KEY line so that we won't
+                     run into an EOF which would return an unspecified
+                     error message (due to iobuf_read_line).  */
+        }
     }
 
   if(!gotversion)
@@ -1577,6 +1612,7 @@ keyserver_spawn(enum ks_action action,STRLIST list,KEYDB_SEARCH_DESC *desc,
 	{
 	  void *stats_handle;
           struct ks_retrieval_filter_arg_s filterarg;
+          int gpgkeys_err;
 
 	  stats_handle=import_new_stats_handle();
 
@@ -1591,14 +1627,21 @@ keyserver_spawn(enum ks_action action,STRLIST list,KEYDB_SEARCH_DESC *desc,
 	     but we better protect against rogue keyservers. */
           filterarg.desc = desc;
           filterarg.ndesc = count;
+          gpgkeys_err = 0;
 	  import_keys_stream (spawn->fromchild, stats_handle, fpr, fpr_len,
                              (opt.keyserver_options.import_options
                               | IMPORT_NO_SECKEY),
-                              keyserver_retrieval_filter, &filterarg);
+                              keyserver_retrieval_filter, &filterarg,
+                              &gpgkeys_err);
 
 	  import_print_stats(stats_handle);
 	  import_release_stats_handle(stats_handle);
-
+          if (gpgkeys_err)
+            {
+              log_error (_("keyserver communications error: %s\n"),
+                         keyserver_errstr (gpgkeys_err));
+              ret = gpgkeys_err;
+            }
 	  break;
 	}
 
@@ -1619,7 +1662,6 @@ keyserver_spawn(enum ks_action action,STRLIST list,KEYDB_SEARCH_DESC *desc,
   xfree(line);
   xfree(searchstr);
 
-
   *prog=exec_finish(spawn);
 
   return ret;
@@ -1644,9 +1686,11 @@ keyserver_work(enum ks_action action,STRLIST list,KEYDB_SEARCH_DESC *desc,
   return G10ERR_KEYSERVER;
 
 #else
-  /* Spawn a handler */
-
+  /* Spawn a handler.  The use of RC and RET is a mess.  We use a
+     kludge to return a suitable error message.  */
   rc=keyserver_spawn(action,list,desc,count,&ret,fpr,fpr_len,keyserver);
+  if (ret == KEYSERVER_INTERNAL_ERROR && rc)
+    ret = rc;
   if(ret)
     {
       switch(ret)
@@ -1675,6 +1719,9 @@ keyserver_work(enum ks_action action,STRLIST list,KEYDB_SEARCH_DESC *desc,
 	  log_error(_("keyserver timed out\n"));
 	  break;
 
+        case KEYSERVER_UNREACHABLE:
+          return G10ERR_UNKNOWN_HOST;
+
 	case KEYSERVER_INTERNAL_ERROR:
 	default:
 	  log_error(_("keyserver internal error\n"));
@@ -2127,7 +2174,7 @@ keyserver_import_cert(const char *name,unsigned char **fpr,size_t *fpr_len)
 
       rc=import_keys_stream (key, NULL, fpr, fpr_len,
                              (opt.keyserver_options.import_options
-                              | IMPORT_NO_SECKEY), NULL, NULL);
+                              | IMPORT_NO_SECKEY), NULL, NULL, NULL);
 
       opt.no_armor=armor_status;
 
diff --git a/g10/main.h b/g10/main.h
index 05a4059..05b60bb 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -67,6 +67,7 @@ void print_digest_algo_note( int algo );
 
 /*-- armor.c --*/
 char *make_radix64_string( const byte *data, size_t len );
+int parse_key_failed_line (const void *lineptr, unsigned int len);
 
 /*-- misc.c --*/
 void trap_unaligned(void);
@@ -216,7 +217,8 @@ void import_keys( char **fnames, int nnames,
 		  void *stats_hd, unsigned int options );
 int import_keys_stream (IOBUF inp,void *stats_hd,unsigned char **fpr,
                         size_t *fpr_len,unsigned int options,
-                        import_filter_t filter, void *filter_arg);
+                        import_filter_t filter, void *filter_arg,
+                        int *r_gpgkeys_err);
 void *import_new_stats_handle (void);
 void import_release_stats_handle (void *p);
 void import_print_stats (void *hd);

commit 57af33d9e7c9b20b413b96882e670e75a67a5e65
Author: Werner Koch <wk at gnupg.org>
Date:   Sat Feb 21 23:10:32 2015 -0500

    Use inline functions to convert buffer data to scalars.
    
    * include/host2net.h (buf16_to_ulong, buf16_to_uint): New.
    (buf16_to_ushort, buf16_to_u16): New.
    (buf32_to_size_t, buf32_to_ulong, buf32_to_uint, buf32_to_u32): New.
    --
    
    This fixes sign extension on shift problems.  Hanno Böck found a case
    with an invalid read due to this problem.  To fix that almost all uses
    of "<< 24" and "<< 8" are changed by this patch to use an inline
    function from host2net.h.
    
    (back ported from commit 2183683bd633818dd031b090b5530951de76f392)
    
    Signed-off-by: Werner Koch <wk at gnupg.org>
    
    [dkg: rebased to STABLE-BRANCH-1-4]
    Signed-off-by: Daniel Kahn Gillmor <dkg at fifthhorseman.net>

diff --git a/g10/apdu.c b/g10/apdu.c
index 66cf30b..ffc7d36 100644
--- a/g10/apdu.c
+++ b/g10/apdu.c
@@ -60,6 +60,7 @@
 #include "scdaemon.h"
 #include "exechelp.h"
 #endif /* GNUPG_MAJOR_VERSION != 1 */
+#include "../include/host2net.h"
 
 #include "apdu.h"
 #include "ccid-driver.h"
@@ -916,15 +917,14 @@ pcsc_get_status_wrapped (int slot, unsigned int *status)
                  i? strerror (errno) : "premature EOF");
       goto command_failed;
     }
-  len = (msgbuf[1] << 24) | (msgbuf[2] << 16) | (msgbuf[3] << 8 ) | msgbuf[4];
+  len = buf32_to_size_t (msgbuf+1);
   if (msgbuf[0] != 0x81 || len < 4)
     {
       log_error ("invalid response header from PC/SC received\n");
       goto command_failed;
     }
   len -= 4; /* Already read the error code. */
-  err = PCSC_ERR_MASK ((msgbuf[5] << 24) | (msgbuf[6] << 16)
-                       | (msgbuf[7] << 8 ) | msgbuf[8]);
+  err = PCSC_ERR_MASK (buf32_to_ulong (msgbuf+5));
   if (err)
     {
       log_error ("pcsc_status failed: %s (0x%lx)\n",
@@ -1084,15 +1084,14 @@ pcsc_send_apdu_wrapped (int slot, unsigned char *apdu, size_t apdulen,
                  i? strerror (errno) : "premature EOF");
       goto command_failed;
     }
-  len = (msgbuf[1] << 24) | (msgbuf[2] << 16) | (msgbuf[3] << 8 ) | msgbuf[4];
+  len = buf32_to_size_t (msgbuf+1);
   if (msgbuf[0] != 0x81 || len < 4)
     {
       log_error ("invalid response header from PC/SC received\n");
       goto command_failed;
     }
   len -= 4; /* Already read the error code. */
-  err = PCSC_ERR_MASK ((msgbuf[5] << 24) | (msgbuf[6] << 16)
-                       | (msgbuf[7] << 8 ) | msgbuf[8]);
+  err = PCSC_ERR_MASK (buf32_to_ulong (msgbuf+5));
   if (err)
     {
       log_error ("pcsc_transmit failed: %s (0x%lx)\n",
@@ -1217,15 +1216,14 @@ close_pcsc_reader_wrapped (int slot)
                  i? strerror (errno) : "premature EOF");
       goto command_failed;
     }
-  len = (msgbuf[1] << 24) | (msgbuf[2] << 16) | (msgbuf[3] << 8 ) | msgbuf[4];
+  len = buf32_to_size_t (msgbuf+1);
   if (msgbuf[0] != 0x81 || len < 4)
     {
       log_error ("invalid response header from PC/SC received\n");
       goto command_failed;
     }
   len -= 4; /* Already read the error code. */
-  err = PCSC_ERR_MASK ((msgbuf[5] << 24) | (msgbuf[6] << 16)
-                       | (msgbuf[7] << 8 ) | msgbuf[8]);
+  err = PCSC_ERR_MASK (buf32_to_ulong (msgbuf+5));
   if (err)
     log_error ("pcsc_close failed: %s (0x%lx)\n",
                pcsc_error_string (err), err);
@@ -1405,7 +1403,7 @@ reset_pcsc_reader_wrapped (int slot)
                  i? strerror (errno) : "premature EOF");
       goto command_failed;
     }
-  len = (msgbuf[1] << 24) | (msgbuf[2] << 16) | (msgbuf[3] << 8 ) | msgbuf[4];
+  len = buf32_to_size_t (msgbuf+1);
   if (msgbuf[0] != 0x81 || len < 4)
     {
       log_error ("invalid response header from PC/SC received\n");
@@ -1419,8 +1417,7 @@ reset_pcsc_reader_wrapped (int slot)
       sw = SW_HOST_GENERAL_ERROR;
       goto command_failed;
     }
-  err = PCSC_ERR_MASK ((msgbuf[5] << 24) | (msgbuf[6] << 16)
-                       | (msgbuf[7] << 8 ) | msgbuf[8]);
+  err = PCSC_ERR_MASK (buf32_to_ulong (msgbuf+5));
   if (err)
     {
       log_error ("PC/SC RESET failed: %s (0x%lx)\n",
@@ -1719,7 +1716,7 @@ open_pcsc_reader_wrapped (const char *portstr)
                  i? strerror (errno) : "premature EOF");
       goto command_failed;
     }
-  len = (msgbuf[1] << 24) | (msgbuf[2] << 16) | (msgbuf[3] << 8 ) | msgbuf[4];
+  len = buf32_to_size_t (msgbuf+1);
   if (msgbuf[0] != 0x81 || len < 4)
     {
       log_error ("invalid response header from PC/SC received\n");
@@ -1732,8 +1729,8 @@ open_pcsc_reader_wrapped (const char *portstr)
                  (unsigned long)len);
       goto command_failed;
     }
-  err = PCSC_ERR_MASK ((msgbuf[5] << 24) | (msgbuf[6] << 16)
-                       | (msgbuf[7] << 8 ) | msgbuf[8]);
+  err = PCSC_ERR_MASK (buf32_to_ulong (msgbuf+5));
+
   if (err)
     {
       log_error ("PC/SC OPEN failed: %s\n", pcsc_error_string (err));
diff --git a/g10/app-openpgp.c b/g10/app-openpgp.c
index c3b4fae..192680c 100644
--- a/g10/app-openpgp.c
+++ b/g10/app-openpgp.c
@@ -68,6 +68,7 @@
 #include "iso7816.h"
 #include "app-common.h"
 #include "tlv.h"
+#include "../include/host2net.h"
 
 
 /* A table describing the DOs of the card.  */
@@ -744,7 +745,7 @@ send_fprtime_if_not_null (ctrl_t ctrl, const char *keyword,
   char numbuf1[50], numbuf2[50];
   unsigned long value;
 
-  value = (stamp[0] << 24) | (stamp[1]<<16) | (stamp[2]<<8) | stamp[3];
+  value = buf32_to_ulong (stamp);
   if (!value)
     return;
   sprintf (numbuf1, "%d", number);
diff --git a/g10/build-packet.c b/g10/build-packet.c
index 499dd68..60eb3c8 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -34,6 +34,7 @@
 #include "memory.h"
 #include "i18n.h"
 #include "options.h"
+#include "../include/host2net.h"
 
 static int do_user_id( IOBUF out, int ctb, PKT_user_id *uid );
 static int do_public_key( IOBUF out, int ctb, PKT_public_key *pk );
@@ -586,8 +587,7 @@ delete_sig_subpkt (subpktarea_t *area, sigsubpkttype_t reqtype )
 	if( n == 255 ) {
 	    if( buflen < 4 )
 		break;
-	    n = (buffer[0] << 24) | (buffer[1] << 16)
-                | (buffer[2] << 8) | buffer[3];
+	    n = buf32_to_size_t (buffer);
 	    buffer += 4;
 	    buflen -= 4;
 	}
@@ -710,7 +710,7 @@ build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type,
 	/* This should never happen since we don't currently allow
 	   creating such a subpacket, but just in case... */
       case SIGSUBPKT_SIG_EXPIRE:
-	if(buffer_to_u32(buffer)+sig->timestamp<=make_timestamp())
+	if (buf32_to_u32 (buffer) + sig->timestamp <= make_timestamp())
 	  sig->flags.expired=1;
 	else
 	  sig->flags.expired=0;
diff --git a/g10/ccid-driver.c b/g10/ccid-driver.c
index 8c362d7..515b15a 100644
--- a/g10/ccid-driver.c
+++ b/g10/ccid-driver.c
@@ -92,6 +92,7 @@
 #include <usb.h>
 
 #include "ccid-driver.h"
+#include "../include/host2net.h"
 
 #define DRVNAME "ccid-driver: "
 
@@ -292,7 +293,7 @@ static int abort_cmd (ccid_driver_t handle, int seqno);
 static unsigned int 
 convert_le_u32 (const unsigned char *buf)
 {
-  return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); 
+  return buf[0] | (buf[1] << 8) | (buf[2] << 16) | ((unsigned int)buf[3] << 24);
 }
 
 
diff --git a/g10/getkey.c b/g10/getkey.c
index 3c953d6..9870710 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -34,6 +34,7 @@
 #include "trustdb.h"
 #include "i18n.h"
 #include "keyserver-internal.h"
+#include "../include/host2net.h"
 
 #define MAX_PK_CACHE_ENTRIES   PK_UID_CACHE_SIZE
 #define MAX_UID_CACHE_ENTRIES  PK_UID_CACHE_SIZE
@@ -1427,14 +1428,14 @@ merge_keys_and_selfsig( KBNODE keyblock )
 
 	    p = parse_sig_subpkt( sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL );
 	    if( pk ) {
-		ed = p? pk->timestamp + buffer_to_u32(p):0;
+		ed = p? pk->timestamp + buf32_to_u32(p):0;
 		if( sig->timestamp > sigdate ) {
 		    pk->expiredate = ed;
 		    sigdate = sig->timestamp;
 		}
 	    }
 	    else {
-		ed = p? sk->timestamp + buffer_to_u32(p):0;
+		ed = p? sk->timestamp + buf32_to_u32(p):0;
 		if( sig->timestamp > sigdate ) {
 		    sk->expiredate = ed;
 		    sigdate = sig->timestamp;
@@ -1559,8 +1560,8 @@ fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated )
 
     /* ditto for the key expiration */
     p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL);
-    if( p && buffer_to_u32(p) )
-      uid->help_key_expire = keycreated + buffer_to_u32(p);
+    if( p && buf32_to_u32 (p) )
+      uid->help_key_expire = keycreated + buf32_to_u32(p);
     else
       uid->help_key_expire = 0;
 
@@ -1774,9 +1775,9 @@ merge_selfsigs_main(KBNODE keyblock, int *r_revoked, struct revoke_info *rinfo)
 	key_usage=parse_key_usage(sig);
 
 	p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL);
-	if( p && buffer_to_u32(p) )
+	if( p && buf32_to_u32 (p) )
 	  {
-	    key_expire = keytimestamp + buffer_to_u32(p);
+	    key_expire = keytimestamp + buf32_to_u32 (p);
 	    key_expire_seen = 1;
 	  }
 
@@ -2198,8 +2199,8 @@ merge_selfsigs_subkey( KBNODE keyblock, KBNODE subnode )
     subpk->pubkey_usage = key_usage;
 
     p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL);
-    if ( p && buffer_to_u32(p) )
-        key_expire = keytimestamp + buffer_to_u32(p);
+    if ( p && buf32_to_u32 (p) )
+        key_expire = keytimestamp + buf32_to_u32 (p);
     else
         key_expire = 0;
     subpk->has_expired = key_expire >= curtime? 0 : key_expire;
diff --git a/g10/keygen.c b/g10/keygen.c
index 995ba63..76ee74e 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -40,6 +40,7 @@
 #include "i18n.h"
 #include "cardglue.h"
 #include "keyserver-internal.h"
+#include "host2net.h"
 
 #define MAX_PREFS 30
 
@@ -832,10 +833,7 @@ make_backsig (PKT_signature *sig, PKT_public_key *pk,
 		}
 	      else if(buf[1]==255)
 		{
-		  pktlen =buf[2] << 24;
-		  pktlen|=buf[3] << 16;
-		  pktlen|=buf[4] << 8;
-		  pktlen|=buf[5];
+                  pktlen = buf32_to_size_t (buf+2);
 		  buf+=6;
 		}
 	      else
@@ -852,14 +850,14 @@ make_backsig (PKT_signature *sig, PKT_public_key *pk,
 		  break;
 
 		case 2:
-		  pktlen =buf[mark++] << 24;
-		  pktlen|=buf[mark++] << 16;
+		  pktlen  = (size_t)buf[mark++] << 24;
+		  pktlen |= buf[mark++] << 16;
 
 		case 1:
-		  pktlen|=buf[mark++] << 8;
+		  pktlen |= buf[mark++] << 8;
 
 		case 0:
-		  pktlen|=buf[mark++];
+		  pktlen |= buf[mark++];
 		}
 
 	      buf+=mark;
diff --git a/g10/keyid.c b/g10/keyid.c
index d7072d4..ed30cff 100644
--- a/g10/keyid.c
+++ b/g10/keyid.c
@@ -32,6 +32,7 @@
 #include "mpi.h"
 #include "keydb.h"
 #include "i18n.h"
+#include "host2net.h"
 
 #ifdef HAVE_UNSIGNED_TIME_T
 # define INVALID_TIME_CHECK(a) ((a) == (time_t)(-1))
@@ -241,15 +242,8 @@ keystr_from_desc(KEYDB_SEARCH_DESC *desc)
       {
 	u32 keyid[2];
 
-	keyid[0] = (unsigned char)desc->u.fpr[12] << 24
-	  | (unsigned char)desc->u.fpr[13] << 16
-	  | (unsigned char)desc->u.fpr[14] << 8
-	  | (unsigned char)desc->u.fpr[15] ;
-	keyid[1] = (unsigned char)desc->u.fpr[16] << 24
-	  | (unsigned char)desc->u.fpr[17] << 16
-	  | (unsigned char)desc->u.fpr[18] << 8
-	  | (unsigned char)desc->u.fpr[19] ;
-
+	keyid[0] = buf32_to_u32 (desc->u.fpr+12);
+	keyid[1] = buf32_to_u32 (desc->u.fpr+16);
 	return keystr(keyid);
       }
 
@@ -300,8 +294,8 @@ keyid_from_sk( PKT_secret_key *sk, u32 *keyid )
       if(md)
 	{
 	  dp = md_read( md, 0 );
-	  keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
-	  keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
+	  keyid[0] = buf32_to_u32 (dp+12);
+	  keyid[1] = buf32_to_u32 (dp+16);
 	  lowbits = keyid[1];
 	  md_close(md);
 	  sk->keyid[0] = keyid[0];
@@ -354,8 +348,8 @@ keyid_from_pk( PKT_public_key *pk, u32 *keyid )
       if(md)
 	{
 	  dp = md_read( md, 0 );
-	  keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
-	  keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
+	  keyid[0] = buf32_to_u32 (dp+12);
+	  keyid[1] = buf32_to_u32 (dp+16);
 	  lowbits = keyid[1];
 	  md_close(md);
 	  pk->keyid[0] = keyid[0];
@@ -398,8 +392,8 @@ keyid_from_fingerprint( const byte *fprint, size_t fprint_len, u32 *keyid )
     }
     else {
 	const byte *dp = fprint;
-	keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
-	keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
+	keyid[0] = buf32_to_u32 (dp+12);
+	keyid[1] = buf32_to_u32 (dp+16);
     }
 
     return keyid[1];
@@ -687,8 +681,8 @@ fingerprint_from_pk( PKT_public_key *pk, byte *array, size_t *ret_len )
 	if( !array )
 	    array = xmalloc( len );
 	memcpy(array, dp, len );
-	pk->keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
-	pk->keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
+        pk->keyid[0] = buf32_to_u32 (dp+12);
+        pk->keyid[1] = buf32_to_u32 (dp+16);
 	md_close(md);
     }
 
diff --git a/g10/misc.c b/g10/misc.c
index 60ecf96..2c5c6cc 100644
--- a/g10/misc.c
+++ b/g10/misc.c
@@ -295,17 +295,6 @@ checksum_mpi( MPI a )
     return csum;
 }
 
-u32
-buffer_to_u32( const byte *buffer )
-{
-    unsigned long a;
-    a =  *buffer << 24;
-    a |= buffer[1] << 16;
-    a |= buffer[2] << 8;
-    a |= buffer[3];
-    return a;
-}
-
 void
 print_pubkey_algo_note( int algo )
 {
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index e7e923b..862ec6e 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -35,6 +35,7 @@
 #include "options.h"
 #include "main.h"
 #include "i18n.h"
+#include "host2net.h"
 
 #ifndef MAX_EXTERN_MPI_BITS
 #define MAX_EXTERN_MPI_BITS 16384
@@ -94,7 +95,7 @@ static unsigned short
 read_16(IOBUF inp)
 {
     unsigned short a;
-    a = iobuf_get_noeof(inp) << 8;
+    a = (unsigned short)iobuf_get_noeof(inp) << 8;
     a |= iobuf_get_noeof(inp);
     return a;
 }
@@ -103,7 +104,7 @@ static unsigned long
 read_32(IOBUF inp)
 {
     unsigned long a;
-    a =  iobuf_get_noeof(inp) << 24;
+    a =  (unsigned long)iobuf_get_noeof(inp) << 24;
     a |= iobuf_get_noeof(inp) << 16;
     a |= iobuf_get_noeof(inp) << 8;
     a |= iobuf_get_noeof(inp);
@@ -383,7 +384,8 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
 	       }
              else if( c == 255 )
 	       {
-		 pktlen  = (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 24;
+		 pktlen  =
+                   (unsigned long)(hdr[hdrlen++] = iobuf_get_noeof(inp)) << 24;
 		 pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 16;
 		 pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 8;
 		 if( (c = iobuf_get(inp)) == -1 )
@@ -878,14 +880,15 @@ dump_sig_subpkt( int hashed, int type, int critical,
     switch( type ) {
       case SIGSUBPKT_SIG_CREATED:
 	if( length >= 4 )
-	    fprintf (listfp, "sig created %s", strtimestamp( buffer_to_u32(buffer) ) );
+	    fprintf (listfp, "sig created %s",
+                     strtimestamp (buf32_to_u32(buffer)) );
 	break;
       case SIGSUBPKT_SIG_EXPIRE:
 	if( length >= 4 )
 	  {
-	    if(buffer_to_u32(buffer))
+	    if(buf32_to_u32(buffer))
 	      fprintf (listfp, "sig expires after %s",
-		       strtimevalue( buffer_to_u32(buffer) ) );
+		       strtimevalue( buf32_to_u32(buffer) ) );
 	    else
 	      fprintf (listfp, "sig does not expire");
 	  }
@@ -918,9 +921,9 @@ dump_sig_subpkt( int hashed, int type, int critical,
       case SIGSUBPKT_KEY_EXPIRE:
 	if( length >= 4 )
 	  {
-	    if(buffer_to_u32(buffer))
+	    if(buf32_to_u32(buffer))
 	      fprintf (listfp, "key expires after %s",
-		       strtimevalue( buffer_to_u32(buffer) ) );
+		       strtimevalue( buf32_to_u32(buffer) ) );
 	    else
 	      fprintf (listfp, "key does not expire");
 	  }
@@ -943,8 +946,8 @@ dump_sig_subpkt( int hashed, int type, int critical,
       case SIGSUBPKT_ISSUER:
 	if( length >= 8 )
 	    fprintf (listfp, "issuer key ID %08lX%08lX",
-		      (ulong)buffer_to_u32(buffer),
-		      (ulong)buffer_to_u32(buffer+4) );
+                     buf32_to_ulong (buffer),
+                     buf32_to_ulong (buffer+4));
 	break;
       case SIGSUBPKT_NOTATION:
 	{
@@ -1192,8 +1195,7 @@ enum_sig_subpkt( const subpktarea_t *pktbuf, sigsubpkttype_t reqtype,
 	if( n == 255 ) { /* 4 byte length header */
 	    if( buflen < 4 )
 		goto too_short;
-	    n = (buffer[0] << 24) | (buffer[1] << 16)
-                | (buffer[2] << 8) | buffer[3];
+            n = buf32_to_size_t (buffer);
 	    buffer += 4;
 	    buflen -= 4;
 	}
@@ -1415,7 +1417,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
 
 	p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIG_CREATED, NULL );
 	if(p)
-	  sig->timestamp = buffer_to_u32(p);
+	  sig->timestamp = buf32_to_u32 (p);
 	else if(!(sig->pubkey_algo>=100 && sig->pubkey_algo<=110)
 		&& opt.verbose)
 	  log_info ("signature packet without timestamp\n");
@@ -1423,16 +1425,16 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
 	p = parse_sig_subpkt2( sig, SIGSUBPKT_ISSUER, NULL );
 	if(p)
 	  {
-	    sig->keyid[0] = buffer_to_u32(p);
-	    sig->keyid[1] = buffer_to_u32(p+4);
+	    sig->keyid[0] = buf32_to_u32 (p);
+	    sig->keyid[1] = buf32_to_u32 (p+4);
 	  }
 	else if(!(sig->pubkey_algo>=100 && sig->pubkey_algo<=110)
 		&& opt.verbose)
 	  log_info ("signature packet without keyid\n");
 
 	p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_SIG_EXPIRE,NULL);
-	if(p && buffer_to_u32(p))
-	  sig->expiredate=sig->timestamp+buffer_to_u32(p);
+	if(p && buf32_to_u32 (p))
+	  sig->expiredate = sig->timestamp + buf32_to_u32 (p);
 	if(sig->expiredate && sig->expiredate<=make_timestamp())
 	  sig->flags.expired=1;
 
@@ -2032,9 +2034,8 @@ parse_attribute_subpkts(PKT_user_id *uid)
       if( n == 255 ) { /* 4 byte length header */
 	if( buflen < 4 )
 	  goto too_short;
-	n = (buffer[0] << 24) | (buffer[1] << 16)
-	  | (buffer[2] << 8) | buffer[3];
-	buffer += 4;
+        n = buf32_to_size_t (buffer);
+        buffer += 4;
 	buflen -= 4;
       }
       else if( n >= 192 ) { /* 2 byte special encoded length header */
diff --git a/g10/tdbio.c b/g10/tdbio.c
index f109dde..403b608 100644
--- a/g10/tdbio.c
+++ b/g10/tdbio.c
@@ -1219,13 +1219,13 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
 	rec->r.ver.trust_model = *p++;
 	rec->r.ver.min_cert_level = *p++;
 	p += 2;
-	rec->r.ver.created  = buftoulong(p); p += 4;
-	rec->r.ver.nextcheck = buftoulong(p); p += 4;
+	rec->r.ver.created  = buf32_to_ulong (p); p += 4;
+	rec->r.ver.nextcheck = buf32_to_ulong (p); p += 4;
 	p += 4;
 	p += 4;
-	rec->r.ver.firstfree =buftoulong(p); p += 4;
+	rec->r.ver.firstfree =buf32_to_ulong (p); p += 4;
 	p += 4;
-	rec->r.ver.trusthashtbl =buftoulong(p); p += 4;
+	rec->r.ver.trusthashtbl =buf32_to_ulong (p); p += 4;
 	if( recnum ) {
 	    log_error( _("%s: version record with recnum %lu\n"), db_name,
 							     (ulong)recnum );
@@ -1238,17 +1238,17 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
 	}
 	break;
       case RECTYPE_FREE:
-	rec->r.free.next  = buftoulong(p); p += 4;
+	rec->r.free.next  = buf32_to_ulong (p); p += 4;
 	break;
       case RECTYPE_HTBL:
 	for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) {
-	    rec->r.htbl.item[i] = buftoulong(p); p += 4;
+	    rec->r.htbl.item[i] = buf32_to_ulong (p); p += 4;
 	}
 	break;
       case RECTYPE_HLST:
-	rec->r.hlst.next = buftoulong(p); p += 4;
+	rec->r.hlst.next = buf32_to_ulong (p); p += 4;
 	for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
-	    rec->r.hlst.rnum[i] = buftoulong(p); p += 4;
+	    rec->r.hlst.rnum[i] = buf32_to_ulong (p); p += 4;
 	}
 	break;
       case RECTYPE_TRUST:
@@ -1257,12 +1257,12 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
         rec->r.trust.depth = *p++;
         rec->r.trust.min_ownertrust = *p++;
         p++;
-	rec->r.trust.validlist = buftoulong(p); p += 4;
+	rec->r.trust.validlist = buf32_to_ulong (p); p += 4;
 	break;
       case RECTYPE_VALID:
 	memcpy( rec->r.valid.namehash, p, 20); p+=20;
         rec->r.valid.validity = *p++;
-	rec->r.valid.next = buftoulong(p); p += 4;
+	rec->r.valid.next = buf32_to_ulong (p); p += 4;
 	rec->r.valid.full_count = *p++;
 	rec->r.valid.marginal_count = *p++;
 	break;
@@ -1570,7 +1570,7 @@ migrate_from_v2 ()
           ottable_size += 1000;
           ottable = xrealloc (ottable, ottable_size * sizeof *ottable);
         }
-      ottable[ottable_used].keyrecno = buftoulong (oldbuf+6);
+      ottable[ottable_used].keyrecno = buf32_to_ulong (oldbuf+6);
       ottable[ottable_used].ot = oldbuf[18];
       ottable[ottable_used].okay = 0;
       memset (ottable[ottable_used].fpr,0, 20);
diff --git a/g10/trustdb.c b/g10/trustdb.c
index a541106..e4317e2 100644
--- a/g10/trustdb.c
+++ b/g10/trustdb.c
@@ -1624,7 +1624,7 @@ mark_usable_uid_certs (KBNODE keyblock, KBNODE uidnode,
           u32 expire;
 
           p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIG_EXPIRE, NULL );
-          expire = p? sig->timestamp + buffer_to_u32(p) : 0;
+          expire = p? sig->timestamp + buf32_to_u32 (p) : 0;
 
           if (expire==0 || expire > curtime )
             {
diff --git a/include/host2net.h b/include/host2net.h
index fe0ec41..ecb00dc 100644
--- a/include/host2net.h
+++ b/include/host2net.h
@@ -1,5 +1,5 @@
-/* host2net.h - Some macros
- *	Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+/* host2net.h - Endian conversion macros
+ * Copyright (C) 1998, 2014, 2015  Werner Koch
  *
  * This file is part of GNUPG.
  *
@@ -17,14 +17,11 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef G10_HOST2NET_H
-#define G10_HOST2NET_H
+#ifndef GNUPG_COMMON_HOST2NET_H
+#define GNUPG_COMMON_HOST2NET_H
 
 #include "types.h"
 
-#define buftoulong( p )  ((*(byte*)(p) << 24) | (*((byte*)(p)+1)<< 16) | \
-		       (*((byte*)(p)+2) << 8) | (*((byte*)(p)+3)))
-#define buftoushort( p )  ((*((byte*)(p)) << 8) | (*((byte*)(p)+1)))
 #define ulongtobuf( p, a ) do { 			  \
 			    ((byte*)p)[0] = a >> 24;	\
 			    ((byte*)p)[1] = a >> 16;	\
@@ -35,8 +32,71 @@
 			    ((byte*)p)[0] = a >>  8;	\
 			    ((byte*)p)[1] = a	   ;	\
 			} while(0)
-#define buftou32( p)	buftoulong( (p) )
-#define u32tobuf( p, a) ulongtobuf( (p), (a) )
 
 
-#endif /*G10_HOST2NET_H*/
+static inline unsigned long
+buf16_to_ulong (const void *buffer)
+{
+  const unsigned char *p = buffer;
+
+  return (((unsigned long)p[0] << 8) | p[1]);
+}
+
+static inline unsigned int
+buf16_to_uint (const void *buffer)
+{
+  const unsigned char *p = buffer;
+
+  return (((unsigned int)p[0] << 8) | p[1]);
+}
+
+static inline unsigned short
+buf16_to_ushort (const void *buffer)
+{
+  const unsigned char *p = buffer;
+
+  return (((unsigned short)p[0] << 8) | p[1]);
+}
+
+static inline u16
+buf16_to_u16 (const void *buffer)
+{
+  const unsigned char *p = buffer;
+
+  return (((u16)p[0] << 8) | p[1]);
+}
+
+static inline size_t
+buf32_to_size_t (const void *buffer)
+{
+  const unsigned char *p = buffer;
+
+  return (((size_t)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
+}
+
+static inline unsigned long
+buf32_to_ulong (const void *buffer)
+{
+  const unsigned char *p = buffer;
+
+  return (((unsigned long)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
+}
+
+static inline unsigned int
+buf32_to_uint (const void *buffer)
+{
+  const unsigned char *p = buffer;
+
+  return (((unsigned int)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
+}
+
+static inline u32
+buf32_to_u32 (const void *buffer)
+{
+  const unsigned char *p = buffer;
+
+  return (((u32)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
+}
+
+
+#endif /*GNUPG_COMMON_HOST2NET_H*/

commit 7106165fd3161b614445d459df3b333d557d9d02
Author: Werner Koch <wk at gnupg.org>
Date:   Sat Feb 21 23:10:31 2015 -0500

    doc: Change remaining http links to gnupg.org to https
    
    --
    GnuPG-bug-id: 1830
    
    [dkg: rebased to STABLE-BRANCH-1-4]
    Signed-off-by: Daniel Kahn Gillmor <dkg at fifthhorseman.net>

diff --git a/doc/gpg.texi b/doc/gpg.texi
index 7d08756..67dc3d0 100644
--- a/doc/gpg.texi
+++ b/doc/gpg.texi
@@ -321,7 +321,7 @@ useful for debugging.
 Present a menu to work with a smartcard. The subcommand "help" provides
 an overview on available commands. For a detailed description, please
 see the Card HOWTO at
-http://www.gnupg.org/documentation/howtos.html#GnuPG-cardHOWTO .
+https://gnupg.org/documentation/howtos.html#GnuPG-cardHOWTO .
 
 @item --card-status
 @opindex card-status
diff --git a/g10/misc.c b/g10/misc.c
index 68b4cea..60ecf96 100644
--- a/g10/misc.c
+++ b/g10/misc.c
@@ -462,7 +462,7 @@ md5_digest_warn (int show)
       log_info (_("WARNING: digest algorithm %s is deprecated\n"),
                 digest_algo_to_string (DIGEST_ALGO_MD5));
       log_info (_("please see %s for more information\n"),
-                "http://www.gnupg.org/faq/weak-digest-algos.html");
+                "https://gnupg.org/faq/weak-digest-algos.html");
       warned = 1;
     }
 }
@@ -477,7 +477,7 @@ not_in_gpg1_notice (void)
     {
       log_info (_("NOTE: This feature is not available in %s\n"), "GnuPG 1.x");
       log_info (_("please see %s for more information\n"),
-                "http://www.gnupg.org/faq/features-not-in-gnupg-1.html");
+                "https://gnupg.org/faq/features-not-in-gnupg-1.html");
       warned = 1;
     }
 }
diff --git a/g10/sig-check.c b/g10/sig-check.c
index d6bbb92..b7709c1 100644
--- a/g10/sig-check.c
+++ b/g10/sig-check.c
@@ -99,7 +99,7 @@ signature_check2( PKT_signature *sig, MD_HANDLE digest, u32 *r_expiredate,
 		log_info(_("WARNING: signing subkey %s is not"
 			   " cross-certified\n"),keystr_from_pk(pk));
 		log_info(_("please see %s for more information\n"),
-			 "http://www.gnupg.org/faq/subkey-cross-certify.html");
+			 "https://gnupg.org/faq/subkey-cross-certify.html");
 		/* --require-cross-certification makes this warning an
                      error.  TODO: change the default to require this
                      after more keys have backsigs. */

commit 81d3e541326e94d26a953aa70afc3cb149d11ebe
Author: Werner Koch <wk at gnupg.org>
Date:   Sat Feb 21 23:10:30 2015 -0500

    gpg: Prevent an invalid memory read using a garbled keyring.
    
    * g10/keyring.c (keyring_get_keyblock): Whitelist allowed packet
    types.
    --
    
    The keyring DB code did not reject packets which don't belong into a
    keyring.  If for example the keyblock contains a literal data packet
    it is expected that the processing code stops at the data packet and
    reads from the input stream which is referenced from the data packets.
    Obviously the keyring processing code does not and cannot do that.
    However, when exporting this messes up the IOBUF and leads to an
    invalid read of sizeof (int).
    
    We now skip all packets which are not allowed in a keyring.
    
    Reported-by: Hanno Böck <hanno at hboeck.de>
    
    (back ported from commit f0f71a721ccd7ab9e40b8b6b028b59632c0cc648)
    
    [dkg: rebased to STABLE-BRANCH-1-4]
    Signed-off-by: Daniel Kahn Gillmor <dkg at fifthhorseman.net>

diff --git a/g10/keyring.c b/g10/keyring.c
index 108e107..270bf8e 100644
--- a/g10/keyring.c
+++ b/g10/keyring.c
@@ -400,8 +400,26 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
             rc = G10ERR_INV_KEYRING;
             break;
         }
-	if (pkt->pkttype == PKT_COMPRESSED) {
-	    log_error ("skipped compressed packet in keyring\n");
+
+        /* Filter allowed packets.  */
+        switch (pkt->pkttype){
+          case PKT_PUBLIC_KEY:
+          case PKT_PUBLIC_SUBKEY:
+          case PKT_SECRET_KEY:
+          case PKT_SECRET_SUBKEY:
+          case PKT_USER_ID:
+          case PKT_ATTRIBUTE:
+          case PKT_SIGNATURE:
+            break; /* Allowed per RFC.  */
+          case PKT_RING_TRUST:
+          case PKT_OLD_COMMENT:
+          case PKT_COMMENT:
+          case PKT_GPG_CONTROL:
+            break; /* Allowed by us.  */
+
+          default:
+	    log_error ("skipped packet of type %d in keyring\n",
+                       (int)pkt->pkttype);
 	    free_packet(pkt);
 	    init_packet(pkt);
 	    continue;
@@ -467,7 +485,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
     if (rc || !ret_kb)
 	release_kbnode (keyblock);
     else {
-        /*(duplicated form the loop body)*/
+        /*(duplicated from the loop body)*/
         if ( pkt && pkt->pkttype == PKT_RING_TRUST
              && lastnode
              && lastnode->pkt->pkttype == PKT_SIGNATURE

commit 68f260f77a9e4f5cacf0a58e4f55ddee125d3f00
Author: Werner Koch <wk at gnupg.org>
Date:   Sat Feb 21 23:10:29 2015 -0500

    gpg: Fix a NULL-deref in export due to invalid packet lengths.
    
    * g10/build-packet.c (write_fake_data): Take care of a NULL stored as
    opaque MPI.
    --
    
    Reported-by: Hanno Böck <hanno at hboeck.de>
    
    (back ported from commit 0835d2f44ef62eab51fce6a927908f544e01cf8f)
    
    [dkg: rebased to STABLE-BRANCH-1-4]
    Signed-off-by: Daniel Kahn Gillmor <dkg at fifthhorseman.net>

diff --git a/g10/build-packet.c b/g10/build-packet.c
index abe0181..499dd68 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -193,7 +193,8 @@ write_fake_data( IOBUF out, MPI a )
 	void *p;
 
 	p = mpi_get_opaque( a, &i );
-	iobuf_write( out, p, i );
+	if (p)
+          iobuf_write( out, p, i );
     }
 }
 

commit 2e8db53854506572e9d5b5908e143b5ca28f30f5
Author: Werner Koch <wk at gnupg.org>
Date:   Sat Feb 21 23:10:28 2015 -0500

    gpg: Fix a NULL-deref due to empty ring trust packets.
    
    * g10/parse-packet.c (parse_trust): Always allocate a packet.
    --
    
    Reported-by: Hanno Böck <hanno at hboeck.de>
    Signed-off-by: Werner Koch <wk at gnupg.org>
    
    (back ported from commit 39978487863066e59bb657f5fe4e8baab510da7e)
    
    [dkg: rebased to STABLE-BRANCH-1-4]
    Signed-off-by: Daniel Kahn Gillmor <dkg at fifthhorseman.net>

diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index c0b6ad6..e7e923b 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -2245,11 +2245,13 @@ parse_trust( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
 {
   int c;
 
+  (void)pkttype;
+
+  pkt->pkt.ring_trust = xmalloc( sizeof *pkt->pkt.ring_trust );
   if (pktlen)
     {
       c = iobuf_get_noeof(inp);
       pktlen--;
-      pkt->pkt.ring_trust = xmalloc( sizeof *pkt->pkt.ring_trust );
       pkt->pkt.ring_trust->trustval = c;
       pkt->pkt.ring_trust->sigcache = 0;
       if (!c && pktlen==1)
@@ -2267,8 +2269,10 @@ parse_trust( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
     }
   else
     {
-      if( list_mode )
-	fprintf (listfp, ":trust packet: empty\n");
+      pkt->pkt.ring_trust->trustval = 0;
+      pkt->pkt.ring_trust->sigcache = 0;
+      if (list_mode)
+        fprintf (listfp, ":trust packet: empty\n");
     }
   iobuf_skip_rest (inp, pktlen, 0);
 }

commit 27d7addccf782d5cb0084cb17522d712d4a6d6b6
Author: Werner Koch <wk at gnupg.org>
Date:   Sat Feb 21 23:10:27 2015 -0500

    gpg: Limit the size of key packets to a sensible value.
    
    * g10/parse-packet.c (MAX_KEY_PACKET_LENGTH): New.
    (MAX_UID_PACKET_LENGTH): New.
    (MAX_COMMENT_PACKET_LENGTH): New.
    (MAX_ATTR_PACKET_LENGTH): New.
    (parse_key): Limit the size of a key packet to 256k.
    (parse_user_id): Use macro for the packet size limit.
    (parse_attribute): Ditto.
    (parse_comment): Ditto.
    --
    
    Without that it is possible to force gpg to allocate large amounts of
    memory by using a bad encoded MPI.  This would be an too easy DoS.
    Another way to mitigate would be to change the MPI read function to
    allocate memory dynamically while reading the MPI.  However, that
    complicates and possibly slows down the code.  A too large key packet
    is in any case a sign for broken data and thus gpg should not use it.
    
    Reported-by: Hanno Böck
    GnuPG-bug-id: 1823
    Signed-off-by: Werner Koch <wk at gnupg.org>
    
    (back ported from commit 382ba4b137b42d5f25a7e256bb7c053ee5ac7b64)
    
    [dkg: rebased to STABLE-BRANCH-1-4]
    Signed-off-by: Daniel Kahn Gillmor <dkg at fifthhorseman.net>

diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index e4e524c..c0b6ad6 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -40,6 +40,12 @@
 #define MAX_EXTERN_MPI_BITS 16384
 #endif
 
+/* Maximum length of packets to avoid excessive memory allocation.  */
+#define MAX_KEY_PACKET_LENGTH     (256 * 1024)
+#define MAX_UID_PACKET_LENGTH     (  2 * 1024)
+#define MAX_COMMENT_PACKET_LENGTH ( 64 * 1024)
+#define MAX_ATTR_PACKET_LENGTH    ( 16 * 1024*1024)
+
 
 static int mpi_print_mode;
 static int list_mode;
@@ -1663,6 +1669,13 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
         rc = G10ERR_INVALID_PACKET;
 	goto leave;
     }
+    else if (pktlen > MAX_KEY_PACKET_LENGTH) {
+        log_error ("packet(%d) too large\n", pkttype);
+        if (list_mode)
+            fputs (":key packet: [too large]\n", listfp);
+        rc = G10ERR_INVALID_PACKET;
+        goto leave;
+    }
 
     timestamp = read_32(inp); pktlen -= 4;
     if( is_v4 ) {
@@ -2083,7 +2096,7 @@ parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
        allocatable, and a very large pktlen could actually cause our
        allocation to wrap around in xmalloc to a small number. */
 
-    if(pktlen>2048)
+    if (pktlen > MAX_UID_PACKET_LENGTH)
       {
 	log_error("packet(%d) too large\n", pkttype);
 	iobuf_skip_rest(inp, pktlen, 0);
@@ -2152,6 +2165,19 @@ parse_attribute( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
 {
     byte *p;
 
+    (void)pkttype;
+
+    /* We better cap the size of an attribute packet to make DoS not
+       too easy.  16MB should be more then enough for one attribute
+       packet (ie. a photo).  */
+    if (pktlen > MAX_ATTR_PACKET_LENGTH) {
+        log_error ("packet(%d) too large\n", pkttype);
+        if (list_mode)
+          fprintf (listfp, ":attribute packet: [too large]\n");
+        iobuf_skip_rest (inp, pktlen, 0);
+        return G10ERR_INVALID_PACKET;
+      }
+
 #define EXTRA_UID_NAME_SPACE 71
     packet->pkt.user_id = xmalloc_clear(sizeof *packet->pkt.user_id
 					+ EXTRA_UID_NAME_SPACE);
@@ -2186,7 +2212,7 @@ parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
        overflow in the malloc below.  Comment packets are actually not
        anymore define my OpenPGP and we even stopped to use our
        private comment packet. */
-    if (pktlen>65536)
+    if (pktlen > MAX_COMMENT_PACKET_LENGTH)
       {
 	log_error ("packet(%d) too large\n", pkttype);
 	iobuf_skip_rest (inp, pktlen, 0);

commit 20e14e331de4a7e9746650f8b39c1a66d2565c9e
Author: Werner Koch <wk at gnupg.org>
Date:   Sat Feb 21 23:10:26 2015 -0500

    gpg: Allow predefined names as answer to the keygen.algo prompt.
    
    * g10/keygen.c (ask_algo): Add list of strings.
    
    --
    Signed-off-by: Werner Koch <wk at gnupg.org>
    (backported from commit b1d5ed6ac842469afcb84868d0f6641dc286a6c7)
    
    [dkg: rebased to STABLE-BRANCH-1-4]
    Signed-off-by: Daniel Kahn Gillmor <dkg at fifthhorseman.net>

diff --git a/doc/DETAILS b/doc/DETAILS
index 7f12e21..de0f21c 100644
--- a/doc/DETAILS
+++ b/doc/DETAILS
@@ -1251,3 +1251,33 @@ This can be implemented using Hurd's translator mechanism.
 However, I think the whole key server stuff has to be re-thought;
 I have some ideas and probably create a white paper.
 
+
+Algorithm names for the "keygen.algo" prompt
+============================================
+
+  When using a --command-fd controlled key generation or "addkey"
+  there is way to know the number to enter on the "keygen.algo"
+  prompt.  The displayed numbers are for human reception and may
+  change with releases.  To provide a stable way to enter a desired
+  algorithm choice the prompt also accepts predefined names for the
+  algorithms, which will not change.
+
+   | Name    | No | Description                     |
+   |---------+----+---------------------------------|
+   | rsa+rsa |  1 | RSA and RSA (default)           |
+   | dsa+elg |  2 | DSA and Elgamal                 |
+   | dsa     |  3 | DSA (sign only)                 |
+   | rsa/s   |  4 | RSA (sign only)                 |
+   | elg     |  5 | Elgamal (encrypt only)          |
+   | rsa/e   |  6 | RSA (encrypt only)              |
+   | dsa/*   |  7 | DSA (set your own capabilities) |
+   | rsa/*   |  8 | RSA (set your own capabilities) |
+
+   If one of the "foo/*" names are used a "keygen.flags" prompt needs
+   to be answered as well.  Instead of toggling the predefined flags,
+   it is also possible to set them direct: Use a "=" character
+   directly followed by a comination of "a" (for authentication), "s"
+   (for signing), or "c" (for certification).
+
+
+#<eof>#
diff --git a/g10/keygen.c b/g10/keygen.c
index 5af0043..995ba63 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -1481,7 +1481,7 @@ ask_key_flags(int algo,int subkey)
 static int
 ask_algo (int addmode, int *r_subkey_algo, unsigned int *r_usage)
 {
-  char *answer;
+  char *answer = NULL;
   int algo;
   int dummy_algo;
 
@@ -1512,53 +1512,53 @@ ask_algo (int addmode, int *r_subkey_algo, unsigned int *r_usage)
     {
       *r_usage = 0;
       *r_subkey_algo = 0;
+      xfree (answer);
       answer = cpr_get ("keygen.algo", _("Your selection? "));
       cpr_kill_prompt ();
-      algo = *answer? atoi(answer): 1;
-      xfree (answer);
-      if ( algo == 1 && !addmode )
+      algo = *answer? atoi (answer) : 1;
+      if ((algo == 1 || !strcmp (answer, "rsa+rsa")) && !addmode)
         {
           algo = PUBKEY_ALGO_RSA;
           *r_subkey_algo = PUBKEY_ALGO_RSA;
           break;
 	}
-      else if (algo == 2 && !addmode)
+      else if ((algo == 2 || !strcmp (answer, "dsa+elg")) && !addmode)
         {
           algo = PUBKEY_ALGO_DSA;
           *r_subkey_algo = PUBKEY_ALGO_ELGAMAL_E;
           break;
 	}
-      else if (algo == 3)
+      else if (algo == 3 || !strcmp (answer, "dsa"))
         {
           algo = PUBKEY_ALGO_DSA;
           *r_usage = PUBKEY_USAGE_SIG;
           break;
 	}
-      else if (algo == 4)
+      else if (algo == 4 || !strcmp (answer, "rsa/s"))
         {
           algo = PUBKEY_ALGO_RSA;
           *r_usage = PUBKEY_USAGE_SIG;
           break;
 	}
-      else if (algo == 5 && addmode)
+      else if ((algo == 5 || !strcmp (answer, "elg")) && addmode)
         {
           algo = PUBKEY_ALGO_ELGAMAL_E;
           *r_usage = PUBKEY_USAGE_ENC;
           break;
 	}
-      else if (algo == 6 && addmode)
+      else if ((algo == 6 || !strcmp (answer, "rsa/e")) && addmode)
         {
           algo = PUBKEY_ALGO_RSA;
           *r_usage = PUBKEY_USAGE_ENC;
           break;
 	}
-      else if (algo == 7 && opt.expert)
+      else if ((algo == 7 || !strcmp (answer, "dsa/*")) && opt.expert)
         {
           algo = PUBKEY_ALGO_DSA;
           *r_usage = ask_key_flags (algo, addmode);
           break;
 	}
-      else if (algo == 8 && opt.expert)
+      else if ((algo == 8 || !strcmp (answer, "rsa/*")) && opt.expert)
         {
           algo = PUBKEY_ALGO_RSA;
           *r_usage = ask_key_flags (algo, addmode);
@@ -1566,8 +1566,10 @@ ask_algo (int addmode, int *r_subkey_algo, unsigned int *r_usage)
 	}
       else
         tty_printf (_("Invalid selection.\n"));
+
     }
 
+  xfree(answer);
   return algo;
 }
 

commit 8baf452bb308a59478c9148109f4c78941170ecc
Author: Werner Koch <wk at gnupg.org>
Date:   Sat Feb 21 23:10:25 2015 -0500

    gpg: Print a warning if the subkey expiration may not be what you want.
    
    * g10/keyedit.c (subkey_expire_warning): New.
    keyedit_menu): Call it when needed.
    --
    GnuPG-bug-id: 1715
    
    The heuristic to detect a problem is not very advanced but it should
    catch the most common cases.
    
    (backported from commit ae3d1bbb65b65cf3c57bb14886be120f5e31635d)
    
    [dkg: rebased to STABLE-BRANCH-1-4]
    Signed-off-by: Daniel Kahn Gillmor <dkg at fifthhorseman.net>

diff --git a/g10/keyedit.c b/g10/keyedit.c
index afc5ff4..95be10e 100644
--- a/g10/keyedit.c
+++ b/g10/keyedit.c
@@ -51,6 +51,7 @@ static void show_names(KBNODE keyblock,PKT_public_key *pk,
 static void show_key_with_all_names( KBNODE keyblock, int only_marked,
 	    int with_revoker, int with_fpr, int with_subkeys, int with_prefs );
 static void show_key_and_fingerprint( KBNODE keyblock );
+static void subkey_expire_warning (kbnode_t keyblock);
 static int menu_adduid( KBNODE keyblock, KBNODE sec_keyblock,
 			int photo, const char *photo_name );
 static void menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock );
@@ -1506,6 +1507,7 @@ keyedit_menu( const char *username, STRLIST locusr,
     int redisplay = 1;
     int modified = 0;
     int sec_modified = 0;
+    int run_subkey_warnings = 0;
     int toggle;
     int have_commands = !!commands;
 
@@ -1604,6 +1606,14 @@ keyedit_menu( const char *username, STRLIST locusr,
 	    tty_printf("\n");
 	    redisplay = 0;
 	  }
+
+        if (run_subkey_warnings)
+          {
+            run_subkey_warnings = 0;
+            if (!count_selected_keys (keyblock))
+              subkey_expire_warning (keyblock);
+          }
+
 	do {
 	    xfree(answer);
 	    if( have_commands ) {
@@ -2053,6 +2063,7 @@ keyedit_menu( const char *username, STRLIST locusr,
 	      {
 		merge_keys_and_selfsig( sec_keyblock );
 		merge_keys_and_selfsig( keyblock );
+                run_subkey_warnings = 1;
 		sec_modified = 1;
 		modified = 1;
 		redisplay = 1;
@@ -2952,6 +2963,53 @@ no_primary_warning(KBNODE keyblock)
 	       " the assumed primary.\n"));
 }
 
+
+/* Print a warning if the latest encryption subkey expires soon.  This
+   function is called after the expire data of the primary key has
+   been changed.  */
+static void
+subkey_expire_warning (kbnode_t keyblock)
+{
+  u32 curtime = make_timestamp ();
+  kbnode_t node;
+  PKT_public_key *pk;
+  /* u32 mainexpire = 0; */
+  u32 subexpire = 0;
+  u32 latest_date = 0;
+
+  for (node = keyblock; node; node = node->next)
+    {
+      if (node->pkt->pkttype != PKT_PUBLIC_SUBKEY)
+        continue;
+      pk = node->pkt->pkt.public_key;
+
+      if (!pk->is_valid)
+        continue;
+      if (pk->is_revoked)
+        continue;
+      if (pk->timestamp > curtime)
+        continue; /* Ignore future keys.  */
+      if (!(pk->pubkey_usage & PUBKEY_USAGE_ENC))
+        continue; /* Not an encryption key.  */
+
+      if (pk->timestamp > latest_date || (!pk->timestamp && !latest_date))
+        {
+          latest_date = pk->timestamp;
+          subexpire = pk->expiredate;
+        }
+    }
+
+  if (!subexpire)
+    return;  /* No valid subkey with an expiration time.  */
+
+  if (curtime + (10*86400) > subexpire)
+    {
+      log_info (_("WARNING: Your encryption subkey expires soon.\n"));
+      log_info (_("You may want to change its expiration date too.\n"));
+    }
+}
+
+
 /****************
  * Ask for a new user id, do the selfsignature and put it into
  * both keyblocks.

commit ff53cf06e966dce0daba5f2c84e03ab9db2c3c8b
Author: Werner Koch <wk at gnupg.org>
Date:   Mon Aug 11 16:15:40 2014 +0200

    Use ciphertext blinding for Elgamal decryption.
    
    * cipher/elgamal.c (USE_BLINDING): New.
    (decrypt): Rewrite to use ciphertext blinding.
    --
    
    CVE-id: CVE-2014-3591
    
    As a countermeasure to a new side-channel attacks on sliding windows
    exponentiation we blind the ciphertext for Elgamal decryption.  This
    is similar to what we are doing with RSA.
    
    Unfortunately, the performance impact of Elgamal blinding is quite
    noticeable: For a 3072 bit Elgamal key the decryption used to take
    13ms; with the blinding it takes 24ms.  This has been measured using
    time(1), calling gpg with a 100 byte message, and having gpg modified
    to run the pubkey_decrypt function 100 times and finally scale the
    result (using an i5-2410M CPU @ 2.30GHz TP 220).

diff --git a/cipher/elgamal.c b/cipher/elgamal.c
index 5143ecc..2ec5217 100644
--- a/cipher/elgamal.c
+++ b/cipher/elgamal.c
@@ -31,6 +31,11 @@
 #include "cipher.h"
 #include "elgamal.h"
 
+/* Blinding is used to mitigate side-channel attacks.  You may undef
+   this to speed up the operation in case the system is secured
+   against physical and network mounted side-channel attacks.  */
+#define USE_BLINDING 1
+
 typedef struct {
     MPI p;	    /* prime */
     MPI g;	    /* group generator */
@@ -372,25 +377,55 @@ do_encrypt(MPI a, MPI b, MPI input, ELG_public_key *pkey )
 static void
 decrypt(MPI output, MPI a, MPI b, ELG_secret_key *skey )
 {
-    MPI t1 = mpi_alloc_secure( mpi_get_nlimbs( skey->p ) );
+  MPI t1, t2, r;
+  unsigned int nbits = mpi_get_nbits (skey->p);
+
+  mpi_normalize (a);
+  mpi_normalize (b);
+
+  t1 = mpi_alloc_secure (mpi_nlimb_hint_from_nbits (nbits));
+#ifdef USE_BLINDING
+
+  t2 = mpi_alloc_secure (mpi_nlimb_hint_from_nbits (nbits));
+  r  = mpi_alloc (mpi_nlimb_hint_from_nbits (nbits));
+
+  /* We need a random number of about the prime size.  The random
+     number merely needs to be unpredictable; thus we use level 0.  */
+  randomize_mpi (r, nbits, 0);
+
+  /* t1 = r^x mod p */
+  mpi_powm (t1, r, skey->x, skey->p);
+  /* t2 = (a * r)^-x mod p */
+  mpi_mulm (t2, a, r, skey->p);
+  mpi_powm (t2, t2, skey->x, skey->p);
+  mpi_invm (t2, t2, skey->p);
+  /* t1 = (t1 * t2) mod p*/
+  mpi_mulm (t1, t1, t2, skey->p);
 
-    mpi_normalize (a);
-    mpi_normalize (b);
+  mpi_free (r);
+  mpi_free (t2);
+
+#else /*!USE_BLINDING*/
+
+  /* output = b/(a^x) mod p */
+  mpi_powm (t1, a, skey->x, skey->p);
+  mpi_invm (t1, t1, skey->p);
+
+#endif  /*!USE_BLINDING*/
+
+  mpi_mulm (output, b, t1, skey->p);
 
-    /* output = b/(a^x) mod p */
-    mpi_powm( t1, a, skey->x, skey->p );
-    mpi_invm( t1, t1, skey->p );
-    mpi_mulm( output, b, t1, skey->p );
 #if 0
-    if( DBG_CIPHER ) {
-	log_mpidump("elg decrypted x= ", skey->x);
-	log_mpidump("elg decrypted p= ", skey->p);
-	log_mpidump("elg decrypted a= ", a);
-	log_mpidump("elg decrypted b= ", b);
-	log_mpidump("elg decrypted M= ", output);
+  if (DBG_CIPHER)
+    {
+      log_mpidump("elg decrypted x= ", skey->x);
+      log_mpidump("elg decrypted p= ", skey->p);
+      log_mpidump("elg decrypted a= ", a);
+      log_mpidump("elg decrypted b= ", b);
+      log_mpidump("elg decrypted M= ", output);
     }
 #endif
-    mpi_free(t1);
+  mpi_free (t1);
 }
 
 

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

Summary of changes:
 cipher/elgamal.c      | 63 ++++++++++++++++++++++++++++++---------
 doc/DETAILS           | 30 +++++++++++++++++++
 doc/gpg.texi          |  2 +-
 g10/apdu.c            | 27 ++++++++---------
 g10/app-openpgp.c     |  3 +-
 g10/armor.c           | 37 +++++++++++++++++++++++
 g10/build-packet.c    | 15 ++++++----
 g10/ccid-driver.c     |  3 +-
 g10/filter.h          |  2 ++
 g10/getkey.c          | 17 ++++++-----
 g10/import.c          | 40 ++++++++++++++++---------
 g10/keyedit.c         | 58 ++++++++++++++++++++++++++++++++++++
 g10/keygen.c          | 38 ++++++++++++------------
 g10/keyid.c           | 36 +++++++++++------------
 g10/keyring.c         | 24 +++++++++++++--
 g10/keyserver.c       | 63 ++++++++++++++++++++++++++++++++++-----
 g10/main.h            |  4 ++-
 g10/misc.c            | 15 ++--------
 g10/parse-packet.c    | 81 +++++++++++++++++++++++++++++++++++----------------
 g10/seckey-cert.c     | 17 +++++++----
 g10/sig-check.c       |  2 +-
 g10/tdbio.c           | 22 +++++++-------
 g10/trustdb.c         |  2 +-
 include/host2net.h    | 80 +++++++++++++++++++++++++++++++++++++++++++-------
 keyserver/curl-shim.c |  2 ++
 25 files changed, 508 insertions(+), 175 deletions(-)


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




More information about the Gnupg-commits mailing list