Package: gnupg
Version: 1.4.5-3
Severity: grave
Tags: security upstream
From: Werner Koch <[EMAIL PROTECTED]>
Subject: [Announce] GnuPG: remotely controllable function pointer
[CVE-2006-6235]
To: [EMAIL PROTECTED], [email protected]
Date: Wed, 06 Dec 2006 16:55:52 +0100
GnuPG: remotely controllable function pointer [CVE-2006-6235]
===============================================================
2006-12-04
Summary
=======
Tavis Ormandy of the Gentoo security team identified a severe and
exploitable bug in the processing of encrypted packets in GnuPG.
[ Please do not send private mail in response to this message. The
mailing list gnupg-devel is the best place to discuss this problem
(please subscribe first so you don't need moderator approval [1]). ]
Impact
======
Using malformed OpenPGP packets an attacker is able to modify and
dereference a function pointer in GnuPG. This is a remotely
exploitable bug and affects any use of GnuPG where an attacker can
control the data processed by GnuPG. It is not necessary limited to
encrypted data, also signed data may be affected.
Affected versions: All versions of GnuPG < 1.4.6
All versions of GnuPG-2 < 2.0.2
All beta versions of GnuPG-2 (1.9.0 .. 1.9.95)
Affected tools: gpg, gpgv, gpg2 and gpgv2.
Affected platforms: All.
gpg-agent, gpgsm as well as other tools are not affected.
A workaround is not known.
[...]
This is a patch against GnuPG 1.4.5. Change the directory to g10/ and
apply this patch.
2006-12-02 Werner Koch <[EMAIL PROTECTED]>
* encr-data.c: Allocate DFX context on the heap and not on the
stack. Changes at several places. Fixes CVE-2006-6235.
--- encr-data.c.orig 2006-05-16 14:34:26.000000000 +0200
+++ encr-data.c 2006-12-04 11:58:53.000000000 +0100
@@ -44,7 +44,27 @@ typedef struct {
char defer[20];
int defer_filled;
int eof_seen;
-} decode_filter_ctx_t;
+ int refcount;
+} *decode_filter_ctx_t;
+
+
+/* Helper to release the decode context. */
+static void
+release_dfx_context (decode_filter_ctx_t dfx)
+{
+ if (!dfx)
+ return;
+
+ assert (dfx->refcount);
+ if ( !--dfx->refcount )
+ {
+ cipher_close (dfx->cipher_hd);
+ dfx->cipher_hd = NULL;
+ md_close (dfx->mdc_hash);
+ dfx->mdc_hash = NULL;
+ xfree (dfx);
+ }
+}
/****************
@@ -60,7 +80,10 @@ decrypt_data( void *procctx, PKT_encrypt
unsigned blocksize;
unsigned nprefix;
- memset( &dfx, 0, sizeof dfx );
+
+ dfx = xcalloc (1, sizeof *dfx);
+ dfx->refcount = 1;
+
if( opt.verbose && !dek->algo_info_printed ) {
const char *s = cipher_algo_to_string( dek->algo );
if( s )
@@ -79,15 +102,15 @@ decrypt_data( void *procctx, PKT_encrypt
BUG();
if( ed->mdc_method ) {
- dfx.mdc_hash = md_open( ed->mdc_method, 0 );
+ dfx->mdc_hash = md_open ( ed->mdc_method, 0 );
if ( DBG_HASHING )
- md_start_debug(dfx.mdc_hash, "checkmdc");
+ md_start_debug (dfx->mdc_hash, "checkmdc");
}
- dfx.cipher_hd = cipher_open( dek->algo,
- ed->mdc_method? CIPHER_MODE_CFB
- : CIPHER_MODE_AUTO_CFB, 1 );
+ dfx->cipher_hd = cipher_open ( dek->algo,
+ ed->mdc_method? CIPHER_MODE_CFB
+ : CIPHER_MODE_AUTO_CFB, 1 );
/* log_hexdump( "thekey", dek->key, dek->keylen );*/
- rc = cipher_setkey( dfx.cipher_hd, dek->key, dek->keylen );
+ rc = cipher_setkey ( dfx->cipher_hd, dek->key, dek->keylen );
if( rc == G10ERR_WEAK_KEY )
{
log_info(_("WARNING: message was encrypted with"
@@ -105,7 +128,7 @@ decrypt_data( void *procctx, PKT_encrypt
goto leave;
}
- cipher_setiv( dfx.cipher_hd, NULL, 0 );
+ cipher_setiv ( dfx->cipher_hd, NULL, 0 );
if( ed->len ) {
for(i=0; i < (nprefix+2) && ed->len; i++, ed->len-- ) {
@@ -122,8 +145,8 @@ decrypt_data( void *procctx, PKT_encrypt
else
temp[i] = c;
}
- cipher_decrypt( dfx.cipher_hd, temp, temp, nprefix+2);
- cipher_sync( dfx.cipher_hd );
+ cipher_decrypt ( dfx->cipher_hd, temp, temp, nprefix+2);
+ cipher_sync ( dfx->cipher_hd );
p = temp;
/* log_hexdump( "prefix", temp, nprefix+2 ); */
if(dek->symmetric
@@ -133,34 +156,34 @@ decrypt_data( void *procctx, PKT_encrypt
goto leave;
}
- if( dfx.mdc_hash )
- md_write( dfx.mdc_hash, temp, nprefix+2 );
+ if ( dfx->mdc_hash )
+ md_write ( dfx->mdc_hash, temp, nprefix+2 );
- if( ed->mdc_method )
- iobuf_push_filter( ed->buf, mdc_decode_filter, &dfx );
+ dfx->refcount++;
+ if ( ed->mdc_method )
+ iobuf_push_filter( ed->buf, mdc_decode_filter, dfx );
else
- iobuf_push_filter( ed->buf, decode_filter, &dfx );
+ iobuf_push_filter( ed->buf, decode_filter, dfx );
proc_packets( procctx, ed->buf );
ed->buf = NULL;
- if( ed->mdc_method && dfx.eof_seen == 2 )
+ if( ed->mdc_method && dfx->eof_seen == 2 )
rc = G10ERR_INVALID_PACKET;
else if( ed->mdc_method ) { /* check the mdc */
int datalen = md_digest_length( ed->mdc_method );
- cipher_decrypt( dfx.cipher_hd, dfx.defer, dfx.defer, 20);
- md_final( dfx.mdc_hash );
+ cipher_decrypt ( dfx->cipher_hd, dfx->defer, dfx->defer, 20);
+ md_final ( dfx->mdc_hash );
if( datalen != 20
- || memcmp(md_read( dfx.mdc_hash, 0 ), dfx.defer, datalen) )
+ || memcmp(md_read( dfx->mdc_hash, 0 ), dfx->defer, datalen) )
rc = G10ERR_BAD_SIGN;
- /*log_hexdump("MDC calculated:", md_read( dfx.mdc_hash, 0), datalen);*/
- /*log_hexdump("MDC message :", dfx.defer, 20);*/
+ /*log_hexdump("MDC calculated:",md_read( dfx->mdc_hash, 0), datalen);*/
+ /*log_hexdump("MDC message :", dfx->defer, 20);*/
}
leave:
- cipher_close(dfx.cipher_hd);
- md_close( dfx.mdc_hash );
+ release_dfx_context (dfx);
return rc;
}
@@ -171,7 +194,7 @@ static int
mdc_decode_filter( void *opaque, int control, IOBUF a,
byte *buf, size_t *ret_len)
{
- decode_filter_ctx_t *dfx = opaque;
+ decode_filter_ctx_t dfx = opaque;
size_t n, size = *ret_len;
int rc = 0;
int c;
@@ -226,8 +249,10 @@ mdc_decode_filter( void *opaque, int con
}
if( n ) {
- cipher_decrypt( dfx->cipher_hd, buf, buf, n);
- md_write( dfx->mdc_hash, buf, n );
+ if (dfx->cipher_hd)
+ cipher_decrypt( dfx->cipher_hd, buf, buf, n);
+ if (dfx->mdc_hash)
+ md_write( dfx->mdc_hash, buf, n );
}
else {
assert( dfx->eof_seen );
@@ -235,6 +260,9 @@ mdc_decode_filter( void *opaque, int con
}
*ret_len = n;
}
+ else if ( control == IOBUFCTRL_FREE ) {
+ release_dfx_context (dfx);
+ }
else if( control == IOBUFCTRL_DESC ) {
*(char**)buf = "mdc_decode_filter";
}
@@ -244,7 +272,7 @@ mdc_decode_filter( void *opaque, int con
static int
decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
{
- decode_filter_ctx_t *fc = opaque;
+ decode_filter_ctx_t fc = opaque;
size_t n, size = *ret_len;
int rc = 0;
@@ -252,12 +280,17 @@ decode_filter( void *opaque, int control
assert(a);
n = iobuf_read( a, buf, size );
if( n == -1 ) n = 0;
- if( n )
- cipher_decrypt( fc->cipher_hd, buf, buf, n);
+ if( n ) {
+ if (fc->cipher_hd)
+ cipher_decrypt( fc->cipher_hd, buf, buf, n);
+ }
else
rc = -1; /* eof */
*ret_len = n;
}
+ else if ( control == IOBUFCTRL_FREE ) {
+ release_dfx_context (fc);
+ }
else if( control == IOBUFCTRL_DESC ) {
*(char**)buf = "decode_filter";
}
--
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]