Debian Bug report logs - #401914
CVE-2006-6235: arbitrary indirect call in GnuPG

version graph

Package: gnupg; Maintainer for gnupg is Debian GnuPG-Maintainers <pkg-gnupg-maint@lists.alioth.debian.org>; Source for gnupg is src:gnupg.

Reported by: Florian Weimer <fw@deneb.enyo.de>

Date: Wed, 6 Dec 2006 19:48:23 UTC

Severity: grave

Tags: security, upstream

Merged with 401894, 401898

Found in versions gnupg/1.4.1-1, gnupg/1.4.5-3

Fixed in version 1.4.6-1

Done: Henrique de Moraes Holschuh <hmh@debian.org>

Bug is archived. No further changes may be made.

Toggle useless messages

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to debian-bugs-dist@lists.debian.org, James Troup <james@nocrew.org>:
Bug#401914; Package gnupg. Full text and rfc822 format available.

Acknowledgement sent to Florian Weimer <fw@deneb.enyo.de>:
New Bug report received and forwarded. Copy sent to James Troup <james@nocrew.org>. Full text and rfc822 format available.

Message #5 received at submit@bugs.debian.org (full text, mbox):

From: Florian Weimer <fw@deneb.enyo.de>
To: submit@bugs.debian.org
Subject: CVE-2006-6235: arbitrary indirect call in GnuPG
Date: Wed, 06 Dec 2006 20:43:25 +0100
Package: gnupg
Version: 1.4.5-3
Severity: grave
Tags: security upstream

From: Werner Koch <wk@g10code.com>
Subject: [Announce] GnuPG: remotely controllable function pointer [CVE-2006-6235]
To: gnupg-announce@gnupg.org, info-gnu@gnu.org
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  <wk@g10code.com>

	* 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";
     }




Merged 401894 401898 401914. Request was from Florian Weimer <fw@deneb.enyo.de> to control@bugs.debian.org. Full text and rfc822 format available.

Forcibly Merged 401894 401898 401914. Request was from Andreas Barth <aba@not.so.argh.org> to control@bugs.debian.org. Full text and rfc822 format available.

Bug archived. Request was from Debbugs Internal Request <owner@bugs.debian.org> to internal_control@bugs.debian.org. (Sun, 24 Jun 2007 16:36:58 GMT) Full text and rfc822 format available.

Send a report that this bug log contains spam.


Debian bug tracking system administrator <owner@bugs.debian.org>. Last modified: Sun Apr 20 19:47:10 2014; Machine Name: buxtehude.debian.org

Debian Bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.