diff -u gnupg-1.4.11/debian/changelog gnupg-1.4.11/debian/changelog --- gnupg-1.4.11/debian/changelog +++ gnupg-1.4.11/debian/changelog @@ -1,3 +1,35 @@ +gnupg (1.4.11-3ubuntu2.9) precise-security; urgency=medium + + * Screen responses from keyservers (LP: #1409117) + - d/p/0001-Screen-keyserver-responses.dpatch + - d/p/0002-Make-screening-of-keyserver-result-work-with-multi-k.dpatch + - d/p/0003-Add-kbnode_t-for-easier-backporting.dpatch + - d/p/0004-gpg-Fix-regression-due-to-the-keyserver-import-filte.dpatch + * Fix large key size regression from CVE-2014-5270 changes (LP: #1371766) + - d/p/Add-build-and-runtime-support-for-larger-RSA-key.dpatch + - debian/rules: build with --enable-large-secmem + * SECURITY UPDATE: sidechannel attack on Elgamal + - debian/patches/CVE-2014-3591.dpatch: use ciphertext blinding in + cipher/elgamal.c. + - CVE-2014-3591 + * SECURITY UPDATE: sidechannel attack via timing variations in mpi_powm + - debian/patches/CVE-2015-0837.dpatch: avoid timing variations in + include/mpi.h, mpi/mpi-pow.c, mpi/mpiutil.c. + - CVE-2015-0837 + * SECURITY UPDATE: invalid memory read via invalid keyring + - debian/patches/CVE-2015-1606.dpatch: skip all packets not allowed in + a keyring in g10/keyring.c. + - CVE-2015-1606 + * SECURITY UPDATE: memcpy with overlapping ranges + - debian/patches/CVE-2015-1607.dpatch: use inline functions to convert + buffer data to scalars in g10/apdu.c, g10/app-openpgp.c, + g10/build-packet.c, g10/ccid-driver.c, g10/getkey.c, g10/keygen.c, + g10/keyid.c, g10/misc.c, g10/parse-packet.c, g10/tdbio.c, + g10/trustdb.c, include/host2net.h. + - CVE-2015-1607 + + -- Marc Deslauriers Fri, 27 Mar 2015 08:24:00 -0400 + gnupg (1.4.11-3ubuntu2.7) precise-security; urgency=medium * SECURITY UPDATE: side-channel attack on Elgamal encryption subkeys diff -u gnupg-1.4.11/debian/rules gnupg-1.4.11/debian/rules --- gnupg-1.4.11/debian/rules +++ gnupg-1.4.11/debian/rules @@ -22,7 +22,7 @@ CONFARGS = --prefix=/usr --libexecdir=/usr/lib/ \ --enable-mailto --with-mailprog=/usr/sbin/sendmail \ - --enable-noexecstack + --enable-noexecstack --enable-large-secmem ifneq ($(DEB_BUILD_GNU_TYPE),$(DEB_HOST_GNU_TYPE)) HOSTARG += --host=$(DEB_HOST_GNU_TYPE) diff -u gnupg-1.4.11/debian/patches/00list gnupg-1.4.11/debian/patches/00list --- gnupg-1.4.11/debian/patches/00list +++ gnupg-1.4.11/debian/patches/00list @@ -11,0 +12,9 @@ +0001-Screen-keyserver-responses +0002-Make-screening-of-keyserver-result-work-with-multi-k +0003-Add-kbnode_t-for-easier-backporting +0004-gpg-Fix-regression-due-to-the-keyserver-import-filte +Add-build-and-runtime-support-for-larger-RSA-key +CVE-2014-3591 +CVE-2015-0837 +CVE-2015-1606 +CVE-2015-1607 only in patch2: unchanged: --- gnupg-1.4.11.orig/debian/patches/CVE-2015-1607.dpatch +++ gnupg-1.4.11/debian/patches/CVE-2015-1607.dpatch @@ -0,0 +1,694 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +# From 57af33d9e7c9b20b413b96882e670e75a67a5e65 Mon Sep 17 00:00:00 2001 +# From: Werner Koch +# Date: Sat, 21 Feb 2015 23:10:32 -0500 +# Subject: [PATCH] Use inline functions to convert buffer data to scalars. + +@DPATCH@ +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/g10/apdu.c gnupg-1.4.11/g10/apdu.c +--- gnupg-1.4.11~/g10/apdu.c 2009-07-21 09:21:44.000000000 -0400 ++++ gnupg-1.4.11/g10/apdu.c 2015-03-25 13:59:41.963070843 -0400 +@@ -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" +@@ -903,15 +904,14 @@ + 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", +@@ -1071,15 +1071,14 @@ + 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", +@@ -1204,15 +1203,14 @@ + 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); +@@ -1391,7 +1389,7 @@ + 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"); +@@ -1405,8 +1403,7 @@ + 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", +@@ -1706,7 +1703,7 @@ + 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"); +@@ -1719,8 +1716,8 @@ + (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 -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/g10/app-openpgp.c gnupg-1.4.11/g10/app-openpgp.c +--- gnupg-1.4.11~/g10/app-openpgp.c 2010-10-18 05:15:23.000000000 -0400 ++++ gnupg-1.4.11/g10/app-openpgp.c 2015-03-25 13:59:41.963070843 -0400 +@@ -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 @@ + 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 -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/g10/build-packet.c gnupg-1.4.11/g10/build-packet.c +--- gnupg-1.4.11~/g10/build-packet.c 2010-09-28 04:51:26.000000000 -0400 ++++ gnupg-1.4.11/g10/build-packet.c 2015-03-25 13:59:41.963070843 -0400 +@@ -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 ); +@@ -585,8 +586,7 @@ + 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; + } +@@ -709,7 +709,7 @@ + /* 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 -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/g10/ccid-driver.c gnupg-1.4.11/g10/ccid-driver.c +--- gnupg-1.4.11~/g10/ccid-driver.c 2009-12-21 09:35:05.000000000 -0500 ++++ gnupg-1.4.11/g10/ccid-driver.c 2015-03-25 13:59:41.967070877 -0400 +@@ -92,6 +92,7 @@ + #include + + #include "ccid-driver.h" ++#include "../include/host2net.h" + + #define DRVNAME "ccid-driver: " + +@@ -292,7 +293,7 @@ + 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 -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/g10/getkey.c gnupg-1.4.11/g10/getkey.c +--- gnupg-1.4.11~/g10/getkey.c 2015-03-25 13:59:38.000000000 -0400 ++++ gnupg-1.4.11/g10/getkey.c 2015-03-25 13:59:41.967070877 -0400 +@@ -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 +@@ -1385,14 +1386,14 @@ + + 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; +@@ -1517,8 +1518,8 @@ + + /* 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; + +@@ -1732,9 +1733,9 @@ + 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; + } + +@@ -2156,8 +2157,8 @@ + 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 -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/g10/keygen.c gnupg-1.4.11/g10/keygen.c +--- gnupg-1.4.11~/g10/keygen.c 2015-03-25 13:59:38.000000000 -0400 ++++ gnupg-1.4.11/g10/keygen.c 2015-03-25 14:00:44.251594381 -0400 +@@ -40,6 +40,7 @@ + #include "i18n.h" + #include "cardglue.h" + #include "keyserver-internal.h" ++#include "host2net.h" + + #define MAX_PREFS 30 + +@@ -837,10 +838,7 @@ + } + 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 +@@ -857,14 +855,14 @@ + 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 -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/g10/keyid.c gnupg-1.4.11/g10/keyid.c +--- gnupg-1.4.11~/g10/keyid.c 2008-12-11 11:40:05.000000000 -0500 ++++ gnupg-1.4.11/g10/keyid.c 2015-03-25 13:59:41.971070912 -0400 +@@ -32,6 +32,7 @@ + #include "mpi.h" + #include "keydb.h" + #include "i18n.h" ++#include "host2net.h" + + int + pubkey_letter( int algo ) +@@ -230,15 +231,8 @@ + { + 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); + } + +@@ -289,8 +283,8 @@ + 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]; +@@ -343,8 +337,8 @@ + 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]; +@@ -387,8 +381,8 @@ + } + 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]; +@@ -676,8 +670,8 @@ + 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 -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/g10/misc.c gnupg-1.4.11/g10/misc.c +--- gnupg-1.4.11~/g10/misc.c 2010-09-28 05:00:25.000000000 -0400 ++++ gnupg-1.4.11/g10/misc.c 2015-03-25 13:59:41.971070912 -0400 +@@ -295,17 +295,6 @@ + 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 -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/g10/parse-packet.c gnupg-1.4.11/g10/parse-packet.c +--- gnupg-1.4.11~/g10/parse-packet.c 2010-06-18 04:06:08.000000000 -0400 ++++ gnupg-1.4.11/g10/parse-packet.c 2015-03-25 13:59:41.975070944 -0400 +@@ -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 +@@ -88,7 +89,7 @@ + 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; + } +@@ -97,7 +98,7 @@ + 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); +@@ -377,7 +378,8 @@ + } + 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 ) +@@ -872,14 +874,15 @@ + 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"); + } +@@ -907,9 +910,9 @@ + 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"); + } +@@ -932,8 +935,8 @@ + 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: + { +@@ -1178,8 +1181,7 @@ + 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; + } +@@ -1401,7 +1403,7 @@ + + 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"); +@@ -1409,16 +1411,16 @@ + 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; + +@@ -1999,9 +2001,8 @@ + 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 -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/g10/tdbio.c gnupg-1.4.11/g10/tdbio.c +--- gnupg-1.4.11~/g10/tdbio.c 2009-12-15 03:56:26.000000000 -0500 ++++ gnupg-1.4.11/g10/tdbio.c 2015-03-25 14:01:46.032113708 -0400 +@@ -1210,13 +1210,13 @@ + rec->r.ver.cert_depth = *p++; + rec->r.ver.trust_model = *p++; + p += 3; +- 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 ); +@@ -1229,17 +1229,17 @@ + } + 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: +@@ -1248,12 +1248,12 @@ + 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; +@@ -1560,7 +1560,7 @@ + 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 -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/g10/trustdb.c gnupg-1.4.11/g10/trustdb.c +--- gnupg-1.4.11~/g10/trustdb.c 2009-12-21 09:34:19.000000000 -0500 ++++ gnupg-1.4.11/g10/trustdb.c 2015-03-25 13:59:41.975070944 -0400 +@@ -1585,7 +1585,7 @@ + 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 -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/include/host2net.h gnupg-1.4.11/include/host2net.h +--- gnupg-1.4.11~/include/host2net.h 2008-12-11 11:39:58.000000000 -0500 ++++ gnupg-1.4.11/include/host2net.h 2015-03-25 13:59:41.975070944 -0400 +@@ -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 . + */ + +-#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*/ only in patch2: unchanged: --- gnupg-1.4.11.orig/debian/patches/CVE-2015-0837.dpatch +++ gnupg-1.4.11/debian/patches/CVE-2015-0837.dpatch @@ -0,0 +1,217 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +# From 6cbc75e71295f23431c4ab95edc7573f2fc28476 Mon Sep 17 00:00:00 2001 +# From: NIIBE Yutaka +# Date: Thu, 26 Feb 2015 21:00:05 +0900 +# Subject: [PATCH] mpi: Avoid data-dependent timing variations in mpi_powm. + +@DPATCH@ +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/include/mpi.h gnupg-1.4.11/include/mpi.h +--- gnupg-1.4.11~/include/mpi.h 2008-12-11 11:39:58.000000000 -0500 ++++ gnupg-1.4.11/include/mpi.h 2015-03-25 13:59:21.846901778 -0400 +@@ -81,6 +81,7 @@ + void mpi_set_secure( MPI a ); + void mpi_clear( MPI a ); + void mpi_set( MPI w, MPI u); ++void mpi_set_cond( MPI w, MPI u, unsigned long set); + void mpi_set_ui( MPI w, ulong u); + MPI mpi_alloc_set_ui( unsigned long u); + void mpi_m_check( MPI a ); +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/mpi/mpi-pow.c gnupg-1.4.11/mpi/mpi-pow.c +--- gnupg-1.4.11~/mpi/mpi-pow.c 2015-03-25 13:59:17.000000000 -0400 ++++ gnupg-1.4.11/mpi/mpi-pow.c 2015-03-25 13:59:21.846901778 -0400 +@@ -345,7 +345,7 @@ + *xsize_p = rsize + ssize; + } + +-#define SIZE_B_2I3 ((1 << (5 - 1)) - 1) ++#define SIZE_PRECOMP ((1 << (5 - 1))) + + /**************** + * RES = BASE ^ EXPO mod MOD +@@ -376,11 +376,12 @@ + mpi_ptr_t bp_marker = NULL; + mpi_ptr_t ep_marker = NULL; + mpi_ptr_t xp_marker = NULL; +- mpi_ptr_t b_2i3[SIZE_B_2I3]; /* Pre-computed array: BASE^3, ^5, ^7, ... */ +- mpi_size_t b_2i3size[SIZE_B_2I3]; ++ mpi_ptr_t precomp[SIZE_PRECOMP]; /* Pre-computed array: BASE^1, ^3, ^5, ... */ ++ mpi_size_t precomp_size[SIZE_PRECOMP]; + mpi_size_t W; + mpi_ptr_t base_u; + mpi_size_t base_u_size; ++ mpi_size_t max_u_size; + + esize = expo->nlimbs; + msize = mod->nlimbs; +@@ -494,7 +495,7 @@ + + /* Main processing. */ + { +- mpi_size_t i, j; ++ mpi_size_t i, j, k; + mpi_ptr_t xp; + mpi_size_t xsize; + int c; +@@ -508,33 +509,29 @@ + memset( &karactx, 0, sizeof karactx ); + negative_result = (ep[0] & 1) && bsign; + +- /* Precompute B_2I3[], BASE^(2 * i + 3), BASE^3, ^5, ^7, ... */ ++ /* Precompute PRECOMP[], BASE^(2 * i + 1), BASE^1, ^3, ^5, ... */ + if (W > 1) /* X := BASE^2 */ + mul_mod (xp, &xsize, bp, bsize, bp, bsize, mp, msize, &karactx); +- for (i = 0; i < (1 << (W - 1)) - 1; i++) +- { /* B_2I3[i] = BASE^(2 * i + 3) */ +- if (i == 0) +- { +- base_u = bp; +- base_u_size = bsize; +- } +- else +- { +- base_u = b_2i3[i-1]; +- base_u_size = b_2i3size[i-1]; +- } +- ++ base_u = precomp[0] = mpi_alloc_limb_space (bsize, esec); ++ base_u_size = max_u_size = precomp_size[0] = bsize; ++ MPN_COPY (precomp[0], bp, bsize); ++ for (i = 1; i < (1 << (W - 1)); i++) ++ { /* PRECOMP[i] = BASE^(2 * i + 1) */ + if (xsize >= base_u_size) + mul_mod (rp, &rsize, xp, xsize, base_u, base_u_size, + mp, msize, &karactx); + else + mul_mod (rp, &rsize, base_u, base_u_size, xp, xsize, + mp, msize, &karactx); +- b_2i3[i] = mpi_alloc_limb_space (rsize, esec); +- b_2i3size[i] = rsize; +- MPN_COPY (b_2i3[i], rp, rsize); ++ base_u = precomp[i] = mpi_alloc_limb_space (rsize, esec); ++ base_u_size = precomp_size[i] = rsize; ++ if (max_u_size < base_u_size) ++ max_u_size = base_u_size; ++ MPN_COPY (precomp[i], rp, rsize); + } + ++ base_u = mpi_alloc_limb_space (max_u_size, esec); ++ + i = esize - 1; + + /* Main loop. +@@ -620,17 +617,26 @@ + rsize = xsize; + } + +- if (e0 == 0) +- { +- base_u = bp; +- base_u_size = bsize; +- } +- else ++ /* ++ * base_u <= precomp[e0] ++ * base_u_size <= precomp_size[e0]; ++ */ ++ base_u_size = 0; ++ for (k = 0; k < (1<< (W - 1)); k++) + { +- base_u = b_2i3[e0 - 1]; +- base_u_size = b_2i3size[e0 -1]; +- } ++ struct gcry_mpi w, u; ++ w.alloced = w.nlimbs = precomp_size[k]; ++ u.alloced = u.nlimbs = precomp_size[k]; ++ w.nbits = w.nlimbs * BITS_PER_MPI_LIMB; ++ u.nbits = u.nlimbs * BITS_PER_MPI_LIMB; ++ w.sign = u.sign = 0; ++ w.flags = u.flags = 0; ++ w.d = base_u; ++ u.d = precomp[k]; + ++ mpi_set_cond (&w, &u, k == e0); ++ base_u_size |= (precomp_size[k] & ((mpi_size_t)0 - (k == e0)) ); ++ } + mul_mod (xp, &xsize, rp, rsize, base_u, base_u_size, + mp, msize, &karactx); + tp = rp; rp = xp; xp = tp; +@@ -656,15 +662,21 @@ + + if (e != 0) + { +- if ((e>>1) == 0) +- { +- base_u = bp; +- base_u_size = bsize; +- } +- else ++ base_u_size = 0; ++ for (k = 0; k < (1<< (W - 1)); k++) + { +- base_u = b_2i3[(e>>1) - 1]; +- base_u_size = b_2i3size[(e>>1) -1]; ++ struct gcry_mpi w, u; ++ w.alloced = w.nlimbs = precomp_size[k]; ++ u.alloced = u.nlimbs = precomp_size[k]; ++ w.nbits = w.nlimbs * BITS_PER_MPI_LIMB; ++ u.nbits = u.nlimbs * BITS_PER_MPI_LIMB; ++ w.sign = u.sign = 0; ++ w.flags = u.flags = 0; ++ w.d = base_u; ++ u.d = precomp[k]; ++ ++ mpi_set_cond (&w, &u, k == (e>>1)); ++ base_u_size |= (precomp_size[k] & ((mpi_size_t)0 - (k == (e>>1))) ); + } + + mul_mod (xp, &xsize, rp, rsize, base_u, base_u_size, +@@ -714,8 +726,9 @@ + MPN_NORMALIZE (rp, rsize); + + mpihelp_release_karatsuba_ctx (&karactx ); +- for (i = 0; i < (1 << (W - 1)) - 1; i++) +- mpi_free_limb_space (b_2i3[i]); ++ for (i = 0; i < (1 << (W - 1)); i++) ++ mpi_free_limb_space (precomp[i]); ++ mpi_free_limb_space (base_u); + } + + /* Fixup for negative results. */ +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/mpi/mpiutil.c gnupg-1.4.11/mpi/mpiutil.c +--- gnupg-1.4.11~/mpi/mpiutil.c 2008-12-11 11:39:43.000000000 -0500 ++++ gnupg-1.4.11/mpi/mpiutil.c 2015-03-25 13:59:21.846901778 -0400 +@@ -433,6 +433,34 @@ + + + void ++mpi_set_cond( MPI w, MPI u, unsigned long set) ++{ ++ mpi_size_t i; ++ mpi_size_t nlimbs = u->alloced; ++ mpi_limb_t mask = ((mpi_limb_t)0) - !!set; ++ mpi_limb_t x; ++ ++ if (w->alloced != u->alloced) ++ log_bug ("mpi_set_cond: different sizes\n"); ++ ++ for (i = 0; i < nlimbs; i++) ++ { ++ x = mask & (w->d[i] ^ u->d[i]); ++ w->d[i] = w->d[i] ^ x; ++ } ++ ++ x = mask & (w->nlimbs ^ u->nlimbs); ++ w->nlimbs = w->nlimbs ^ x; ++ ++ x = mask & (w->nbits ^ u->nbits); ++ w->nbits = w->nbits ^ x; ++ ++ x = mask & (w->sign ^ u->sign); ++ w->sign = w->sign ^ x; ++} ++ ++ ++void + mpi_set_ui( MPI w, unsigned long u) + { + RESIZE_IF_NEEDED(w, 1); only in patch2: unchanged: --- gnupg-1.4.11.orig/debian/patches/0002-Make-screening-of-keyserver-result-work-with-multi-k.dpatch +++ gnupg-1.4.11/debian/patches/0002-Make-screening-of-keyserver-result-work-with-multi-k.dpatch @@ -0,0 +1,120 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +# From 955524f4359ba9e9de213f4067c38df9ae4808a8 Mon Sep 17 00:00:00 2001 +# From: Werner Koch +# Date: Wed, 25 Jun 2014 14:33:34 +0200 +# Subject: [PATCH] Make screening of keyserver result work with multi-key +# commands. + +@DPATCH@ +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/g10/keyserver.c gnupg-1.4.11/g10/keyserver.c +--- gnupg-1.4.11~/g10/keyserver.c 2015-03-25 13:55:23.000000000 -0400 ++++ gnupg-1.4.11/g10/keyserver.c 2015-03-25 13:56:00.733211909 -0400 +@@ -954,13 +954,25 @@ + #define KEYSERVER_ARGS_NOKEEP " -o \"%o\" \"%i\"" + + ++/* Structure to convey the arg to keyserver_retrieval_filter. */ ++struct ks_retrieval_filter_arg_s ++{ ++ KEYDB_SEARCH_DESC *desc; ++ int ndesc; ++}; ++ ++ + /* Check whether a key matches the search description. The filter + returns 0 if the key shall be imported. Note that this kind of + filter is not related to the iobuf filters. */ + static int +-keyserver_retrieval_filter (PKT_public_key *pk, PKT_secret_key *sk, void *arg) ++keyserver_retrieval_filter (PKT_public_key *pk, PKT_secret_key *sk, ++ void *opaque) + { +- KEYDB_SEARCH_DESC *desc = arg; ++ struct ks_retrieval_filter_arg_s *arg = opaque; ++ KEYDB_SEARCH_DESC *desc = arg->desc; ++ int ndesc = arg->ndesc; ++ int n; + u32 keyid[2]; + byte fpr[MAX_FINGERPRINT_LEN]; + size_t fpr_len = 0; +@@ -969,32 +981,40 @@ + if (sk) + return G10ERR_GENERAL; + ++ if (!ndesc) ++ return 0; /* Okay if no description given. */ ++ + fingerprint_from_pk (pk, fpr, &fpr_len); + keyid_from_pk (pk, keyid); + + /* Compare requested and returned fingerprints if available. */ +- if (desc->mode == KEYDB_SEARCH_MODE_FPR20) +- { +- if (fpr_len != 20 || memcmp (fpr, desc->u.fpr, 20)) +- return G10ERR_GENERAL; +- } +- else if (desc->mode == KEYDB_SEARCH_MODE_FPR16) +- { +- if (fpr_len != 16 || memcmp (fpr, desc->u.fpr, 16)) +- return G10ERR_GENERAL; +- } +- else if (desc->mode == KEYDB_SEARCH_MODE_LONG_KID) +- { +- if (keyid[0] != desc->u.kid[0] || keyid[1] != desc->u.kid[1]) +- return G10ERR_GENERAL; +- } +- else if (desc->mode == KEYDB_SEARCH_MODE_SHORT_KID) ++ for (n = 0; n < ndesc; n++) + { +- if (keyid[1] != desc->u.kid[1]) +- return G10ERR_GENERAL; ++ if (desc[n].mode == KEYDB_SEARCH_MODE_FPR20) ++ { ++ if (fpr_len == 20 && !memcmp (fpr, desc[n].u.fpr, 20)) ++ return 0; ++ } ++ else if (desc[n].mode == KEYDB_SEARCH_MODE_FPR16) ++ { ++ if (fpr_len == 16 && !memcmp (fpr, desc[n].u.fpr, 16)) ++ return 0; ++ } ++ else if (desc[n].mode == KEYDB_SEARCH_MODE_LONG_KID) ++ { ++ if (keyid[0] == desc[n].u.kid[0] && keyid[1] == desc[n].u.kid[1]) ++ return 0; ++ } ++ else if (desc[n].mode == KEYDB_SEARCH_MODE_SHORT_KID) ++ { ++ if (keyid[1] == desc[n].u.kid[1]) ++ return 0; ++ } ++ else ++ return 0; + } + +- return 0; ++ return G10ERR_GENERAL; + } + + +@@ -1534,6 +1554,7 @@ + case KS_GETNAME: + { + void *stats_handle; ++ struct ks_retrieval_filter_arg_s filterarg; + + stats_handle=import_new_stats_handle(); + +@@ -1544,9 +1565,11 @@ + way to do this could be to continue parsing this + line-by-line and make a temp iobuf for each key. */ + ++ filterarg.desc = desc; ++ filterarg.ndesc = count; + import_keys_stream(spawn->fromchild,stats_handle,fpr,fpr_len, + opt.keyserver_options.import_options, +- keyserver_retrieval_filter, desc); ++ keyserver_retrieval_filter, &filterarg); + + import_print_stats(stats_handle); + import_release_stats_handle(stats_handle); only in patch2: unchanged: --- gnupg-1.4.11.orig/debian/patches/0004-gpg-Fix-regression-due-to-the-keyserver-import-filte.dpatch +++ gnupg-1.4.11/debian/patches/0004-gpg-Fix-regression-due-to-the-keyserver-import-filte.dpatch @@ -0,0 +1,215 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +# From d58552760b26d840824658814d59c8b1a25a4219 Mon Sep 17 00:00:00 2001 +# From: Werner Koch +# Date: Wed, 6 Aug 2014 17:11:21 +0200 +# Subject: [PATCH 2/2] gpg: Fix regression due to the keyserver import filter. + +@DPATCH@ +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/g10/import.c gnupg-1.4.11/g10/import.c +--- gnupg-1.4.11~/g10/import.c 2015-03-25 13:56:41.000000000 -0400 ++++ gnupg-1.4.11/g10/import.c 2015-03-25 13:56:46.693598034 -0400 +@@ -60,16 +60,16 @@ + + static int import( IOBUF inp, const char* fname,struct stats_s *stats, + unsigned char **fpr,size_t *fpr_len,unsigned int options, +- import_filter filter, void *filter_arg ); ++ import_filter_t filter, void *filter_arg ); + 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, + unsigned char **fpr,size_t *fpr_len, + unsigned int options,int from_sk, +- import_filter filter, void *filter_arg); ++ import_filter_t filter, void *filter_arg); + static int import_secret_one( const char *fname, KBNODE keyblock, + struct stats_s *stats, unsigned int options, +- import_filter filter, void *filter_arg); ++ import_filter_t filter, void *filter_arg); + static int import_revoke_cert( const char *fname, KBNODE node, + struct stats_s *stats); + static int chk_self_sigs( const char *fname, KBNODE keyblock, +@@ -167,7 +167,7 @@ + import_keys_internal( IOBUF inp, char **fnames, int nnames, + void *stats_handle, unsigned char **fpr, size_t *fpr_len, + unsigned int options, +- import_filter filter, void *filter_arg) ++ import_filter_t filter, void *filter_arg) + { + int i, rc = 0; + struct stats_s *stats = stats_handle; +@@ -239,7 +239,7 @@ + int + import_keys_stream( IOBUF inp, void *stats_handle, + unsigned char **fpr, size_t *fpr_len,unsigned int options, +- import_filter filter, void *filter_arg ) ++ import_filter_t filter, void *filter_arg ) + { + return import_keys_internal (inp, NULL, 0, stats_handle, fpr, fpr_len, + options, filter, filter_arg); +@@ -248,7 +248,7 @@ + static int + import( IOBUF inp, const char* fname,struct stats_s *stats, + unsigned char **fpr,size_t *fpr_len,unsigned int options, +- import_filter filter, void *filter_arg) ++ import_filter_t filter, void *filter_arg) + { + PACKET *pending_pkt = NULL; + KBNODE keyblock = NULL; +@@ -753,7 +753,7 @@ + static int + import_one( const char *fname, KBNODE keyblock, struct stats_s *stats, + unsigned char **fpr,size_t *fpr_len,unsigned int options, +- int from_sk, import_filter filter, void *filter_arg) ++ int from_sk, import_filter_t filter, void *filter_arg) + { + PKT_public_key *pk; + PKT_public_key *pk_orig; +@@ -793,7 +793,7 @@ + return 0; + } + +- if (filter && filter (pk, NULL, filter_arg)) ++ if (filter && filter (keyblock, filter_arg)) + { + log_error (_("key %s: %s\n"), keystr_from_pk(pk), + _("rejected by import filter")); +@@ -1169,7 +1169,7 @@ + static int + import_secret_one( const char *fname, KBNODE keyblock, + struct stats_s *stats, unsigned int options, +- import_filter filter, void *filter_arg) ++ import_filter_t filter, void *filter_arg) + { + PKT_secret_key *sk; + KBNODE node, uidnode; +@@ -1185,7 +1185,7 @@ + keyid_from_sk( sk, keyid ); + uidnode = find_next_kbnode( keyblock, PKT_USER_ID ); + +- if (filter && filter (NULL, sk, filter_arg)) { ++ if (filter && filter (keyblock, filter_arg)) { + log_error (_("secret key %s: %s\n"), keystr_from_sk(sk), + _("rejected by import filter")); + return 0; +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/g10/keyserver.c gnupg-1.4.11/g10/keyserver.c +--- gnupg-1.4.11~/g10/keyserver.c 2015-03-25 13:56:41.000000000 -0400 ++++ gnupg-1.4.11/g10/keyserver.c 2015-03-25 13:56:46.697598067 -0400 +@@ -966,52 +966,68 @@ + returns 0 if the key shall be imported. Note that this kind of + filter is not related to the iobuf filters. */ + static int +-keyserver_retrieval_filter (PKT_public_key *pk, PKT_secret_key *sk, +- void *opaque) ++keyserver_retrieval_filter (kbnode_t keyblock, void *opaque) + { + struct ks_retrieval_filter_arg_s *arg = opaque; + KEYDB_SEARCH_DESC *desc = arg->desc; + int ndesc = arg->ndesc; ++ kbnode_t node; ++ PKT_public_key *pk; + int n; + u32 keyid[2]; + byte fpr[MAX_FINGERPRINT_LEN]; + size_t fpr_len = 0; + +- /* Secret keys are not expected from a keyserver. Do not import. */ +- if (sk) +- return G10ERR_GENERAL; ++ /* Secret keys are not expected from a keyserver. We do not ++ care about secret subkeys because the import code takes care ++ of skipping them. Not allowing an import of a public key ++ with a secret subkey would make it too easy to inhibit the ++ downloading of a public key. Recall that keyservers do only ++ limited checks. */ ++ node = find_kbnode (keyblock, PKT_SECRET_KEY); ++ if (node) ++ return G10ERR_GENERAL; /* Do not import. */ + + if (!ndesc) + return 0; /* Okay if no description given. */ + +- fingerprint_from_pk (pk, fpr, &fpr_len); +- keyid_from_pk (pk, keyid); +- +- /* Compare requested and returned fingerprints if available. */ +- for (n = 0; n < ndesc; n++) ++ /* Loop over all key packets. */ ++ for (node = keyblock; node; node = node->next) + { +- if (desc[n].mode == KEYDB_SEARCH_MODE_FPR20) +- { +- if (fpr_len == 20 && !memcmp (fpr, desc[n].u.fpr, 20)) +- return 0; +- } +- else if (desc[n].mode == KEYDB_SEARCH_MODE_FPR16) +- { +- if (fpr_len == 16 && !memcmp (fpr, desc[n].u.fpr, 16)) +- return 0; +- } +- else if (desc[n].mode == KEYDB_SEARCH_MODE_LONG_KID) +- { +- if (keyid[0] == desc[n].u.kid[0] && keyid[1] == desc[n].u.kid[1]) +- return 0; +- } +- else if (desc[n].mode == KEYDB_SEARCH_MODE_SHORT_KID) ++ if (node->pkt->pkttype != PKT_PUBLIC_KEY ++ && node->pkt->pkttype != PKT_PUBLIC_SUBKEY) ++ continue; ++ ++ pk = node->pkt->pkt.public_key; ++ fingerprint_from_pk (pk, fpr, &fpr_len); ++ keyid_from_pk (pk, keyid); ++ ++ /* Compare requested and returned fingerprints if available. */ ++ for (n = 0; n < ndesc; n++) + { +- if (keyid[1] == desc[n].u.kid[1]) +- return 0; ++ if (desc[n].mode == KEYDB_SEARCH_MODE_FPR20) ++ { ++ if (fpr_len == 20 && !memcmp (fpr, desc[n].u.fpr, 20)) ++ return 0; ++ } ++ else if (desc[n].mode == KEYDB_SEARCH_MODE_FPR16) ++ { ++ if (fpr_len == 16 && !memcmp (fpr, desc[n].u.fpr, 16)) ++ return 0; ++ } ++ else if (desc[n].mode == KEYDB_SEARCH_MODE_LONG_KID) ++ { ++ if (keyid[0] == desc[n].u.kid[0] && keyid[1] == desc[n].u.kid[1]) ++ return 0; ++ } ++ else if (desc[n].mode == KEYDB_SEARCH_MODE_SHORT_KID) ++ { ++ if (keyid[1] == desc[n].u.kid[1]) ++ return 0; ++ } ++ else /* No keyid or fingerprint - can't check. */ ++ return 0; /* allow import. */ + } +- else +- return 0; + } + + return G10ERR_GENERAL; +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/g10/main.h gnupg-1.4.11/g10/main.h +--- gnupg-1.4.11~/g10/main.h 2015-03-25 13:56:41.000000000 -0400 ++++ gnupg-1.4.11/g10/main.h 2015-03-25 13:56:46.697598067 -0400 +@@ -214,14 +214,14 @@ + + /*-- import.c --*/ + +-typedef int (*import_filter)(PKT_public_key *pk, PKT_secret_key *sk, void *arg); ++typedef int (*import_filter_t)(kbnode_t keyblock, void *arg); + + int parse_import_options(char *str,unsigned int *options,int noisy); + 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 filter, void *filter_arg); ++ import_filter_t filter, void *filter_arg); + void *import_new_stats_handle (void); + void import_release_stats_handle (void *p); + void import_print_stats (void *hd); only in patch2: unchanged: --- gnupg-1.4.11.orig/debian/patches/0003-Add-kbnode_t-for-easier-backporting.dpatch +++ gnupg-1.4.11/debian/patches/0003-Add-kbnode_t-for-easier-backporting.dpatch @@ -0,0 +1,18 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +# From dcf58b3471b1c9ba87a826aa132033e506664808 Mon Sep 17 00:00:00 2001 +# From: Werner Koch +# Date: Wed, 6 Aug 2014 17:09:15 +0200 +# Subject: [PATCH 1/2] Add kbnode_t for easier backporting. + +@DPATCH@ +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/g10/global.h gnupg-1.4.11/g10/global.h +--- gnupg-1.4.11~/g10/global.h 2008-12-11 11:40:05.000000000 -0500 ++++ gnupg-1.4.11/g10/global.h 2015-03-25 13:56:28.385444218 -0400 +@@ -23,6 +23,7 @@ + #define MAX_FINGERPRINT_LEN 20 + + typedef struct kbnode_struct *KBNODE; ++typedef struct kbnode_struct *kbnode_t; + typedef struct keydb_search_desc KEYDB_SEARCH_DESC; + + #endif /*GPG_GLOBAL_H*/ only in patch2: unchanged: --- gnupg-1.4.11.orig/debian/patches/CVE-2014-3591.dpatch +++ gnupg-1.4.11/debian/patches/CVE-2014-3591.dpatch @@ -0,0 +1,92 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +# From ff53cf06e966dce0daba5f2c84e03ab9db2c3c8b Mon Sep 17 00:00:00 2001 +# From: Werner Koch +# Date: Mon, 11 Aug 2014 16:15:40 +0200 +# Subject: [PATCH] Use ciphertext blinding for Elgamal decryption. + +@DPATCH@ +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/cipher/elgamal.c gnupg-1.4.11/cipher/elgamal.c +--- gnupg-1.4.11~/cipher/elgamal.c 2015-03-25 13:59:01.000000000 -0400 ++++ gnupg-1.4.11/cipher/elgamal.c 2015-03-25 13:59:09.318796491 -0400 +@@ -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 @@ + 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); ++ 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_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); + } + + only in patch2: unchanged: --- gnupg-1.4.11.orig/debian/patches/0001-Screen-keyserver-responses.dpatch +++ gnupg-1.4.11/debian/patches/0001-Screen-keyserver-responses.dpatch @@ -0,0 +1,398 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +# From 5230304349490f31aa64ee2b69a8a2bc06bf7816 Mon Sep 17 00:00:00 2001 +# From: Stefan Tomanek +# Date: Thu, 30 Jan 2014 00:57:43 +0100 +# Subject: [PATCH] Screen keyserver responses. + +@DPATCH@ +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/g10/import.c gnupg-1.4.11/g10/import.c +--- gnupg-1.4.11~/g10/import.c 2015-03-25 13:51:43.000000000 -0400 ++++ gnupg-1.4.11/g10/import.c 2015-03-25 13:53:51.628127467 -0400 +@@ -59,14 +59,17 @@ + + + static int import( IOBUF inp, const char* fname,struct stats_s *stats, +- unsigned char **fpr,size_t *fpr_len,unsigned int options ); ++ unsigned char **fpr,size_t *fpr_len,unsigned int options, ++ import_filter filter, void *filter_arg ); + 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, + unsigned char **fpr,size_t *fpr_len, +- unsigned int options,int from_sk); ++ unsigned int options,int from_sk, ++ import_filter filter, void *filter_arg); + static int import_secret_one( const char *fname, KBNODE keyblock, +- struct stats_s *stats, unsigned int options); ++ struct stats_s *stats, unsigned int options, ++ import_filter filter, void *filter_arg); + static int import_revoke_cert( const char *fname, KBNODE node, + struct stats_s *stats); + static int chk_self_sigs( const char *fname, KBNODE keyblock, +@@ -163,7 +166,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 ) ++ unsigned int options, ++ import_filter filter, void *filter_arg) + { + int i, rc = 0; + struct stats_s *stats = stats_handle; +@@ -172,7 +176,8 @@ + stats = import_new_stats_handle (); + + if (inp) { +- rc = import( inp, "[stream]", stats, fpr, fpr_len, options); ++ rc = import (inp, "[stream]", stats, fpr, fpr_len, options, ++ filter, filter_arg); + } + else { + if( !fnames && !nnames ) +@@ -193,7 +198,8 @@ + log_error(_("can't open `%s': %s\n"), fname, strerror(errno) ); + else + { +- rc = import( inp2, fname, stats, fpr, fpr_len, options ); ++ rc = import (inp2, fname, stats, fpr, fpr_len, options, ++ NULL, NULL); + iobuf_close(inp2); + /* Must invalidate that ugly cache to actually close it. */ + iobuf_ioctl (NULL, 2, 0, (char*)fname); +@@ -226,19 +232,23 @@ + import_keys( char **fnames, int nnames, + void *stats_handle, unsigned int options ) + { +- import_keys_internal(NULL,fnames,nnames,stats_handle,NULL,NULL,options); ++ import_keys_internal (NULL, fnames, nnames, stats_handle, NULL, NULL, ++ options, NULL, NULL); + } + + int + import_keys_stream( IOBUF inp, void *stats_handle, +- unsigned char **fpr, size_t *fpr_len,unsigned int options ) ++ unsigned char **fpr, size_t *fpr_len,unsigned int options, ++ import_filter filter, void *filter_arg ) + { +- return import_keys_internal(inp,NULL,0,stats_handle,fpr,fpr_len,options); ++ return import_keys_internal (inp, NULL, 0, stats_handle, fpr, fpr_len, ++ options, filter, filter_arg); + } + + static int + import( IOBUF inp, const char* fname,struct stats_s *stats, +- unsigned char **fpr,size_t *fpr_len,unsigned int options ) ++ unsigned char **fpr,size_t *fpr_len,unsigned int options, ++ import_filter filter, void *filter_arg) + { + PACKET *pending_pkt = NULL; + KBNODE keyblock = NULL; +@@ -255,9 +265,11 @@ + + while( !(rc = read_block( inp, &pending_pkt, &keyblock) )) { + if( keyblock->pkt->pkttype == PKT_PUBLIC_KEY ) +- rc = import_one( fname, keyblock, stats, fpr, fpr_len, options, 0); +- else if( keyblock->pkt->pkttype == PKT_SECRET_KEY ) +- rc = import_secret_one( fname, keyblock, stats, options ); ++ rc = import_one (fname, keyblock, stats, fpr, fpr_len, options, 0, ++ filter, filter_arg); ++ else if( keyblock->pkt->pkttype == PKT_SECRET_KEY ) ++ rc = import_secret_one (fname, keyblock, stats, options, ++ filter, filter_arg); + else if( keyblock->pkt->pkttype == PKT_SIGNATURE + && keyblock->pkt->pkt.signature->sig_class == 0x20 ) + rc = import_revoke_cert( fname, keyblock, stats ); +@@ -741,7 +753,7 @@ + static int + import_one( const char *fname, KBNODE keyblock, struct stats_s *stats, + unsigned char **fpr,size_t *fpr_len,unsigned int options, +- int from_sk ) ++ int from_sk, import_filter filter, void *filter_arg) + { + PKT_public_key *pk; + PKT_public_key *pk_orig; +@@ -780,6 +792,13 @@ + log_error( _("key %s: no user ID\n"), keystr_from_pk(pk)); + return 0; + } ++ ++ if (filter && filter (pk, NULL, filter_arg)) ++ { ++ log_error (_("key %s: %s\n"), keystr_from_pk(pk), ++ _("rejected by import filter")); ++ return 0; ++ } + + if (opt.interactive) { + if(is_status_enabled()) +@@ -1149,7 +1168,8 @@ + */ + static int + import_secret_one( const char *fname, KBNODE keyblock, +- struct stats_s *stats, unsigned int options) ++ struct stats_s *stats, unsigned int options, ++ import_filter filter, void *filter_arg) + { + PKT_secret_key *sk; + KBNODE node, uidnode; +@@ -1165,6 +1185,12 @@ + keyid_from_sk( sk, keyid ); + uidnode = find_next_kbnode( keyblock, PKT_USER_ID ); + ++ if (filter && filter (NULL, sk, filter_arg)) { ++ log_error (_("secret key %s: %s\n"), keystr_from_sk(sk), ++ _("rejected by import filter")); ++ return 0; ++ } ++ + if( opt.verbose ) + { + log_info( "sec %4u%c/%s %s ", +@@ -1237,8 +1263,9 @@ + KBNODE pub_keyblock=sec_to_pub_keyblock(keyblock); + if(pub_keyblock) + { +- import_one(fname,pub_keyblock,stats, +- NULL,NULL,opt.import_options,1); ++ import_one (fname, pub_keyblock, stats, ++ NULL, NULL, opt.import_options, 1, ++ NULL, NULL); + release_kbnode(pub_keyblock); + } + } +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/g10/keyserver.c gnupg-1.4.11/g10/keyserver.c +--- gnupg-1.4.11~/g10/keyserver.c 2010-09-28 04:55:23.000000000 -0400 ++++ gnupg-1.4.11/g10/keyserver.c 2015-03-25 13:54:37.392511839 -0400 +@@ -650,7 +650,7 @@ + case 'R': + work->flags|=1; + break; +- ++ + case 'd': + case 'D': + work->flags|=2; +@@ -904,7 +904,7 @@ + /* Leave this commented out or now, and perhaps for a very long + time. All HKPish servers return HTML error messages for + no-key-found. */ +- /* ++ /* + if(!started) + log_info(_("keyserver does not support searching\n")); + else +@@ -953,7 +953,52 @@ + #define KEYSERVER_ARGS_KEEP " -o \"%O\" \"%I\"" + #define KEYSERVER_ARGS_NOKEEP " -o \"%o\" \"%i\"" + +-static int ++ ++/* Check whether a key matches the search description. The filter ++ returns 0 if the key shall be imported. Note that this kind of ++ filter is not related to the iobuf filters. */ ++static int ++keyserver_retrieval_filter (PKT_public_key *pk, PKT_secret_key *sk, void *arg) ++{ ++ KEYDB_SEARCH_DESC *desc = arg; ++ u32 keyid[2]; ++ byte fpr[MAX_FINGERPRINT_LEN]; ++ size_t fpr_len = 0; ++ ++ /* Secret keys are not expected from a keyserver. Do not import. */ ++ if (sk) ++ return G10ERR_GENERAL; ++ ++ fingerprint_from_pk (pk, fpr, &fpr_len); ++ keyid_from_pk (pk, keyid); ++ ++ /* Compare requested and returned fingerprints if available. */ ++ if (desc->mode == KEYDB_SEARCH_MODE_FPR20) ++ { ++ if (fpr_len != 20 || memcmp (fpr, desc->u.fpr, 20)) ++ return G10ERR_GENERAL; ++ } ++ else if (desc->mode == KEYDB_SEARCH_MODE_FPR16) ++ { ++ if (fpr_len != 16 || memcmp (fpr, desc->u.fpr, 16)) ++ return G10ERR_GENERAL; ++ } ++ else if (desc->mode == KEYDB_SEARCH_MODE_LONG_KID) ++ { ++ if (keyid[0] != desc->u.kid[0] || keyid[1] != desc->u.kid[1]) ++ return G10ERR_GENERAL; ++ } ++ else if (desc->mode == KEYDB_SEARCH_MODE_SHORT_KID) ++ { ++ if (keyid[1] != desc->u.kid[1]) ++ return G10ERR_GENERAL; ++ } ++ ++ return 0; ++} ++ ++ ++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, + struct keyserver_spec *keyserver) +@@ -993,7 +1038,7 @@ + the program of this process lives. Fortunately Windows provides + a way to retrieve this and our get_libexecdir function has been + modified to return just this. Setting the exec-path is not +- anymore required. ++ anymore required. + set_exec_path(libexecdir); + */ + #else +@@ -1025,7 +1070,7 @@ + fetcher that can speak that protocol (this is a problem for + LDAP). */ + +- strcat(command,GPGKEYS_PREFIX); ++ strcat(command,GPGKEYS_PREFIX); + strcat(command,scheme); + + /* This "_uri" thing is in case we need to call a direct handler +@@ -1055,7 +1100,7 @@ + { + command=xrealloc(command,strlen(command)+ + strlen(KEYSERVER_ARGS_NOKEEP)+1); +- strcat(command,KEYSERVER_ARGS_NOKEEP); ++ strcat(command,KEYSERVER_ARGS_NOKEEP); + } + + ret=exec_write(&spawn,NULL,command,NULL,0,0); +@@ -1500,7 +1545,8 @@ + line-by-line and make a temp iobuf for each key. */ + + import_keys_stream(spawn->fromchild,stats_handle,fpr,fpr_len, +- opt.keyserver_options.import_options); ++ opt.keyserver_options.import_options, ++ keyserver_retrieval_filter, desc); + + import_print_stats(stats_handle); + import_release_stats_handle(stats_handle); +@@ -1531,7 +1577,7 @@ + return ret; + } + +-static int ++static int + keyserver_work(enum ks_action action,STRLIST list,KEYDB_SEARCH_DESC *desc, + int count,unsigned char **fpr,size_t *fpr_len, + struct keyserver_spec *keyserver) +@@ -1601,7 +1647,7 @@ + #endif /* ! DISABLE_KEYSERVER_HELPERS*/ + } + +-int ++int + keyserver_export(STRLIST users) + { + STRLIST sl=NULL; +@@ -1633,7 +1679,7 @@ + return rc; + } + +-int ++int + keyserver_import(STRLIST users) + { + KEYDB_SEARCH_DESC *desc; +@@ -1693,7 +1739,7 @@ + return keyserver_work(KS_GET,NULL,&desc,1,NULL,NULL,keyserver); + } + +-int ++int + keyserver_import_keyid(u32 *keyid,struct keyserver_spec *keyserver) + { + KEYDB_SEARCH_DESC desc; +@@ -1708,7 +1754,7 @@ + } + + /* code mostly stolen from do_export_stream */ +-static int ++static int + keyidlist(STRLIST users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3) + { + int rc=0,ndesc,num=100; +@@ -1731,10 +1777,10 @@ + } + else + { +- for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++) ++ for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++) + ; + desc = xmalloc ( ndesc * sizeof *desc); +- ++ + for (ndesc=0, sl=users; sl; sl = sl->next) + { + if(classify_user_id (sl->d, desc+ndesc)) +@@ -1747,7 +1793,7 @@ + + while (!(rc = keydb_search (kdbhd, desc, ndesc))) + { +- if (!users) ++ if (!users) + desc[0].mode = KEYDB_SEARCH_MODE_NEXT; + + /* read the keyblock */ +@@ -1850,7 +1896,7 @@ + + if(rc==-1) + rc=0; +- ++ + leave: + if(rc) + xfree(*klist); +@@ -2032,7 +2078,7 @@ + opt.no_armor=1; + + rc=import_keys_stream(key,NULL,fpr,fpr_len, +- opt.keyserver_options.import_options); ++ opt.keyserver_options.import_options, NULL, NULL); + + opt.no_armor=armor_status; + +@@ -2171,7 +2217,7 @@ + snprintf(port,7,":%u",srvlist[i].port); + strcat(keyserver->host,port); + } +- ++ + strcat(keyserver->host," "); + } + +@@ -2187,7 +2233,7 @@ + strcat(keyserver->host,domain); + + append_to_strlist(&list,name); +- ++ + rc=keyserver_work(KS_GETNAME,list,NULL,0,fpr,fpr_len,keyserver); + + free_strlist(list); +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/g10/main.h gnupg-1.4.11/g10/main.h +--- gnupg-1.4.11~/g10/main.h 2009-08-03 12:19:20.000000000 -0400 ++++ gnupg-1.4.11/g10/main.h 2015-03-25 13:51:57.223166764 -0400 +@@ -213,11 +213,15 @@ + MD_HANDLE md, int hash_algo ); + + /*-- import.c --*/ ++ ++typedef int (*import_filter)(PKT_public_key *pk, PKT_secret_key *sk, void *arg); ++ + int parse_import_options(char *str,unsigned int *options,int noisy); + 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 ); ++int import_keys_stream (IOBUF inp,void *stats_hd,unsigned char **fpr, ++ size_t *fpr_len,unsigned int options, ++ import_filter filter, void *filter_arg); + void *import_new_stats_handle (void); + void import_release_stats_handle (void *p); + void import_print_stats (void *hd); only in patch2: unchanged: --- gnupg-1.4.11.orig/debian/patches/CVE-2015-1606.dpatch +++ gnupg-1.4.11/debian/patches/CVE-2015-1606.dpatch @@ -0,0 +1,48 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +# From 81d3e541326e94d26a953aa70afc3cb149d11ebe Mon Sep 17 00:00:00 2001 +# From: Werner Koch +# Date: Sat, 21 Feb 2015 23:10:30 -0500 +# Subject: [PATCH] gpg: Prevent an invalid memory read using a garbled keyring. + +@DPATCH@ +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/g10/keyring.c gnupg-1.4.11/g10/keyring.c +--- gnupg-1.4.11~/g10/keyring.c 2010-10-10 05:16:23.000000000 -0400 ++++ gnupg-1.4.11/g10/keyring.c 2015-03-25 13:59:33.478999538 -0400 +@@ -400,8 +400,26 @@ + 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 @@ + 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 only in patch2: unchanged: --- gnupg-1.4.11.orig/debian/patches/Add-build-and-runtime-support-for-larger-RSA-key.dpatch +++ gnupg-1.4.11/debian/patches/Add-build-and-runtime-support-for-larger-RSA-key.dpatch @@ -0,0 +1,193 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +# From 534e2876acc05f9f8d9b54c18511fe768d77dfb5 Mon Sep 17 00:00:00 2001 +# From: Daniel Kahn Gillmor +# Date: Fri, 3 Oct 2014 12:01:11 -0400 +# Subject: [PATCH] gpg: Add build and runtime support for larger RSA keys + +@DPATCH@ +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/config.h.in gnupg-1.4.11/config.h.in +--- gnupg-1.4.11~/config.h.in 2015-03-25 13:57:03.000000000 -0400 ++++ gnupg-1.4.11/config.h.in 2015-03-25 13:57:09.117786438 -0400 +@@ -664,6 +664,9 @@ + /* Define as the return type of signal handlers (`int' or `void'). */ + #undef RETSIGTYPE + ++/* Size of secure memory buffer */ ++#undef SECMEM_BUFFER_SIZE ++ + /* The size of `time_t', as computed by sizeof. */ + #undef SIZEOF_TIME_T + +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/configure gnupg-1.4.11/configure +--- gnupg-1.4.11~/configure 2010-10-18 04:50:11.000000000 -0400 ++++ gnupg-1.4.11/configure 2015-03-25 13:57:09.121786471 -0400 +@@ -814,6 +814,7 @@ + enable_selinux_support + enable_gnupg_iconv + enable_minimal ++enable_large_secmem + enable_card_support + enable_agent_support + enable_rsa +@@ -1507,6 +1508,7 @@ + enable SELinux support + --disable-gnupg-iconv disable the new iconv code + --enable-minimal build the smallest gpg binary possible ++ --enable-large-secmem allocate extra secure memory + --disable-card-support disable OpenPGP card support + --disable-agent-support disable gpg-agent support + --disable-rsa disable the RSA public key algorithm +@@ -4740,6 +4742,7 @@ + card_support=yes + agent_support=yes + disable_keyserver_path=no ++large_secmem=no + + # Check whether --enable-minimal was given. + if test "${enable_minimal+set}" = set; then : +@@ -4761,6 +4764,29 @@ + + + ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to allocate extra secure memory" >&5 ++$as_echo_n "checking whether to allocate extra secure memory... " >&6; } ++# Check whether --enable-large-secmem was given. ++if test "${enable_large_secmem+set}" = set; then : ++ enableval=$enable_large_secmem; large_secmem=$enableval ++else ++ large_secmem=no ++fi ++ ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $large_secmem" >&5 ++$as_echo "$large_secmem" >&6; } ++if test "$large_secmem" = yes ; then ++ SECMEM_BUFFER_SIZE=65536 ++else ++ SECMEM_BUFFER_SIZE=32768 ++fi ++ ++cat >>confdefs.h <<_ACEOF ++#define SECMEM_BUFFER_SIZE $SECMEM_BUFFER_SIZE ++_ACEOF ++ ++ ++ + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenPGP card support is requested" >&5 + $as_echo_n "checking whether OpenPGP card support is requested... " >&6; } + # Check whether --enable-card-support was given. +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/configure.ac gnupg-1.4.11/configure.ac +--- gnupg-1.4.11~/configure.ac 2010-10-18 04:45:45.000000000 -0400 ++++ gnupg-1.4.11/configure.ac 2015-03-25 13:57:09.105786337 -0400 +@@ -147,6 +147,7 @@ + card_support=yes + agent_support=yes + disable_keyserver_path=no ++large_secmem=no + + AC_ARG_ENABLE(minimal, + AC_HELP_STRING([--enable-minimal],[build the smallest gpg binary possible]), +@@ -166,6 +167,21 @@ + agent_support=no) + + ++AC_MSG_CHECKING([whether to allocate extra secure memory]) ++AC_ARG_ENABLE(large-secmem, ++ AC_HELP_STRING([--enable-large-secmem], ++ [allocate extra secure memory]), ++ large_secmem=$enableval, large_secmem=no) ++AC_MSG_RESULT($large_secmem) ++if test "$large_secmem" = yes ; then ++ SECMEM_BUFFER_SIZE=65536 ++else ++ SECMEM_BUFFER_SIZE=32768 ++fi ++AC_DEFINE_UNQUOTED(SECMEM_BUFFER_SIZE,$SECMEM_BUFFER_SIZE, ++ [Size of secure memory buffer]) ++ ++ + AC_MSG_CHECKING([whether OpenPGP card support is requested]) + AC_ARG_ENABLE(card-support, + AC_HELP_STRING([--disable-card-support], +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/doc/gpg.texi gnupg-1.4.11/doc/gpg.texi +--- gnupg-1.4.11~/doc/gpg.texi 2010-10-18 05:10:48.000000000 -0400 ++++ gnupg-1.4.11/doc/gpg.texi 2015-03-25 13:57:09.109786371 -0400 +@@ -1127,6 +1127,15 @@ + validation. This option is only meaningful if pka-lookups is set. + @end table + ++@item --enable-large-rsa ++@itemx --disable-large-rsa ++@opindex enable-large-rsa ++@opindex disable-large-rsa ++With --gen-key and --batch, enable the creation of larger RSA secret ++keys than is generally recommended (up to 8192 bits). These large ++keys are more expensive to use, and their signatures and ++certifications are also larger. ++ + @item --enable-dsa2 + @itemx --disable-dsa2 + Enable hash truncation for all DSA keys even for old DSA Keys up to +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/g10/gpg.c gnupg-1.4.11/g10/gpg.c +--- gnupg-1.4.11~/g10/gpg.c 2010-07-05 05:17:37.000000000 -0400 ++++ gnupg-1.4.11/g10/gpg.c 2015-03-25 13:57:09.109786371 -0400 +@@ -368,6 +368,8 @@ + oAutoKeyLocate, + oNoAutoKeyLocate, + oAllowMultisigVerification, ++ oEnableLargeRSA, ++ oDisableLargeRSA, + oEnableDSA2, + oDisableDSA2, + oAllowMultipleMessages, +@@ -715,6 +717,8 @@ + { oDebugCCIDDriver, "debug-ccid-driver", 0, "@"}, + #endif + { oAllowMultisigVerification, "allow-multisig-verification", 0, "@"}, ++ { oEnableLargeRSA, "enable-large-rsa", 0, "@"}, ++ { oDisableLargeRSA, "disable-large-rsa", 0, "@"}, + { oEnableDSA2, "enable-dsa2", 0, "@"}, + { oDisableDSA2, "disable-dsa2", 0, "@"}, + { oAllowMultipleMessages, "allow-multiple-messages", 0, "@"}, +@@ -2008,7 +2012,7 @@ + } + #endif + /* initialize the secure memory. */ +- got_secmem=secmem_init( 32768 ); ++ got_secmem=secmem_init( SECMEM_BUFFER_SIZE ); + maybe_setuid = 0; + /* Okay, we are now working under our real uid */ + +@@ -2876,6 +2880,22 @@ + release_akl(); + break; + ++ case oEnableLargeRSA: ++#if SECMEM_BUFFER_SIZE >= 65536 ++ opt.flags.large_rsa=1; ++#else ++ if (configname) ++ log_info("%s:%d: WARNING: gpg not built with large secure " ++ "memory buffer. Ignoring enable-large-rsa\n", ++ configname,configlineno); ++ else ++ log_info("WARNING: gpg not built with large secure " ++ "memory buffer. Ignoring --enable-large-rsa\n"); ++#endif /* SECMEM_BUFFER_SIZE >= 65536 */ ++ break; ++ case oDisableLargeRSA: opt.flags.large_rsa=0; ++ break; ++ + case oEnableDSA2: opt.flags.dsa2=1; break; + case oDisableDSA2: opt.flags.dsa2=0; break; + +diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gnupg-1.4.11~/g10/options.h gnupg-1.4.11/g10/options.h +--- gnupg-1.4.11~/g10/options.h 2009-07-20 04:01:58.000000000 -0400 ++++ gnupg-1.4.11/g10/options.h 2015-03-25 13:57:09.113786404 -0400 +@@ -227,6 +227,7 @@ + unsigned int utf8_filename:1; + unsigned int dsa2:1; + unsigned int allow_multiple_messages:1; ++ unsigned int large_rsa:1; + } flags; + + /* Linked list of ways to find a key if the key isn't on the local