* keyserver.c (parse_keyserver_uri, add_canonical_option): Always append
[gnupg.git] / g10 / parse-packet.c
index c50c8a2..b67ad7f 100644 (file)
@@ -1,5 +1,6 @@
 /* parse-packet.c  - read packets
 /* parse-packet.c  - read packets
- * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ *               2005 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
  *
  * This file is part of GnuPG.
  *
@@ -15,7 +16,8 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
  */
 
 #include <config.h>
  */
 
 #include <config.h>
 #include "main.h"
 #include "i18n.h"
 
 #include "main.h"
 #include "i18n.h"
 
-static int mpi_print_mode = 0;
-static int list_mode = 0;
+static int mpi_print_mode;
+static int list_mode;
+static FILE *listfp;
 
 static int  parse( IOBUF inp, PACKET *pkt, int onlykeypkts,
                   off_t *retpos, int *skip, IOBUF out, int do_skip
 
 static int  parse( IOBUF inp, PACKET *pkt, int onlykeypkts,
                   off_t *retpos, int *skip, IOBUF out, int do_skip
-           #ifdef DEBUG_PARSE_PACKET
+#ifdef DEBUG_PARSE_PACKET
                   ,const char *dbg_w, const char *dbg_f, int dbg_l
                   ,const char *dbg_w, const char *dbg_f, int dbg_l
-           #endif
+#endif
                 );
 static int  copy_packet( IOBUF inp, IOBUF out, int pkttype,
                 );
 static int  copy_packet( IOBUF inp, IOBUF out, int pkttype,
-                                              unsigned long pktlen );
-static void skip_packet( IOBUF inp, int pkttype, unsigned long pktlen );
-static void skip_rest( IOBUF inp, unsigned long pktlen );
-static void *read_rest( IOBUF inp, size_t pktlen );
+                        unsigned long pktlen, int partial );
+static void skip_packet( IOBUF inp, int pkttype,
+                        unsigned long pktlen, int partial );
+static void *read_rest( IOBUF inp, size_t pktlen, int partial );
 static int  parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen,
                                                             PACKET *packet );
 static int  parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen,
                                                             PACKET *packet );
 static int  parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen,
                                                             PACKET *packet );
 static int  parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen,
                                                             PACKET *packet );
-static int  parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
-                                                        PKT_signature *sig );
 static int  parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
                                                        PKT_onepass_sig *ops );
 static int  parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
 static int  parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
                                                        PKT_onepass_sig *ops );
 static int  parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
@@ -69,15 +70,15 @@ static int  parse_comment( IOBUF inp, int pkttype, unsigned long pktlen,
 static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen,
                                                           PACKET *packet );
 static int  parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
 static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen,
                                                           PACKET *packet );
 static int  parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
-                                              PACKET *packet, int new_ctb);
+                            PACKET *packet, int new_ctb, int partial);
 static int  parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
                                               PACKET *packet, int new_ctb );
 static int  parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
 static int  parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
                                               PACKET *packet, int new_ctb );
 static int  parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
-                                              PACKET *packet, int new_ctb);
+                            PACKET *packet, int new_ctb, int partial);
 static int  parse_mdc( IOBUF inp, int pkttype, unsigned long pktlen,
                                               PACKET *packet, int new_ctb);
 static int  parse_gpg_control( IOBUF inp, int pkttype, unsigned long pktlen,
 static int  parse_mdc( IOBUF inp, int pkttype, unsigned long pktlen,
                                               PACKET *packet, int new_ctb);
 static int  parse_gpg_control( IOBUF inp, int pkttype, unsigned long pktlen,
-                               PACKET *packet );
+                               PACKET *packet, int partial );
 
 static unsigned short
 read_16(IOBUF inp)
 
 static unsigned short
 read_16(IOBUF inp)
@@ -106,6 +107,23 @@ set_packet_list_mode( int mode )
     int old = list_mode;
     list_mode = mode;
     mpi_print_mode = DBG_MPI;
     int old = list_mode;
     list_mode = mode;
     mpi_print_mode = DBG_MPI;
+    /* We use stdout print only if invoked by the --list-packets
+       command but switch to stderr in all otehr cases.  This breaks
+       the previous behaviour but that seems to be more of a bug than
+       intentional.  I don't believe that any application makes use of
+       this long standing annoying way of printing to stdout except
+       when doing a --list-packets. If this assumption fails, it will
+       be easy to add an option for the listing stream.  Note that we
+       initialize it only once; mainly because some code may switch
+       the option value later back to 1 and we want to have all output
+       to the same stream.  
+
+       Using stderr is not actually very clean because it bypasses the
+       logging code but it is a special thing anyay.  I am not sure
+       whether using log_stream() would be better.  Perhaps we should
+       enable the list mdoe only with a special option. */
+    if (!listfp)
+        listfp = opt.list_packets == 2 ? stdout : stderr;
     return old;
 }
 
     return old;
 }
 
@@ -296,7 +314,7 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
     unsigned long pktlen;
     byte hdr[8];
     int hdrlen;
     unsigned long pktlen;
     byte hdr[8];
     int hdrlen;
-    int new_ctb = 0;
+    int new_ctb = 0, partial=0;
     int with_uid = (onlykeypkts == 2);
 
     *skip = 0;
     int with_uid = (onlykeypkts == 2);
 
     *skip = 0;
@@ -327,55 +345,88 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
         if (pkttype == PKT_COMPRESSED) {
              iobuf_set_partial_block_mode(inp, c & 0xff);
              pktlen = 0;/* to indicate partial length */
         if (pkttype == PKT_COMPRESSED) {
              iobuf_set_partial_block_mode(inp, c & 0xff);
              pktlen = 0;/* to indicate partial length */
+            partial=1;
         }
         else {
              hdr[hdrlen++] = c;
              if( c < 192 )
         }
         else {
              hdr[hdrlen++] = c;
              if( c < 192 )
-                  pktlen = c;
-             else if( c < 224 ) {
-                  pktlen = (c - 192) * 256;
-                  if( (c = iobuf_get(inp)) == -1 ) {
-                       log_error("%s: 2nd length byte missing\n",
-                                 iobuf_where(inp) );
-                       rc = G10ERR_INVALID_PACKET;
-                       goto leave;
-                  }
-                  hdr[hdrlen++] = c;
-                  pktlen += c + 192;
-             }
-             else if( c == 255 ) {
-                  pktlen  = (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 ) {
-                       log_error("%s: 4 byte length invalid\n",
-                                 iobuf_where(inp) );
-                       rc = G10ERR_INVALID_PACKET;
-                       goto leave;
-                  }
-                  pktlen |= (hdr[hdrlen++] = c );
-             }
-             else { /* partial body length */
-                  iobuf_set_partial_block_mode(inp, c & 0xff);
-                  pktlen = 0;/* to indicate partial length */
-             }
+              pktlen = c;
+             else if( c < 224 )
+              {
+                pktlen = (c - 192) * 256;
+                if( (c = iobuf_get(inp)) == -1 )
+                  {
+                    log_error("%s: 2nd length byte missing\n",
+                              iobuf_where(inp) );
+                    rc = G10ERR_INVALID_PACKET;
+                    goto leave;
+                  }
+                hdr[hdrlen++] = c;
+                pktlen += c + 192;
+              }
+             else if( c == 255 )
+              {
+                pktlen  = (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 )
+                  {
+                    log_error("%s: 4 byte length invalid\n",
+                              iobuf_where(inp) );
+                    rc = G10ERR_INVALID_PACKET;
+                    goto leave;
+                  }
+                pktlen |= (hdr[hdrlen++] = c );
+              }
+             else
+              {
+                /* Partial body length.  Note that we handled
+                   PKT_COMPRESSED earlier. */
+                if(pkttype==PKT_PLAINTEXT || pkttype==PKT_ENCRYPTED
+                   || pkttype==PKT_ENCRYPTED_MDC)
+                  {
+                    iobuf_set_partial_block_mode(inp, c & 0xff);
+                    pktlen = 0;/* to indicate partial length */
+                    partial=1;
+                  }
+                else
+                  {
+                    log_error("%s: partial length for invalid"
+                              " packet type %d\n",iobuf_where(inp),pkttype);
+                    rc=G10ERR_INVALID_PACKET;
+                    goto leave;
+                  }
+              }
        }
     }
        }
     }
-    else {
+    else
+      {
        pkttype = (ctb>>2)&0xf;
        lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3));
        pkttype = (ctb>>2)&0xf;
        lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3));
-       if( !lenbytes ) {
+       if( !lenbytes )
+         {
            pktlen = 0; /* don't know the value */
            pktlen = 0; /* don't know the value */
-           if( pkttype != PKT_COMPRESSED )
-               iobuf_set_block_mode(inp, 1);
-       }
-       else {
-           for( ; lenbytes; lenbytes-- ) {
+           /* This isn't really partial, but we can treat it the same
+              in a "read until the end" sort of way. */
+           partial=1;
+           if(pkttype!=PKT_ENCRYPTED && pkttype!=PKT_PLAINTEXT
+              && pkttype!=PKT_COMPRESSED)
+             {
+               log_error ("%s: indeterminate length for invalid"
+                          " packet type %d\n", iobuf_where(inp), pkttype );
+               rc = G10ERR_INVALID_PACKET;
+               goto leave;
+             }
+         }
+       else
+         {
+           for( ; lenbytes; lenbytes-- )
+             {
                pktlen <<= 8;
                pktlen |= hdr[hdrlen++] = iobuf_get_noeof(inp);
                pktlen <<= 8;
                pktlen |= hdr[hdrlen++] = iobuf_get_noeof(inp);
-           }
-       }
-    }
+             }
+         }
+      }
 
     if (pktlen == 0xffffffff) {
         /* with a some probability this is caused by a problem in the
 
     if (pktlen == 0xffffffff) {
         /* with a some probability this is caused by a problem in the
@@ -389,7 +440,7 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
        if( iobuf_write( out, hdr, hdrlen ) == -1 )
            rc = G10ERR_WRITE_FILE;
        else
        if( iobuf_write( out, hdr, hdrlen ) == -1 )
            rc = G10ERR_WRITE_FILE;
        else
-           rc = copy_packet(inp, out, pkttype, pktlen );
+           rc = copy_packet(inp, out, pkttype, pktlen, partial );
        goto leave;
     }
 
        goto leave;
     }
 
@@ -401,7 +452,7 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
                         && pkttype != PKT_PUBLIC_KEY
                         && pkttype != PKT_SECRET_SUBKEY
                         && pkttype != PKT_SECRET_KEY  ) ) {
                         && pkttype != PKT_PUBLIC_KEY
                         && pkttype != PKT_SECRET_SUBKEY
                         && pkttype != PKT_SECRET_KEY  ) ) {
-       skip_rest(inp, pktlen);
+       iobuf_skip_rest(inp, pktlen, partial);
        *skip = 1;
        rc = 0;
        goto leave;
        *skip = 1;
        rc = 0;
        goto leave;
@@ -422,12 +473,12 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
     switch( pkttype ) {
       case PKT_PUBLIC_KEY:
       case PKT_PUBLIC_SUBKEY:
     switch( pkttype ) {
       case PKT_PUBLIC_KEY:
       case PKT_PUBLIC_SUBKEY:
-       pkt->pkt.public_key = m_alloc_clear(sizeof *pkt->pkt.public_key );
+       pkt->pkt.public_key = xmalloc_clear(sizeof *pkt->pkt.public_key );
        rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt );
        break;
       case PKT_SECRET_KEY:
       case PKT_SECRET_SUBKEY:
        rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt );
        break;
       case PKT_SECRET_KEY:
       case PKT_SECRET_SUBKEY:
-       pkt->pkt.secret_key = m_alloc_clear(sizeof *pkt->pkt.secret_key );
+       pkt->pkt.secret_key = xmalloc_clear(sizeof *pkt->pkt.secret_key );
        rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt );
        break;
       case PKT_SYMKEY_ENC:
        rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt );
        break;
       case PKT_SYMKEY_ENC:
@@ -437,11 +488,11 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
        rc = parse_pubkeyenc(inp, pkttype, pktlen, pkt );
        break;
       case PKT_SIGNATURE:
        rc = parse_pubkeyenc(inp, pkttype, pktlen, pkt );
        break;
       case PKT_SIGNATURE:
-       pkt->pkt.signature = m_alloc_clear(sizeof *pkt->pkt.signature );
+       pkt->pkt.signature = xmalloc_clear(sizeof *pkt->pkt.signature );
        rc = parse_signature(inp, pkttype, pktlen, pkt->pkt.signature );
        break;
       case PKT_ONEPASS_SIG:
        rc = parse_signature(inp, pkttype, pktlen, pkt->pkt.signature );
        break;
       case PKT_ONEPASS_SIG:
-       pkt->pkt.onepass_sig = m_alloc_clear(sizeof *pkt->pkt.onepass_sig );
+       pkt->pkt.onepass_sig = xmalloc_clear(sizeof *pkt->pkt.onepass_sig );
        rc = parse_onepass_sig(inp, pkttype, pktlen, pkt->pkt.onepass_sig );
        break;
       case PKT_USER_ID:
        rc = parse_onepass_sig(inp, pkttype, pktlen, pkt->pkt.onepass_sig );
        break;
       case PKT_USER_ID:
@@ -460,23 +511,23 @@ parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
        rc = 0;
        break;
       case PKT_PLAINTEXT:
        rc = 0;
        break;
       case PKT_PLAINTEXT:
-       rc = parse_plaintext(inp, pkttype, pktlen, pkt, new_ctb );
+       rc = parse_plaintext(inp, pkttype, pktlen, pkt, new_ctb, partial );
        break;
       case PKT_COMPRESSED:
        rc = parse_compressed(inp, pkttype, pktlen, pkt, new_ctb );
        break;
       case PKT_ENCRYPTED:
       case PKT_ENCRYPTED_MDC:
        break;
       case PKT_COMPRESSED:
        rc = parse_compressed(inp, pkttype, pktlen, pkt, new_ctb );
        break;
       case PKT_ENCRYPTED:
       case PKT_ENCRYPTED_MDC:
-       rc = parse_encrypted(inp, pkttype, pktlen, pkt, new_ctb );
+       rc = parse_encrypted(inp, pkttype, pktlen, pkt, new_ctb, partial );
        break;
       case PKT_MDC:
        rc = parse_mdc(inp, pkttype, pktlen, pkt, new_ctb );
        break;
       case PKT_GPG_CONTROL:
        break;
       case PKT_MDC:
        rc = parse_mdc(inp, pkttype, pktlen, pkt, new_ctb );
        break;
       case PKT_GPG_CONTROL:
-        rc = parse_gpg_control(inp, pkttype, pktlen, pkt );
+        rc = parse_gpg_control(inp, pkttype, pktlen, pkt, partial );
         break;
       default:
         break;
       default:
-       skip_packet(inp, pkttype, pktlen);
+       skip_packet(inp, pkttype, pktlen, partial);
        break;
     }
 
        break;
     }
 
@@ -491,25 +542,26 @@ dump_hex_line( int c, int *i )
 {
     if( *i && !(*i%8) ) {
        if( *i && !(*i%24) )
 {
     if( *i && !(*i%8) ) {
        if( *i && !(*i%24) )
-           printf("\n%4d:", *i );
+           fprintf (listfp, "\n%4d:", *i );
        else
        else
-           putchar(' ');
+           putc (' ', listfp);
     }
     if( c == -1 )
     }
     if( c == -1 )
-       printf(" EOF" );
+       fprintf (listfp, " EOF" );
     else
     else
-       printf(" %02x", c );
+       fprintf (listfp, " %02x", c );
     ++*i;
 }
 
 
 static int
     ++*i;
 }
 
 
 static int
-copy_packet( IOBUF inp, IOBUF out, int pkttype, unsigned long pktlen )
+copy_packet( IOBUF inp, IOBUF out, int pkttype,
+            unsigned long pktlen, int partial )
 {
     int n;
     char buf[100];
 
 {
     int n;
     char buf[100];
 
-    if( iobuf_in_block_mode(inp) ) {
+    if( partial ) {
        while( (n = iobuf_read( inp, buf, 100 )) != -1 )
            if( iobuf_write(out, buf, n ) )
                return G10ERR_WRITE_FILE; /* write error */
        while( (n = iobuf_read( inp, buf, 100 )) != -1 )
            if( iobuf_write(out, buf, n ) )
                return G10ERR_WRITE_FILE; /* write error */
@@ -536,18 +588,19 @@ copy_packet( IOBUF inp, IOBUF out, int pkttype, unsigned long pktlen )
 
 
 static void
 
 
 static void
-skip_packet( IOBUF inp, int pkttype, unsigned long pktlen )
+skip_packet( IOBUF inp, int pkttype, unsigned long pktlen, int partial )
 {
     if( list_mode ) {
        if( pkttype == PKT_MARKER )
 {
     if( list_mode ) {
        if( pkttype == PKT_MARKER )
-           fputs(":marker packet:\n", stdout );
+           fputs(":marker packet:\n", listfp );
        else
        else
-           printf(":unknown packet: type %2d, length %lu\n", pkttype, pktlen);
+           fprintf (listfp, ":unknown packet: type %2d, length %lu\n",
+                     pkttype, pktlen);
        if( pkttype ) {
            int c, i=0 ;
            if( pkttype != PKT_MARKER )
        if( pkttype ) {
            int c, i=0 ;
            if( pkttype != PKT_MARKER )
-               fputs("dump:", stdout );
-           if( iobuf_in_block_mode(inp) ) {
+               fputs("dump:", listfp );
+           if( partial ) {
                while( (c=iobuf_get(inp)) != -1 )
                    dump_hex_line(c, &i);
            }
                while( (c=iobuf_get(inp)) != -1 )
                    dump_hex_line(c, &i);
            }
@@ -555,40 +608,26 @@ skip_packet( IOBUF inp, int pkttype, unsigned long pktlen )
                for( ; pktlen; pktlen-- )
                    dump_hex_line(iobuf_get(inp), &i);
            }
                for( ; pktlen; pktlen-- )
                    dump_hex_line(iobuf_get(inp), &i);
            }
-           putchar('\n');
+           putc ('\n', listfp);
            return;
        }
     }
            return;
        }
     }
-    skip_rest(inp,pktlen);
-}
-
-static void
-skip_rest( IOBUF inp, unsigned long pktlen )
-{
-    if( iobuf_in_block_mode(inp) ) {
-       while( iobuf_get(inp) != -1 )
-               ;
-    }
-    else {
-       for( ; pktlen; pktlen-- )
-           if( iobuf_get(inp) == -1 )
-               break;
-    }
+    iobuf_skip_rest(inp,pktlen,partial);
 }
 
 
 static void *
 }
 
 
 static void *
-read_rest( IOBUF inp, size_t pktlen )
+read_rest( IOBUF inp, size_t pktlen, int partial )
 {
     byte *p;
     int i;
 
 {
     byte *p;
     int i;
 
-    if( iobuf_in_block_mode(inp) ) {
+    if( partial ) {
        log_error("read_rest: can't store stream data\n");
        p = NULL;
     }
     else {
        log_error("read_rest: can't store stream data\n");
        p = NULL;
     }
     else {
-       p = m_alloc( pktlen );
+       p = xmalloc( pktlen );
        for(i=0; pktlen; pktlen--, i++ )
            p[i] = iobuf_get(inp);
     }
        for(i=0; pktlen; pktlen--, i++ )
            p[i] = iobuf_get(inp);
     }
@@ -643,7 +682,7 @@ parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
        goto leave;
     }
     seskeylen = pktlen - minlen;
        goto leave;
     }
     seskeylen = pktlen - minlen;
-    k = packet->pkt.symkey_enc = m_alloc_clear( sizeof *packet->pkt.symkey_enc
+    k = packet->pkt.symkey_enc = xmalloc_clear( sizeof *packet->pkt.symkey_enc
                                                + seskeylen - 1 );
     k->version = version;
     k->cipher_algo = cipher_algo;
                                                + seskeylen - 1 );
     k->version = version;
     k->cipher_algo = cipher_algo;
@@ -657,25 +696,38 @@ parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
        k->s2k.count = iobuf_get(inp); pktlen--;
     }
     k->seskeylen = seskeylen;
        k->s2k.count = iobuf_get(inp); pktlen--;
     }
     k->seskeylen = seskeylen;
-    for(i=0; i < seskeylen && pktlen; i++, pktlen-- )
-       k->seskey[i] = iobuf_get_noeof(inp);
+    if(k->seskeylen)
+      {
+       for(i=0; i < seskeylen && pktlen; i++, pktlen-- )
+         k->seskey[i] = iobuf_get_noeof(inp);
+
+       /* What we're watching out for here is a session key decryptor
+          with no salt.  The RFC says that using salt for this is a
+          MUST. */
+       if(s2kmode!=1 && s2kmode!=3)
+         log_info(_("WARNING: potentially insecure symmetrically"
+                    " encrypted session key\n"));
+      }
     assert( !pktlen );
 
     if( list_mode ) {
     assert( !pktlen );
 
     if( list_mode ) {
-       printf(":symkey enc packet: version %d, cipher %d, s2k %d, hash %d\n",
-                           version, cipher_algo, s2kmode, hash_algo);
+       fprintf (listfp, ":symkey enc packet: version %d, cipher %d, s2k %d, hash %d",
+              version, cipher_algo, s2kmode, hash_algo);
+       if(seskeylen)
+         fprintf (listfp, ", seskey %d bits",(seskeylen-1)*8);
+       fprintf (listfp, "\n");
        if( s2kmode == 1 || s2kmode == 3 ) {
        if( s2kmode == 1 || s2kmode == 3 ) {
-           printf("\tsalt ");
+           fprintf (listfp, "\tsalt ");
            for(i=0; i < 8; i++ )
            for(i=0; i < 8; i++ )
-               printf("%02x", k->s2k.salt[i]);
+               fprintf (listfp, "%02x", k->s2k.salt[i]);
            if( s2kmode == 3 )
            if( s2kmode == 3 )
-               printf(", count %lu\n", (ulong)k->s2k.count );
-           printf("\n");
+               fprintf (listfp, ", count %lu", (ulong)k->s2k.count );
+           fprintf (listfp, "\n");
        }
     }
 
   leave:
        }
     }
 
   leave:
-    skip_rest(inp, pktlen);
+    iobuf_skip_rest(inp, pktlen, 0);
     return rc;
 }
 
     return rc;
 }
 
@@ -687,7 +739,7 @@ parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
     int i, ndata;
     PKT_pubkey_enc *k;
 
     int i, ndata;
     PKT_pubkey_enc *k;
 
-    k = packet->pkt.pubkey_enc = m_alloc_clear(sizeof *packet->pkt.pubkey_enc);
+    k = packet->pkt.pubkey_enc = xmalloc_clear(sizeof *packet->pkt.pubkey_enc);
     if( pktlen < 12 ) {
        log_error("packet(%d) too short\n", pkttype);
         rc = G10ERR_INVALID_PACKET;
     if( pktlen < 12 ) {
        log_error("packet(%d) too short\n", pkttype);
         rc = G10ERR_INVALID_PACKET;
@@ -704,13 +756,13 @@ parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
     k->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
     k->throw_keyid = 0; /* only used as flag for build_packet */
     if( list_mode )
     k->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
     k->throw_keyid = 0; /* only used as flag for build_packet */
     if( list_mode )
-       printf(":pubkey enc packet: version %d, algo %d, keyid %08lX%08lX\n",
+       fprintf (listfp, ":pubkey enc packet: version %d, algo %d, keyid %08lX%08lX\n",
          k->version, k->pubkey_algo, (ulong)k->keyid[0], (ulong)k->keyid[1]);
 
     ndata = pubkey_get_nenc(k->pubkey_algo);
     if( !ndata ) {
        if( list_mode )
          k->version, k->pubkey_algo, (ulong)k->keyid[0], (ulong)k->keyid[1]);
 
     ndata = pubkey_get_nenc(k->pubkey_algo);
     if( !ndata ) {
        if( list_mode )
-           printf("\tunsupported algorithm %d\n", k->pubkey_algo );
+           fprintf (listfp, "\tunsupported algorithm %d\n", k->pubkey_algo );
        unknown_pubkey_warning( k->pubkey_algo );
        k->data[0] = NULL;  /* no need to store the encrypted data */
     }
        unknown_pubkey_warning( k->pubkey_algo );
        k->data[0] = NULL;  /* no need to store the encrypted data */
     }
@@ -719,9 +771,9 @@ parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
            n = pktlen;
            k->data[i] = mpi_read(inp, &n, 0); pktlen -=n;
            if( list_mode ) {
            n = pktlen;
            k->data[i] = mpi_read(inp, &n, 0); pktlen -=n;
            if( list_mode ) {
-               printf("\tdata: ");
-               mpi_print(stdout, k->data[i], mpi_print_mode );
-               putchar('\n');
+               fprintf (listfp, "\tdata: ");
+               mpi_print(listfp, k->data[i], mpi_print_mode );
+               putc ('\n', listfp);
            }
             if (!k->data[i])
                 rc = G10ERR_INVALID_PACKET;
            }
             if (!k->data[i])
                 rc = G10ERR_INVALID_PACKET;
@@ -729,7 +781,7 @@ parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
     }
 
   leave:
     }
 
   leave:
-    skip_rest(inp, pktlen);
+    iobuf_skip_rest(inp, pktlen, 0);
     return rc;
 }
 
     return rc;
 }
 
@@ -745,86 +797,85 @@ dump_sig_subpkt( int hashed, int type, int critical,
      * detect the ARRs - we print our old message here when it is a faked
      * ARR and add an additional notice */
     if ( type == SIGSUBPKT_ARR && !hashed ) {
      * detect the ARRs - we print our old message here when it is a faked
      * ARR and add an additional notice */
     if ( type == SIGSUBPKT_ARR && !hashed ) {
-        printf("\tsubpkt %d len %u (additional recipient request)\n"
-               "WARNING: PGP versions > 5.0 and < 6.5.8 will automagically "
-               "encrypt to this key and thereby reveal the plaintext to "
-               "the owner of this ARR key. Detailed info follows:\n",
-               type, (unsigned)length );
+        fprintf (listfp,
+                 "\tsubpkt %d len %u (additional recipient request)\n"
+                 "WARNING: PGP versions > 5.0 and < 6.5.8 will automagically "
+                 "encrypt to this key and thereby reveal the plaintext to "
+                 "the owner of this ARR key. Detailed info follows:\n",
+                 type, (unsigned)length );
     }
     
     }
     
+    buffer++;
+    length--;
    
    
-    printf("\t%s%ssubpkt %d len %u (", /*)*/
+    fprintf (listfp, "\t%s%ssubpkt %d len %u (", /*)*/
              critical ? "critical ":"",
              hashed ? "hashed ":"", type, (unsigned)length );
              critical ? "critical ":"",
              hashed ? "hashed ":"", type, (unsigned)length );
-    buffer++;
-    length--;
     if( length > buflen ) {
     if( length > buflen ) {
-       printf("too short: buffer is only %u)\n", (unsigned)buflen );
+       fprintf (listfp, "too short: buffer is only %u)\n", (unsigned)buflen );
        return;
     }
     switch( type ) {
       case SIGSUBPKT_SIG_CREATED:
        if( length >= 4 )
        return;
     }
     switch( type ) {
       case SIGSUBPKT_SIG_CREATED:
        if( length >= 4 )
-           printf("sig created %s", strtimestamp( buffer_to_u32(buffer) ) );
+           fprintf (listfp, "sig created %s", strtimestamp( buffer_to_u32(buffer) ) );
        break;
       case SIGSUBPKT_SIG_EXPIRE:
        if( length >= 4 )
        break;
       case SIGSUBPKT_SIG_EXPIRE:
        if( length >= 4 )
-           printf("sig expires after %s",
+           fprintf (listfp, "sig expires after %s",
                                     strtimevalue( buffer_to_u32(buffer) ) );
        break;
       case SIGSUBPKT_EXPORTABLE:
        if( length )
                                     strtimevalue( buffer_to_u32(buffer) ) );
        break;
       case SIGSUBPKT_EXPORTABLE:
        if( length )
-           printf("%sexportable", *buffer? "":"not ");
+           fprintf (listfp, "%sexportable", *buffer? "":"not ");
        break;
       case SIGSUBPKT_TRUST:
        if(length!=2)
        break;
       case SIGSUBPKT_TRUST:
        if(length!=2)
-         p="[invalid trust signature]";
+         p="[invalid trust subpacket]";
        else
        else
-         printf("trust signature of level %d, amount %d",buffer[0],buffer[1]);
+         fprintf (listfp, "trust signature of depth %d, value %d",buffer[0],buffer[1]);
        break;
       case SIGSUBPKT_REGEXP:
        if(!length)
        break;
       case SIGSUBPKT_REGEXP:
        if(!length)
-         p="[invalid regexp]";
+         p="[invalid regexp subpacket]";
        else
        else
-         printf("regular expression: \"%s\"",buffer);
+         fprintf (listfp, "regular expression: \"%s\"",buffer);
        break;
       case SIGSUBPKT_REVOCABLE:
        if( length )
        break;
       case SIGSUBPKT_REVOCABLE:
        if( length )
-           printf("%srevocable", *buffer? "":"not ");
+           fprintf (listfp, "%srevocable", *buffer? "":"not ");
        break;
       case SIGSUBPKT_KEY_EXPIRE:
        if( length >= 4 )
        break;
       case SIGSUBPKT_KEY_EXPIRE:
        if( length >= 4 )
-           printf("key expires after %s",
+           fprintf (listfp, "key expires after %s",
                                    strtimevalue( buffer_to_u32(buffer) ) );
        break;
       case SIGSUBPKT_PREF_SYM:
                                    strtimevalue( buffer_to_u32(buffer) ) );
        break;
       case SIGSUBPKT_PREF_SYM:
-       fputs("pref-sym-algos:", stdout );
+       fputs("pref-sym-algos:", listfp );
        for( i=0; i < length; i++ )
        for( i=0; i < length; i++ )
-           printf(" %d", buffer[i] );
+           fprintf (listfp, " %d", buffer[i] );
        break;
       case SIGSUBPKT_REV_KEY:
        break;
       case SIGSUBPKT_REV_KEY:
-       fputs("revocation key: ", stdout );
+       fputs("revocation key: ", listfp );
        if( length < 22 )
            p = "[too short]";
        else {
        if( length < 22 )
            p = "[too short]";
        else {
-           printf("c=%02x a=%d f=", buffer[0], buffer[1] );
+           fprintf (listfp, "c=%02x a=%d f=", buffer[0], buffer[1] );
            for( i=2; i < length; i++ )
            for( i=2; i < length; i++ )
-               printf("%02X", buffer[i] );
+               fprintf (listfp, "%02X", buffer[i] );
        }
        break;
       case SIGSUBPKT_ISSUER:
        if( length >= 8 )
        }
        break;
       case SIGSUBPKT_ISSUER:
        if( length >= 8 )
-           printf("issuer key ID %08lX%08lX",
+           fprintf (listfp, "issuer key ID %08lX%08lX",
                      (ulong)buffer_to_u32(buffer),
                      (ulong)buffer_to_u32(buffer+4) );
        break;
       case SIGSUBPKT_NOTATION:
        {
                      (ulong)buffer_to_u32(buffer),
                      (ulong)buffer_to_u32(buffer+4) );
        break;
       case SIGSUBPKT_NOTATION:
        {
-           fputs("notation: ", stdout );
+           fputs("notation: ", listfp );
            if( length < 8 )
                p = "[too short]";
            if( length < 8 )
                p = "[too short]";
-           else if( !(*buffer & 0x80) )
-               p = "[not human readable]";
            else {
                const byte *s = buffer;
                size_t n1, n2;
            else {
                const byte *s = buffer;
                size_t n1, n2;
@@ -835,172 +886,201 @@ dump_sig_subpkt( int hashed, int type, int critical,
                if( 8+n1+n2 != length )
                    p = "[error]";
                else {
                if( 8+n1+n2 != length )
                    p = "[error]";
                else {
-                   print_string( stdout, s, n1, ')' );
-                   putc( '=', stdout );
-                   print_string( stdout, s+n1, n2, ')' );
+                   print_string( listfp, s, n1, ')' );
+                   putc( '=', listfp );
+
+                   if( *buffer & 0x80 )
+                     print_string( listfp, s+n1, n2, ')' );
+                   else
+                     p = "[not human readable]";
                }
            }
        }
        break;
       case SIGSUBPKT_PREF_HASH:
                }
            }
        }
        break;
       case SIGSUBPKT_PREF_HASH:
-       fputs("pref-hash-algos:", stdout );
+       fputs("pref-hash-algos:", listfp );
        for( i=0; i < length; i++ )
        for( i=0; i < length; i++ )
-           printf(" %d", buffer[i] );
+           fprintf (listfp, " %d", buffer[i] );
        break;
       case SIGSUBPKT_PREF_COMPR:
        break;
       case SIGSUBPKT_PREF_COMPR:
-       fputs("pref-zip-algos:", stdout );
+       fputs("pref-zip-algos:", listfp );
        for( i=0; i < length; i++ )
        for( i=0; i < length; i++ )
-           printf(" %d", buffer[i] );
+           fprintf (listfp, " %d", buffer[i] );
        break;
       case SIGSUBPKT_KS_FLAGS:
        break;
       case SIGSUBPKT_KS_FLAGS:
-       fputs("key server preferences:",stdout);
+       fputs("key server preferences:",listfp);
        for(i=0;i<length;i++)
        for(i=0;i<length;i++)
-         printf(" %02X", buffer[i]);
+         fprintf (listfp, " %02X", buffer[i]);
        break;
       case SIGSUBPKT_PREF_KS:
        break;
       case SIGSUBPKT_PREF_KS:
-       p = "preferred key server";
+       fputs("preferred key server: ", listfp );
+       print_string( listfp, buffer, length, ')' );
        break;
       case SIGSUBPKT_PRIMARY_UID:
        p = "primary user ID";
        break;
       case SIGSUBPKT_POLICY:
        break;
       case SIGSUBPKT_PRIMARY_UID:
        p = "primary user ID";
        break;
       case SIGSUBPKT_POLICY:
-       fputs("policy: ", stdout );
-       print_string( stdout, buffer, length, ')' );
+       fputs("policy: ", listfp );
+       print_string( listfp, buffer, length, ')' );
        break;
       case SIGSUBPKT_KEY_FLAGS:
        break;
       case SIGSUBPKT_KEY_FLAGS:
-        fputs ( "key flags:", stdout );
+        fputs ( "key flags:", listfp );
         for( i=0; i < length; i++ )
         for( i=0; i < length; i++ )
-            printf(" %02X", buffer[i] );
+            fprintf (listfp, " %02X", buffer[i] );
        break;
       case SIGSUBPKT_SIGNERS_UID:
        p = "signer's user ID";
        break;
       case SIGSUBPKT_REVOC_REASON:
         if( length ) {
        break;
       case SIGSUBPKT_SIGNERS_UID:
        p = "signer's user ID";
        break;
       case SIGSUBPKT_REVOC_REASON:
         if( length ) {
-           printf("revocation reason 0x%02x (", *buffer );
-           print_string( stdout, buffer+1, length-1, ')' );
+           fprintf (listfp, "revocation reason 0x%02x (", *buffer );
+           print_string( listfp, buffer+1, length-1, ')' );
            p = ")";
        }
        break;
       case SIGSUBPKT_ARR:
            p = ")";
        }
        break;
       case SIGSUBPKT_ARR:
-        fputs("Big Brother's key (ignored): ", stdout );
+        fputs("Big Brother's key (ignored): ", listfp );
        if( length < 22 )
            p = "[too short]";
        else {
        if( length < 22 )
            p = "[too short]";
        else {
-           printf("c=%02x a=%d f=", buffer[0], buffer[1] );
+           fprintf (listfp, "c=%02x a=%d f=", buffer[0], buffer[1] );
            for( i=2; i < length; i++ )
            for( i=2; i < length; i++ )
-               printf("%02X", buffer[i] );
+               fprintf (listfp, "%02X", buffer[i] );
        }
         break;
       case SIGSUBPKT_FEATURES:
        }
         break;
       case SIGSUBPKT_FEATURES:
-        fputs ( "features:", stdout );
+        fputs ( "features:", listfp );
         for( i=0; i < length; i++ )
         for( i=0; i < length; i++ )
-            printf(" %02x", buffer[i] );
+            fprintf (listfp, " %02x", buffer[i] );
+       break;
+      case SIGSUBPKT_SIGNATURE:
+       fputs("signature: ",listfp);
+       if(length<17)
+         p="[too short]";
+       else
+         fprintf (listfp, "v%d, class 0x%02X, algo %d, digest algo %d",
+                buffer[0],
+                buffer[0]==3?buffer[2]:buffer[1],
+                buffer[0]==3?buffer[15]:buffer[2],
+                buffer[0]==3?buffer[16]:buffer[3]);
        break;
        break;
-      case SIGSUBPKT_PRIV_VERIFY_CACHE:
-       p = "obsolete verification cache";
+      default:
+       if(type>=100 && type<=110)
+         p="experimental / private subpacket";
+       else
+         p = "?";
        break;
        break;
-      default: p = "?"; break;
     }
 
     }
 
-    printf("%s)\n", p? p: "");
+    fprintf (listfp, "%s)\n", p? p: "");
 }
 
 /****************
 }
 
 /****************
- * Returns: >= 0 offset into buffer
- *         -1 unknown type
- *         -2 unsupported type
- *         -3 subpacket too short
+ * Returns: >= 0 use this offset into buffer
+ *         -1 explicitly reject returning this type
+ *         -2 subpacket too short
  */
 int
 parse_one_sig_subpkt( const byte *buffer, size_t n, int type )
 {
  */
 int
 parse_one_sig_subpkt( const byte *buffer, size_t n, int type )
 {
-    switch( type ) {
-      case SIGSUBPKT_REV_KEY:
-       if(n < 22)
-         break;
-       return 0;
-      case SIGSUBPKT_SIG_CREATED:
-      case SIGSUBPKT_SIG_EXPIRE:
-      case SIGSUBPKT_KEY_EXPIRE:
-       if( n < 4 )
-           break;
-       return 0;
-      case SIGSUBPKT_KEY_FLAGS:
-      case SIGSUBPKT_KS_FLAGS:
-      case SIGSUBPKT_PREF_SYM:
-      case SIGSUBPKT_PREF_HASH:
-      case SIGSUBPKT_PREF_COMPR:
-      case SIGSUBPKT_POLICY:
-      case SIGSUBPKT_FEATURES:
-       return 0;
-      case SIGSUBPKT_EXPORTABLE:
-      case SIGSUBPKT_REVOCABLE:
-       if( !n )
-           break;
-       return 0;
-      case SIGSUBPKT_ISSUER: /* issuer key ID */
-       if( n < 8 )
-           break;
-       return 0;
-      case SIGSUBPKT_NOTATION:
-       if( n < 8 ) /* minimum length needed */
-           break;
-       return 0;
-      case SIGSUBPKT_REVOC_REASON:
-       if( !n  )
-           break;
-       return 0;
-      case SIGSUBPKT_PRIMARY_UID:
-          if ( n != 1 )
-              break;
-          return 0;   
-      case SIGSUBPKT_PRIV_VERIFY_CACHE:
-        /* We used this in gpg 1.0.5 and 1.0.6 to cache signature
-         * verification results - it is no longer used.
-         * "GPG" 0x00 <mode> <stat>
-         * where mode == 1: valid data, stat == 0: invalid signature
-         * stat == 1: valid signature 
-        * (because we use private data, we check our marker) */
-       if( n < 6 )
-           break;
-       if( buffer[0] != 'G' || buffer[1] != 'P'
-            || buffer[2] != 'G' || buffer[3] )
-           return -2;
-       return 4;
-      default: return -1;
-    }
-    return -3;
+  switch( type )
+    {
+    case SIGSUBPKT_REV_KEY:
+      if(n < 22)
+       break;
+      return 0;
+    case SIGSUBPKT_SIG_CREATED:
+    case SIGSUBPKT_SIG_EXPIRE:
+    case SIGSUBPKT_KEY_EXPIRE:
+      if( n < 4 )
+       break;
+      return 0;
+    case SIGSUBPKT_KEY_FLAGS:
+    case SIGSUBPKT_KS_FLAGS:
+    case SIGSUBPKT_PREF_SYM:
+    case SIGSUBPKT_PREF_HASH:
+    case SIGSUBPKT_PREF_COMPR:
+    case SIGSUBPKT_POLICY:
+    case SIGSUBPKT_PREF_KS:
+    case SIGSUBPKT_FEATURES:
+    case SIGSUBPKT_REGEXP:
+      return 0;
+    case SIGSUBPKT_SIGNATURE:
+    case SIGSUBPKT_EXPORTABLE:
+    case SIGSUBPKT_REVOCABLE:
+    case SIGSUBPKT_REVOC_REASON:
+      if( !n )
+       break;
+      return 0;
+    case SIGSUBPKT_ISSUER: /* issuer key ID */
+      if( n < 8 )
+       break;
+      return 0;
+    case SIGSUBPKT_NOTATION:
+      /* minimum length needed, and the subpacket must be well-formed
+        where the name length and value length all fit inside the
+        packet. */
+      if(n<8 || 8+((buffer[4]<<8)|buffer[5])+((buffer[6]<<8)|buffer[7]) != n)
+       break;
+      return 0;
+    case SIGSUBPKT_PRIMARY_UID:
+      if ( n != 1 )
+       break;
+      return 0;
+    case SIGSUBPKT_TRUST:
+      if ( n != 2 )
+       break;
+      return 0;
+    default: return 0;
+    }
+  return -2;
 }
 
 }
 
-
+/* Not many critical notations we understand yet... */
 static int
 static int
-can_handle_critical( const byte *buffer, size_t n, int type )
+can_handle_critical_notation(const byte *name,size_t len)
 {
 {
-    switch( type ) {
-      case SIGSUBPKT_NOTATION:
-       if( n >= 8 && (*buffer & 0x80) )
-           return 1; /* human readable is handled */
-       return 0;
+  if(len==32 && memcmp(name,"preferred-email-encoding@pgp.com",32)==0)
+    return 1;
+  if(len==21 && memcmp(name,"pka-address@gnupg.org",21)==0)
+    return 1;
 
 
-      case SIGSUBPKT_SIG_CREATED:
-      case SIGSUBPKT_SIG_EXPIRE:
-      case SIGSUBPKT_KEY_EXPIRE:
-      case SIGSUBPKT_EXPORTABLE:
-      case SIGSUBPKT_REVOCABLE:
-      case SIGSUBPKT_REV_KEY:
-      case SIGSUBPKT_ISSUER:/* issuer key ID */
-      case SIGSUBPKT_PREF_SYM:
-      case SIGSUBPKT_PREF_HASH:
-      case SIGSUBPKT_PREF_COMPR:
-      case SIGSUBPKT_KEY_FLAGS:
-      case SIGSUBPKT_PRIMARY_UID:
-      case SIGSUBPKT_FEATURES:
-      case SIGSUBPKT_POLICY: /* Is it enough to show the policy? */
-       return 1;
+  return 0;
+}
 
 
-      default:
+static int
+can_handle_critical( const byte *buffer, size_t n, int type )
+{
+  switch( type )
+    {
+    case SIGSUBPKT_NOTATION:
+      if(n>=8)
+       return can_handle_critical_notation(buffer+8,(buffer[4]<<8)|buffer[5]);
+      else
        return 0;
        return 0;
+    case SIGSUBPKT_SIGNATURE:
+    case SIGSUBPKT_SIG_CREATED:
+    case SIGSUBPKT_SIG_EXPIRE:
+    case SIGSUBPKT_KEY_EXPIRE:
+    case SIGSUBPKT_EXPORTABLE:
+    case SIGSUBPKT_REVOCABLE:
+    case SIGSUBPKT_REV_KEY:
+    case SIGSUBPKT_ISSUER:/* issuer key ID */
+    case SIGSUBPKT_PREF_SYM:
+    case SIGSUBPKT_PREF_HASH:
+    case SIGSUBPKT_PREF_COMPR:
+    case SIGSUBPKT_KEY_FLAGS:
+    case SIGSUBPKT_PRIMARY_UID:
+    case SIGSUBPKT_FEATURES:
+    case SIGSUBPKT_TRUST:
+    case SIGSUBPKT_REGEXP:
+      /* Is it enough to show the policy or keyserver? */
+    case SIGSUBPKT_POLICY:
+    case SIGSUBPKT_PREF_KS:
+      return 1;
+
+    default:
+      return 0;
     }
 }
 
     }
 }
 
@@ -1061,13 +1141,15 @@ enum_sig_subpkt( const subpktarea_t *pktbuf, sigsubpkttype_t reqtype,
            if( *critical ) {
                if( n-1 > buflen+1 )
                    goto too_short;
            if( *critical ) {
                if( n-1 > buflen+1 )
                    goto too_short;
-               if( !can_handle_critical(buffer+1, n-1, type ) ) {
-                   log_info(_("subpacket of type %d has critical bit set\n"),
-                                                                       type);
+               if( !can_handle_critical(buffer+1, n-1, type ) )
+                 {
+                   if(opt.verbose)
+                     log_info(_("subpacket of type %d has "
+                                "critical bit set\n"),type);
                    if( start )
                    if( start )
-                       *start = seq;
+                     *start = seq;
                    return NULL; /* this is an error */
                    return NULL; /* this is an error */
-               }
+                 }
            }
        }
        else if( reqtype < 0 ) /* list packets */
            }
        }
        else if( reqtype < 0 ) /* list packets */
@@ -1082,13 +1164,11 @@ enum_sig_subpkt( const subpktarea_t *pktbuf, sigsubpkttype_t reqtype,
                *ret_n = n;
            offset = parse_one_sig_subpkt(buffer, n, type );
            switch( offset ) {
                *ret_n = n;
            offset = parse_one_sig_subpkt(buffer, n, type );
            switch( offset ) {
-             case -3:
-               log_error("subpacket of type %d too short\n", type);
-               return NULL;
              case -2:
              case -2:
+               log_error("subpacket of type %d too short\n", type);
                return NULL;
              case -1:
                return NULL;
              case -1:
-               BUG(); /* not yet needed */
+               return NULL;
              default:
                break;
            }
              default:
                break;
            }
@@ -1106,7 +1186,8 @@ enum_sig_subpkt( const subpktarea_t *pktbuf, sigsubpkttype_t reqtype,
     return NULL; /* end of packets; not found */
 
   too_short:
     return NULL; /* end of packets; not found */
 
   too_short:
-    log_error("buffer shorter than subpacket\n");
+    if(opt.verbose)
+      log_info("buffer shorter than subpacket\n");
     if( start )
        *start = -1;
     return NULL;
     if( start )
        *start = -1;
     return NULL;
@@ -1150,7 +1231,7 @@ void parse_revkeys(PKT_signature *sig)
       if(len==sizeof(struct revocation_key) &&
         (revkey->class&0x80)) /* 0x80 bit must be set */
        {
       if(len==sizeof(struct revocation_key) &&
         (revkey->class&0x80)) /* 0x80 bit must be set */
        {
-         sig->revkey=m_realloc(sig->revkey,
+         sig->revkey=xrealloc(sig->revkey,
                          sizeof(struct revocation_key *)*(sig->numrevkeys+1));
          sig->revkey[sig->numrevkeys]=revkey;
          sig->numrevkeys++;
                          sizeof(struct revocation_key *)*(sig->numrevkeys+1));
          sig->revkey[sig->numrevkeys]=revkey;
          sig->numrevkeys++;
@@ -1158,7 +1239,7 @@ void parse_revkeys(PKT_signature *sig)
     }
 }
 
     }
 }
 
-static int
+int
 parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
                                          PKT_signature *sig )
 {
 parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
                                          PKT_signature *sig )
 {
@@ -1202,7 +1283,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
            goto leave;
        }
        if( n ) {
            goto leave;
        }
        if( n ) {
-           sig->hashed = m_alloc (sizeof (*sig->hashed) + n - 1 );
+           sig->hashed = xmalloc (sizeof (*sig->hashed) + n - 1 );
             sig->hashed->size = n;
            sig->hashed->len = n;
            if( iobuf_read (inp, sig->hashed->data, n ) != n ) {
             sig->hashed->size = n;
            sig->hashed->len = n;
            if( iobuf_read (inp, sig->hashed->data, n ) != n ) {
@@ -1220,11 +1301,8 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
            goto leave;
        }
        if( n ) {
            goto leave;
        }
        if( n ) {
-            /* we add 8 extra bytes so that we have space for the signature
-             * status cache.  Well we are wasting this if there is a cache
-             * packet already, but in the other case it avoids an realloc */
-           sig->unhashed = m_alloc (sizeof(*sig->unhashed) + n + 8 - 1 );
-            sig->unhashed->size = n + 8;
+           sig->unhashed = xmalloc (sizeof(*sig->unhashed) + n - 1 );
+            sig->unhashed->size = n;
            sig->unhashed->len = n;
            if( iobuf_read(inp, sig->unhashed->data, n ) != n ) {
                log_error("premature eof while reading "
            sig->unhashed->len = n;
            if( iobuf_read(inp, sig->unhashed->data, n ) != n ) {
                log_error("premature eof while reading "
@@ -1245,41 +1323,49 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
     sig->digest_start[0] = iobuf_get_noeof(inp); pktlen--;
     sig->digest_start[1] = iobuf_get_noeof(inp); pktlen--;
 
     sig->digest_start[0] = iobuf_get_noeof(inp); pktlen--;
     sig->digest_start[1] = iobuf_get_noeof(inp); pktlen--;
 
-    if( is_v4 && sig->pubkey_algo ) { /*extract required information */
+    if( is_v4 && sig->pubkey_algo )
+      { /*extract required information */
        const byte *p;
        const byte *p;
+       size_t len;
 
        /* set sig->flags.unknown_critical if there is a
         * critical bit set for packets which we do not understand */
        if( !parse_sig_subpkt (sig->hashed, SIGSUBPKT_TEST_CRITICAL, NULL)
 
        /* set sig->flags.unknown_critical if there is a
         * critical bit set for packets which we do not understand */
        if( !parse_sig_subpkt (sig->hashed, SIGSUBPKT_TEST_CRITICAL, NULL)
-          || !parse_sig_subpkt (sig->unhashed, SIGSUBPKT_TEST_CRITICAL,
-                                                                       NULL) )
-       {
-           sig->flags.unknown_critical = 1;
-       }
+           || !parse_sig_subpkt (sig->unhashed, SIGSUBPKT_TEST_CRITICAL,
+                                 NULL) )
+         sig->flags.unknown_critical = 1;
 
        p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIG_CREATED, NULL );
 
        p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIG_CREATED, NULL );
-       if( !p )
-           log_error("signature packet without timestamp\n");
-       else
-           sig->timestamp = buffer_to_u32(p);
+       if(p)
+         sig->timestamp = buffer_to_u32(p);
+       else if(!(sig->pubkey_algo>=100 && sig->pubkey_algo<=110)
+               && opt.verbose)
+         log_info ("signature packet without timestamp\n");
+
        p = parse_sig_subpkt2( sig, SIGSUBPKT_ISSUER, NULL );
        p = parse_sig_subpkt2( sig, SIGSUBPKT_ISSUER, NULL );
-       if( !p )
-           log_error("signature packet without keyid\n");
-       else {
+       if(p)
+         {
            sig->keyid[0] = buffer_to_u32(p);
            sig->keyid[1] = buffer_to_u32(p+4);
            sig->keyid[0] = buffer_to_u32(p);
            sig->keyid[1] = buffer_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)
          sig->expiredate=sig->timestamp+buffer_to_u32(p);
        if(sig->expiredate && sig->expiredate<=make_timestamp())
 
        p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_SIG_EXPIRE,NULL);
        if(p)
          sig->expiredate=sig->timestamp+buffer_to_u32(p);
        if(sig->expiredate && sig->expiredate<=make_timestamp())
-           sig->flags.expired=1;
+         sig->flags.expired=1;
 
        p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_POLICY,NULL);
        if(p)
          sig->flags.policy_url=1;
 
 
        p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_POLICY,NULL);
        if(p)
          sig->flags.policy_url=1;
 
+       p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_PREF_KS,NULL);
+       if(p)
+         sig->flags.pref_ks=1;
+
        p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_NOTATION,NULL);
        if(p)
          sig->flags.notation=1;
        p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_NOTATION,NULL);
        if(p)
          sig->flags.notation=1;
@@ -1288,6 +1374,23 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
        if(p && *p==0)
          sig->flags.revocable=0;
 
        if(p && *p==0)
          sig->flags.revocable=0;
 
+       p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_TRUST,&len);
+       if(p && len==2)
+         {
+           sig->trust_depth=p[0];
+           sig->trust_value=p[1];
+
+           /* Only look for a regexp if there is also a trust
+              subpacket. */
+           sig->trust_regexp=
+             parse_sig_subpkt(sig->hashed,SIGSUBPKT_REGEXP,&len);
+
+           /* If the regular expression is of 0 length, there is no
+              regular expression. */
+           if(len==0)
+             sig->trust_regexp=NULL;
+         }
+
        /* We accept the exportable subpacket from either the hashed
           or unhashed areas as older versions of gpg put it in the
           unhashed area.  In theory, anyway, we should never see this
        /* We accept the exportable subpacket from either the hashed
           or unhashed areas as older versions of gpg put it in the
           unhashed area.  In theory, anyway, we should never see this
@@ -1300,10 +1403,10 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
        /* Find all revocation keys. */
        if(sig->sig_class==0x1F)
          parse_revkeys(sig);
        /* Find all revocation keys. */
        if(sig->sig_class==0x1F)
          parse_revkeys(sig);
-    }
+      }
 
     if( list_mode ) {
 
     if( list_mode ) {
-       printf(":signature packet: algo %d, keyid %08lX%08lX\n"
+       fprintf (listfp, ":signature packet: algo %d, keyid %08lX%08lX\n"
               "\tversion %d, created %lu, md5len %d, sigclass %02x\n"
               "\tdigest algo %d, begin of digest %02x %02x\n",
                sig->pubkey_algo,
               "\tversion %d, created %lu, md5len %d, sigclass %02x\n"
               "\tdigest algo %d, begin of digest %02x %02x\n",
                sig->pubkey_algo,
@@ -1320,11 +1423,11 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
     ndata = pubkey_get_nsig(sig->pubkey_algo);
     if( !ndata ) {
        if( list_mode )
     ndata = pubkey_get_nsig(sig->pubkey_algo);
     if( !ndata ) {
        if( list_mode )
-           printf("\tunknown algorithm %d\n", sig->pubkey_algo );
+           fprintf (listfp, "\tunknown algorithm %d\n", sig->pubkey_algo );
        unknown_pubkey_warning( sig->pubkey_algo );
        /* we store the plain material in data[0], so that we are able
         * to write it back with build_packet() */
        unknown_pubkey_warning( sig->pubkey_algo );
        /* we store the plain material in data[0], so that we are able
         * to write it back with build_packet() */
-       sig->data[0] = mpi_set_opaque(NULL, read_rest(inp, pktlen), pktlen );
+       sig->data[0]= mpi_set_opaque(NULL, read_rest(inp, pktlen, 0), pktlen );
        pktlen = 0;
     }
     else {
        pktlen = 0;
     }
     else {
@@ -1333,9 +1436,9 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
            sig->data[i] = mpi_read(inp, &n, 0 );
            pktlen -=n;
            if( list_mode ) {
            sig->data[i] = mpi_read(inp, &n, 0 );
            pktlen -=n;
            if( list_mode ) {
-               printf("\tdata: ");
-               mpi_print(stdout, sig->data[i], mpi_print_mode );
-               putchar('\n');
+               fprintf (listfp, "\tdata: ");
+               mpi_print(listfp, sig->data[i], mpi_print_mode );
+               putc ('\n', listfp);
            }
             if (!sig->data[i])
                 rc = G10ERR_INVALID_PACKET;
            }
             if (!sig->data[i])
                 rc = G10ERR_INVALID_PACKET;
@@ -1343,7 +1446,7 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
     }
 
   leave:
     }
 
   leave:
-    skip_rest(inp, pktlen);
+    iobuf_skip_rest(inp, pktlen, 0);
     return rc;
 }
 
     return rc;
 }
 
@@ -1373,7 +1476,7 @@ parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
     ops->keyid[1] = read_32(inp); pktlen -= 4;
     ops->last = iobuf_get_noeof(inp); pktlen--;
     if( list_mode )
     ops->keyid[1] = read_32(inp); pktlen -= 4;
     ops->last = iobuf_get_noeof(inp); pktlen--;
     if( list_mode )
-       printf(":onepass_sig packet: keyid %08lX%08lX\n"
+       fprintf (listfp, ":onepass_sig packet: keyid %08lX%08lX\n"
               "\tversion %d, sigclass %02x, digest %d, pubkey %d, last=%d\n",
                (ulong)ops->keyid[0], (ulong)ops->keyid[1],
                version, ops->sig_class,
               "\tversion %d, sigclass %02x, digest %d, pubkey %d, last=%d\n",
                (ulong)ops->keyid[0], (ulong)ops->keyid[1],
                version, ops->sig_class,
@@ -1381,7 +1484,7 @@ parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
 
 
   leave:
 
 
   leave:
-    skip_rest(inp, pktlen);
+    iobuf_skip_rest(inp, pktlen, 0);
     return rc;
 }
 
     return rc;
 }
 
@@ -1415,7 +1518,7 @@ read_protected_v3_mpi (IOBUF inp, unsigned long *length)
       return NULL;
     }
   nbytes = (nbits+7) / 8;
       return NULL;
     }
   nbytes = (nbits+7) / 8;
-  buf = p = m_alloc (2 + nbytes);
+  buf = p = xmalloc (2 + nbytes);
   *p++ = nbits >> 8;
   *p++ = nbits;
   for (; nbytes && length; nbytes--, --*length)
   *p++ = nbits >> 8;
   *p++ = nbits;
   for (; nbytes && length; nbytes--, --*length)
@@ -1423,7 +1526,7 @@ read_protected_v3_mpi (IOBUF inp, unsigned long *length)
   if (nbytes)
     {
       log_error ("packet shorter tham mpi\n");
   if (nbytes)
     {
       log_error ("packet shorter tham mpi\n");
-      m_free (buf);
+      xfree (buf);
       return NULL;
     }
 
       return NULL;
     }
 
@@ -1449,18 +1552,18 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
        /* early versions of G10 use old PGP comments packets;
         * luckily all those comments are started by a hash */
        if( list_mode ) {
        /* early versions of G10 use old PGP comments packets;
         * luckily all those comments are started by a hash */
        if( list_mode ) {
-           printf(":rfc1991 comment packet: \"" );
+           fprintf (listfp, ":rfc1991 comment packet: \"" );
            for( ; pktlen; pktlen-- ) {
                int c;
                c = iobuf_get_noeof(inp);
                if( c >= ' ' && c <= 'z' )
            for( ; pktlen; pktlen-- ) {
                int c;
                c = iobuf_get_noeof(inp);
                if( c >= ' ' && c <= 'z' )
-                   putchar(c);
+                   putc (c, listfp);
                else
                else
-                   printf("\\x%02x", c );
+                   fprintf (listfp, "\\x%02x", c );
            }
            }
-           printf("\"\n");
+           fprintf (listfp, "\"\n");
        }
        }
-       skip_rest(inp, pktlen);
+       iobuf_skip_rest(inp, pktlen, 0);
        return 0;
     }
     else if( version == 4 )
        return 0;
     }
     else if( version == 4 )
@@ -1494,7 +1597,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
     }
     algorithm = iobuf_get_noeof(inp); pktlen--;
     if( list_mode )
     }
     algorithm = iobuf_get_noeof(inp); pktlen--;
     if( list_mode )
-       printf(":%s key packet:\n"
+       fprintf (listfp, ":%s key packet:\n"
               "\tversion %d, algo %d, created %lu, expires %lu\n",
                pkttype == PKT_PUBLIC_KEY? "public" :
                pkttype == PKT_SECRET_KEY? "secret" :
               "\tversion %d, algo %d, created %lu, expires %lu\n",
                pkttype == PKT_PUBLIC_KEY? "public" :
                pkttype == PKT_SECRET_KEY? "secret" :
@@ -1523,10 +1626,12 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
        pk->max_expiredate = max_expiredate;
        pk->hdrbytes    = hdrlen;
        pk->version     = version;
        pk->max_expiredate = max_expiredate;
        pk->hdrbytes    = hdrlen;
        pk->version     = version;
+       pk->is_primary = pkttype == PKT_PUBLIC_KEY;
        pk->pubkey_algo = algorithm;
        pk->req_usage = 0; 
        pk->pubkey_usage = 0; /* not yet used */
         pk->is_revoked = 0;
        pk->pubkey_algo = algorithm;
        pk->req_usage = 0; 
        pk->pubkey_usage = 0; /* not yet used */
         pk->is_revoked = 0;
+       pk->is_disabled = 0;
        pk->keyid[0] = 0;
        pk->keyid[1] = 0;
     }
        pk->keyid[0] = 0;
        pk->keyid[1] = 0;
     }
@@ -1534,7 +1639,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
     npkey = pubkey_get_npkey( algorithm );
     if( !npkey ) {
        if( list_mode )
     npkey = pubkey_get_npkey( algorithm );
     if( !npkey ) {
        if( list_mode )
-           printf("\tunknown algorithm %d\n", algorithm );
+           fprintf (listfp, "\tunknown algorithm %d\n", algorithm );
        unknown_pubkey_warning( algorithm );
     }
 
        unknown_pubkey_warning( algorithm );
     }
 
@@ -1542,10 +1647,11 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
     if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) {
        PKT_secret_key *sk = pkt->pkt.secret_key;
        byte temp[16];
     if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) {
        PKT_secret_key *sk = pkt->pkt.secret_key;
        byte temp[16];
+        size_t snlen = 0;
 
        if( !npkey ) {
            sk->skey[0] = mpi_set_opaque( NULL,
 
        if( !npkey ) {
            sk->skey[0] = mpi_set_opaque( NULL,
-                                         read_rest(inp, pktlen), pktlen );
+                                         read_rest(inp, pktlen, 0), pktlen );
            pktlen = 0;
            goto leave;
        }
            pktlen = 0;
            goto leave;
        }
@@ -1553,9 +1659,9 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
        for(i=0; i < npkey; i++ ) {
            n = pktlen; sk->skey[i] = mpi_read(inp, &n, 0 ); pktlen -=n;
            if( list_mode ) {
        for(i=0; i < npkey; i++ ) {
            n = pktlen; sk->skey[i] = mpi_read(inp, &n, 0 ); pktlen -=n;
            if( list_mode ) {
-               printf(  "\tskey[%d]: ", i);
-               mpi_print(stdout, sk->skey[i], mpi_print_mode  );
-               putchar('\n');
+               fprintf (listfp,   "\tskey[%d]: ", i);
+               mpi_print(listfp, sk->skey[i], mpi_print_mode  );
+               putc ('\n', listfp);
            }
             if (!sk->skey[i])
                 rc = G10ERR_INVALID_PACKET;
            }
             if (!sk->skey[i])
                 rc = G10ERR_INVALID_PACKET;
@@ -1585,7 +1691,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
                        temp[i] = iobuf_get_noeof(inp);
                    if( i < 4 || memcmp( temp, "GNU", 3 ) ) {
                        if( list_mode )
                        temp[i] = iobuf_get_noeof(inp);
                    if( i < 4 || memcmp( temp, "GNU", 3 ) ) {
                        if( list_mode )
-                           printf(  "\tunknown S2K %d\n",
+                           fprintf (listfp,   "\tunknown S2K %d\n",
                                                sk->protect.s2k.mode );
                        rc = G10ERR_INVALID_PACKET;
                        goto leave;
                                                sk->protect.s2k.mode );
                        rc = G10ERR_INVALID_PACKET;
                        goto leave;
@@ -1606,17 +1712,21 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
                    break;
                }
                switch( sk->protect.s2k.mode ) {
                    break;
                }
                switch( sk->protect.s2k.mode ) {
-                 case 0: if( list_mode ) printf(  "\tsimple S2K" );
+                 case 0: if( list_mode ) fprintf (listfp, "\tsimple S2K" );
                    break;
                    break;
-                 case 1: if( list_mode ) printf(  "\tsalted S2K" );
+                 case 1: if( list_mode ) fprintf (listfp, "\tsalted S2K" );
                    break;
                    break;
-                 case 3: if( list_mode ) printf(  "\titer+salt S2K" );
+                 case 3: if( list_mode ) fprintf (listfp, "\titer+salt S2K" );
                    break;
                    break;
-                 case 1001: if( list_mode ) printf(  "\tgnu-dummy S2K" );
+                 case 1001: if( list_mode ) fprintf (listfp,
+                                                      "\tgnu-dummy S2K" );
+                   break;
+                 case 1002: if (list_mode) fprintf (listfp,
+                                                  "\tgnu-divert-to-card S2K");
                    break;
                  default:
                    if( list_mode )
                    break;
                  default:
                    if( list_mode )
-                       printf(  "\tunknown %sS2K %d\n",
+                       fprintf (listfp,   "\tunknown %sS2K %d\n",
                                 sk->protect.s2k.mode < 1000? "":"GNU ",
                                                   sk->protect.s2k.mode );
                    rc = G10ERR_INVALID_PACKET;
                                 sk->protect.s2k.mode < 1000? "":"GNU ",
                                                   sk->protect.s2k.mode );
                    rc = G10ERR_INVALID_PACKET;
@@ -1624,18 +1734,18 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
                }
 
                if( list_mode ) {
                }
 
                if( list_mode ) {
-                   printf(", algo: %d,%s hash: %d",
+                   fprintf (listfp, ", algo: %d,%s hash: %d",
                                     sk->protect.algo,
                                      sk->protect.sha1chk?" SHA1 protection,"
                                                         :" simple checksum,",
                                     sk->protect.s2k.hash_algo );
                    if( sk->protect.s2k.mode == 1
                        || sk->protect.s2k.mode == 3 ) {
                                     sk->protect.algo,
                                      sk->protect.sha1chk?" SHA1 protection,"
                                                         :" simple checksum,",
                                     sk->protect.s2k.hash_algo );
                    if( sk->protect.s2k.mode == 1
                        || sk->protect.s2k.mode == 3 ) {
-                       printf(", salt: ");
+                       fprintf (listfp, ", salt: ");
                        for(i=0; i < 8; i++ )
                        for(i=0; i < 8; i++ )
-                           printf("%02x", sk->protect.s2k.salt[i]);
+                           fprintf (listfp, "%02x", sk->protect.s2k.salt[i]);
                    }
                    }
-                   putchar('\n');
+                   putc ('\n', listfp);
                }
 
                if( sk->protect.s2k.mode == 3 ) {
                }
 
                if( sk->protect.s2k.mode == 3 ) {
@@ -1646,9 +1756,22 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
                    sk->protect.s2k.count = iobuf_get(inp);
                    pktlen--;
                    if( list_mode )
                    sk->protect.s2k.count = iobuf_get(inp);
                    pktlen--;
                    if( list_mode )
-                       printf("\tprotect count: %lu\n",
+                       fprintf (listfp, "\tprotect count: %lu\n",
                                            (ulong)sk->protect.s2k.count);
                }
                                            (ulong)sk->protect.s2k.count);
                }
+               else if( sk->protect.s2k.mode == 1002 ) {
+                    /* Read the serial number. */
+                    if (pktlen < 1) {
+                      rc = G10ERR_INVALID_PACKET;
+                       goto leave;
+                   }
+                   snlen = iobuf_get (inp);
+                   pktlen--;
+                    if (pktlen < snlen || snlen == -1) {
+                       rc = G10ERR_INVALID_PACKET;
+                       goto leave;
+                    }
+               }
            }
            /* Note that a sk->protect.algo > 110 is illegal, but I'm
               not erroring on it here as otherwise there would be no
            }
            /* Note that a sk->protect.algo > 110 is illegal, but I'm
               not erroring on it here as otherwise there would be no
@@ -1657,7 +1780,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
                sk->protect.s2k.mode = 0;
                sk->protect.s2k.hash_algo = DIGEST_ALGO_MD5;
                if( list_mode )
                sk->protect.s2k.mode = 0;
                sk->protect.s2k.hash_algo = DIGEST_ALGO_MD5;
                if( list_mode )
-                   printf(  "\tprotect algo: %d  (hash algo: %d)\n",
+                   fprintf (listfp,   "\tprotect algo: %d  (hash algo: %d)\n",
                         sk->protect.algo, sk->protect.s2k.hash_algo );
            }
            /* It is really ugly that we don't know the size
                         sk->protect.algo, sk->protect.s2k.hash_algo );
            }
            /* It is really ugly that we don't know the size
@@ -1678,6 +1801,8 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
            }
            if( sk->protect.s2k.mode == 1001 )
                sk->protect.ivlen = 0;
            }
            if( sk->protect.s2k.mode == 1001 )
                sk->protect.ivlen = 0;
+           else if( sk->protect.s2k.mode == 1002 )
+               sk->protect.ivlen = snlen < 16? snlen : 16;
 
            if( pktlen < sk->protect.ivlen ) {
                rc = G10ERR_INVALID_PACKET;
 
            if( pktlen < sk->protect.ivlen ) {
                rc = G10ERR_INVALID_PACKET;
@@ -1686,10 +1811,12 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
            for(i=0; i < sk->protect.ivlen && pktlen; i++, pktlen-- )
                temp[i] = iobuf_get_noeof(inp);
            if( list_mode ) {
            for(i=0; i < sk->protect.ivlen && pktlen; i++, pktlen-- )
                temp[i] = iobuf_get_noeof(inp);
            if( list_mode ) {
-               printf(  "\tprotect IV: ");
+               fprintf (listfp,
+                         sk->protect.s2k.mode == 1002? "\tserial-number: "
+                                                     : "\tprotect IV: ");
                for(i=0; i < sk->protect.ivlen; i++ )
                for(i=0; i < sk->protect.ivlen; i++ )
-                   printf(" %02x", temp[i] );
-               putchar('\n');
+                   fprintf (listfp, " %02x", temp[i] );
+               putc ('\n', listfp);
            }
            memcpy(sk->protect.iv, temp, sk->protect.ivlen );
        }
            }
            memcpy(sk->protect.iv, temp, sk->protect.ivlen );
        }
@@ -1699,9 +1826,10 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
         * If the user is so careless, not to protect his secret key,
         * we can assume, that he operates an open system :=(.
         * So we put the key into secure memory when we unprotect it. */
         * If the user is so careless, not to protect his secret key,
         * we can assume, that he operates an open system :=(.
         * So we put the key into secure memory when we unprotect it. */
-       if( sk->protect.s2k.mode == 1001 ) {
+       if( sk->protect.s2k.mode == 1001 
+            || sk->protect.s2k.mode == 1002 ) {
            /* better set some dummy stuff here */
            /* better set some dummy stuff here */
-           sk->skey[npkey] = mpi_set_opaque(NULL, m_strdup("dummydata"), 10);
+           sk->skey[npkey] = mpi_set_opaque(NULL, xstrdup("dummydata"), 10);
            pktlen = 0;
        }
        else if( is_v4 && sk->is_protected ) {
            pktlen = 0;
        }
        else if( is_v4 && sk->is_protected ) {
@@ -1709,10 +1837,10 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
             * stuff up to the end of the packet into the first
             * skey element */
            sk->skey[npkey] = mpi_set_opaque(NULL,
             * stuff up to the end of the packet into the first
             * skey element */
            sk->skey[npkey] = mpi_set_opaque(NULL,
-                                            read_rest(inp, pktlen), pktlen );
+                                            read_rest(inp, pktlen, 0),pktlen);
            pktlen = 0;
            if( list_mode ) {
            pktlen = 0;
            if( list_mode ) {
-               printf("\tencrypted stuff follows\n");
+               fprintf (listfp, "\tencrypted stuff follows\n");
            }
        }
        else { /* v3 method: the mpi length is not encrypted */
            }
        }
        else { /* v3 method: the mpi length is not encrypted */
@@ -1720,16 +1848,16 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
                 if ( sk->is_protected ) {
                     sk->skey[i] = read_protected_v3_mpi (inp, &pktlen);
                     if( list_mode ) 
                 if ( sk->is_protected ) {
                     sk->skey[i] = read_protected_v3_mpi (inp, &pktlen);
                     if( list_mode ) 
-                        printf(  "\tskey[%d]: [encrypted]\n", i);
+                        fprintf (listfp,   "\tskey[%d]: [encrypted]\n", i);
                 }
                 else {
                     n = pktlen;
                     sk->skey[i] = mpi_read(inp, &n, 0 );
                     pktlen -=n;
                     if( list_mode ) {
                 }
                 else {
                     n = pktlen;
                     sk->skey[i] = mpi_read(inp, &n, 0 );
                     pktlen -=n;
                     if( list_mode ) {
-                        printf(  "\tskey[%d]: ", i);
-                        mpi_print(stdout, sk->skey[i], mpi_print_mode  );
-                        putchar('\n');
+                        fprintf (listfp,   "\tskey[%d]: ", i);
+                        mpi_print(listfp, sk->skey[i], mpi_print_mode  );
+                        putc ('\n', listfp);
                     }
                 }
 
                     }
                 }
 
@@ -1741,7 +1869,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
 
            sk->csum = read_16(inp); pktlen -= 2;
            if( list_mode ) {
 
            sk->csum = read_16(inp); pktlen -= 2;
            if( list_mode ) {
-               printf("\tchecksum: %04hx\n", sk->csum);
+               fprintf (listfp, "\tchecksum: %04hx\n", sk->csum);
            }
        }
     }
            }
        }
     }
@@ -1750,7 +1878,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
 
        if( !npkey ) {
            pk->pkey[0] = mpi_set_opaque( NULL,
 
        if( !npkey ) {
            pk->pkey[0] = mpi_set_opaque( NULL,
-                                         read_rest(inp, pktlen), pktlen );
+                                         read_rest(inp, pktlen, 0), pktlen );
            pktlen = 0;
            goto leave;
        }
            pktlen = 0;
            goto leave;
        }
@@ -1758,9 +1886,9 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
        for(i=0; i < npkey; i++ ) {
            n = pktlen; pk->pkey[i] = mpi_read(inp, &n, 0 ); pktlen -=n;
            if( list_mode ) {
        for(i=0; i < npkey; i++ ) {
            n = pktlen; pk->pkey[i] = mpi_read(inp, &n, 0 ); pktlen -=n;
            if( list_mode ) {
-               printf(  "\tpkey[%d]: ", i);
-               mpi_print(stdout, pk->pkey[i], mpi_print_mode  );
-               putchar('\n');
+               fprintf (listfp,   "\tpkey[%d]: ", i);
+               mpi_print(listfp, pk->pkey[i], mpi_print_mode  );
+               putc ('\n', listfp);
            }
             if (!pk->pkey[i])
                 rc = G10ERR_INVALID_PACKET;
            }
             if (!pk->pkey[i])
                 rc = G10ERR_INVALID_PACKET;
@@ -1770,7 +1898,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
     }
 
   leave:
     }
 
   leave:
-    skip_rest(inp, pktlen);
+    iobuf_skip_rest(inp, pktlen, 0);
     return rc;
 }
 
     return rc;
 }
 
@@ -1787,7 +1915,7 @@ parse_attribute_subpkts(PKT_user_id *uid)
   int buflen=uid->attrib_len;
   byte type;
 
   int buflen=uid->attrib_len;
   byte type;
 
-  m_free(uid->attribs);
+  xfree(uid->attribs);
 
   while(buflen)
     {
 
   while(buflen)
     {
@@ -1810,7 +1938,7 @@ parse_attribute_subpkts(PKT_user_id *uid)
       if( buflen < n )
        goto too_short;
 
       if( buflen < n )
        goto too_short;
 
-      attribs=m_realloc(attribs,(count+1)*sizeof(struct user_attribute));
+      attribs=xrealloc(attribs,(count+1)*sizeof(struct user_attribute));
       memset(&attribs[count],0,sizeof(struct user_attribute));
 
       type=*buffer;
       memset(&attribs[count],0,sizeof(struct user_attribute));
 
       type=*buffer;
@@ -1831,37 +1959,22 @@ parse_attribute_subpkts(PKT_user_id *uid)
   return count;
 
  too_short:
   return count;
 
  too_short:
-  log_error("buffer shorter than attribute subpacket\n");
+  if(opt.verbose)
+    log_info("buffer shorter than attribute subpacket\n");
   uid->attribs=attribs;
   uid->numattribs=count;
   return count;
 }
 
   uid->attribs=attribs;
   uid->numattribs=count;
   return count;
 }
 
-static void setup_user_id(PACKET *packet)
-{
-  packet->pkt.user_id->ref = 1;
-  packet->pkt.user_id->attribs = NULL;
-  packet->pkt.user_id->attrib_data = NULL;
-  packet->pkt.user_id->attrib_len = 0;
-  packet->pkt.user_id->is_primary = 0;
-  packet->pkt.user_id->is_revoked = 0;
-  packet->pkt.user_id->is_expired = 0;
-  packet->pkt.user_id->expiredate = 0;
-  packet->pkt.user_id->created = 0;
-  packet->pkt.user_id->help_key_usage = 0;
-  packet->pkt.user_id->help_key_expire = 0;
-  packet->pkt.user_id->prefs = NULL;
-}
 
 static int
 parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
 {
     byte *p;
 
 
 static int
 parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
 {
     byte *p;
 
-    packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id  + pktlen);
+    packet->pkt.user_id = xmalloc_clear(sizeof *packet->pkt.user_id + pktlen);
     packet->pkt.user_id->len = pktlen;
     packet->pkt.user_id->len = pktlen;
-
-    setup_user_id(packet);
+    packet->pkt.user_id->ref=1;
 
     p = packet->pkt.user_id->name;
     for( ; pktlen; pktlen--, p++ )
 
     p = packet->pkt.user_id->name;
     for( ; pktlen; pktlen--, p++ )
@@ -1870,15 +1983,15 @@ parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
 
     if( list_mode ) {
        int n = packet->pkt.user_id->len;
 
     if( list_mode ) {
        int n = packet->pkt.user_id->len;
-       printf(":user ID packet: \"");
+       fprintf (listfp, ":user ID packet: \"");
        /* fixme: Hey why don't we replace this with print_string?? */
        for(p=packet->pkt.user_id->name; n; p++, n-- ) {
            if( *p >= ' ' && *p <= 'z' )
        /* fixme: Hey why don't we replace this with print_string?? */
        for(p=packet->pkt.user_id->name; n; p++, n-- ) {
            if( *p >= ' ' && *p <= 'z' )
-               putchar(*p);
+               putc (*p, listfp);
            else
            else
-               printf("\\x%02x", *p );
+               fprintf (listfp, "\\x%02x", *p );
        }
        }
-       printf("\"\n");
+       fprintf (listfp, "\"\n");
     }
     return 0;
 }
     }
     return 0;
 }
@@ -1922,13 +2035,12 @@ parse_attribute( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
     byte *p;
 
 #define EXTRA_UID_NAME_SPACE 71
     byte *p;
 
 #define EXTRA_UID_NAME_SPACE 71
-    packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id
-                                  + EXTRA_UID_NAME_SPACE);
-
-    setup_user_id(packet);
-
-    packet->pkt.user_id->attrib_data = m_alloc(pktlen);
+    packet->pkt.user_id = xmalloc_clear(sizeof *packet->pkt.user_id
+                                       + EXTRA_UID_NAME_SPACE);
+    packet->pkt.user_id->ref=1;
+    packet->pkt.user_id->attrib_data = xmalloc(pktlen);
     packet->pkt.user_id->attrib_len = pktlen;
     packet->pkt.user_id->attrib_len = pktlen;
+
     p = packet->pkt.user_id->attrib_data;
     for( ; pktlen; pktlen--, p++ )
        *p = iobuf_get_noeof(inp);
     p = packet->pkt.user_id->attrib_data;
     for( ; pktlen; pktlen--, p++ )
        *p = iobuf_get_noeof(inp);
@@ -1941,7 +2053,7 @@ parse_attribute( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
     make_attribute_uidname(packet->pkt.user_id, EXTRA_UID_NAME_SPACE);
 
     if( list_mode ) {
     make_attribute_uidname(packet->pkt.user_id, EXTRA_UID_NAME_SPACE);
 
     if( list_mode ) {
-       printf(":attribute packet: %s\n", packet->pkt.user_id->name );
+       fprintf (listfp, ":attribute packet: %s\n", packet->pkt.user_id->name );
     }
     return 0;
 }
     }
     return 0;
 }
@@ -1952,7 +2064,7 @@ parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
 {
     byte *p;
 
 {
     byte *p;
 
-    packet->pkt.comment = m_alloc(sizeof *packet->pkt.comment + pktlen - 1);
+    packet->pkt.comment = xmalloc(sizeof *packet->pkt.comment + pktlen - 1);
     packet->pkt.comment->len = pktlen;
     p = packet->pkt.comment->data;
     for( ; pktlen; pktlen--, p++ )
     packet->pkt.comment->len = pktlen;
     p = packet->pkt.comment->data;
     for( ; pktlen; pktlen--, p++ )
@@ -1960,15 +2072,15 @@ parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
 
     if( list_mode ) {
        int n = packet->pkt.comment->len;
 
     if( list_mode ) {
        int n = packet->pkt.comment->len;
-       printf(":%scomment packet: \"", pkttype == PKT_OLD_COMMENT?
+       fprintf (listfp, ":%scomment packet: \"", pkttype == PKT_OLD_COMMENT?
                                         "OpenPGP draft " : "" );
        for(p=packet->pkt.comment->data; n; p++, n-- ) {
            if( *p >= ' ' && *p <= 'z' )
                                         "OpenPGP draft " : "" );
        for(p=packet->pkt.comment->data; n; p++, n-- ) {
            if( *p >= ' ' && *p <= 'z' )
-               putchar(*p);
+               putc (*p, listfp);
            else
            else
-               printf("\\x%02x", *p );
+               fprintf (listfp, "\\x%02x", *p );
        }
        }
-       printf("\"\n");
+       fprintf (listfp, "\"\n");
     }
     return 0;
 }
     }
     return 0;
 }
@@ -1983,7 +2095,7 @@ parse_trust( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
     {
       c = iobuf_get_noeof(inp);
       pktlen--;
     {
       c = iobuf_get_noeof(inp);
       pktlen--;
-      pkt->pkt.ring_trust = m_alloc( sizeof *pkt->pkt.ring_trust );
+      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)
       pkt->pkt.ring_trust->trustval = c;
       pkt->pkt.ring_trust->sigcache = 0;
       if (!c && pktlen==1)
@@ -1995,42 +2107,37 @@ parse_trust( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
             pkt->pkt.ring_trust->sigcache = c;
         }
       if( list_mode )
             pkt->pkt.ring_trust->sigcache = c;
         }
       if( list_mode )
-       printf(":trust packet: flag=%02x sigcache=%02x\n",
+       fprintf (listfp, ":trust packet: flag=%02x sigcache=%02x\n",
                pkt->pkt.ring_trust->trustval,
                pkt->pkt.ring_trust->sigcache);
     }
   else
     {
       if( list_mode )
                pkt->pkt.ring_trust->trustval,
                pkt->pkt.ring_trust->sigcache);
     }
   else
     {
       if( list_mode )
-       printf(":trust packet: empty\n");
+       fprintf (listfp, ":trust packet: empty\n");
     }
     }
-  skip_rest (inp, pktlen);
+  iobuf_skip_rest (inp, pktlen, 0);
 }
 
 
 static int
 parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
 }
 
 
 static int
 parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
-                                       PACKET *pkt, int new_ctb )
+                PACKET *pkt, int new_ctb, int partial )
 {
     int rc = 0;
 {
     int rc = 0;
-    int mode, namelen, partial=0;
+    int mode, namelen;
     PKT_plaintext *pt;
     byte *p;
     int c, i;
 
     PKT_plaintext *pt;
     byte *p;
     int c, i;
 
-    if( pktlen && pktlen < 6 ) {
+    if( !partial && pktlen < 6 ) {
        log_error("packet(%d) too short (%lu)\n", pkttype, (ulong)pktlen);
         rc = G10ERR_INVALID_PACKET;
        goto leave;
     }
        log_error("packet(%d) too short (%lu)\n", pkttype, (ulong)pktlen);
         rc = G10ERR_INVALID_PACKET;
        goto leave;
     }
-    /* A packet length of zero indicates partial body length.  A zero
-       data length isn't a zero length packet due to the header (mode,
-       name, etc), so this is accurate. */
-    if(pktlen==0)
-      partial=1;
     mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
     namelen = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
     mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
     namelen = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
-    pt = pkt->pkt.plaintext = m_alloc(sizeof *pkt->pkt.plaintext + namelen -1);
+    pt = pkt->pkt.plaintext = xmalloc(sizeof *pkt->pkt.plaintext + namelen -1);
     pt->new_ctb = new_ctb;
     pt->mode = mode;
     pt->namelen = namelen;
     pt->new_ctb = new_ctb;
     pt->mode = mode;
     pt->namelen = namelen;
@@ -2052,17 +2159,21 @@ parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
     pktlen = 0;
 
     if( list_mode ) {
     pktlen = 0;
 
     if( list_mode ) {
-       printf(":literal data packet:\n"
-              "\tmode %c, created %lu, name=\"",
-                   mode >= ' ' && mode <'z'? mode : '?',
+       fprintf (listfp, ":literal data packet:\n"
+              "\tmode %c (%X), created %lu, name=\"",
+                   mode >= ' ' && mode <'z'? mode : '?', mode,
                    (ulong)pt->timestamp );
        for(p=pt->name,i=0; i < namelen; p++, i++ ) {
            if( *p >= ' ' && *p <= 'z' )
                    (ulong)pt->timestamp );
        for(p=pt->name,i=0; i < namelen; p++, i++ ) {
            if( *p >= ' ' && *p <= 'z' )
-               putchar(*p);
+               putc (*p, listfp);
            else
            else
-               printf("\\x%02x", *p );
+               fprintf (listfp, "\\x%02x", *p );
        }
        }
-       printf("\",\n\traw data: %lu bytes\n", (ulong)pt->len );
+       fprintf (listfp, "\",\n\traw data: ");
+       if(partial)
+         fprintf (listfp, "unknown length\n");
+       else
+         fprintf (listfp, "%lu bytes\n", (ulong)pt->len );
     }
 
   leave:
     }
 
   leave:
@@ -2080,26 +2191,26 @@ parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
      * (this should be the last object in a file or
      * the compress algorithm should know the length)
      */
      * (this should be the last object in a file or
      * the compress algorithm should know the length)
      */
-    zd = pkt->pkt.compressed = m_alloc(sizeof *pkt->pkt.compressed );
+    zd = pkt->pkt.compressed = xmalloc(sizeof *pkt->pkt.compressed );
     zd->algorithm = iobuf_get_noeof(inp);
     zd->len = 0; /* not used */ 
     zd->new_ctb = new_ctb;
     zd->buf = inp;
     if( list_mode )
     zd->algorithm = iobuf_get_noeof(inp);
     zd->len = 0; /* not used */ 
     zd->new_ctb = new_ctb;
     zd->buf = inp;
     if( list_mode )
-       printf(":compressed packet: algo=%d\n", zd->algorithm);
+       fprintf (listfp, ":compressed packet: algo=%d\n", zd->algorithm);
     return 0;
 }
 
 
 static int
 parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
     return 0;
 }
 
 
 static int
 parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
-                                      PACKET *pkt, int new_ctb )
+                PACKET *pkt, int new_ctb, int partial )
 {
     int rc = 0;
     PKT_encrypted *ed;
     unsigned long orig_pktlen = pktlen;
 
 {
     int rc = 0;
     PKT_encrypted *ed;
     unsigned long orig_pktlen = pktlen;
 
-    ed = pkt->pkt.encrypted =  m_alloc(sizeof *pkt->pkt.encrypted );
+    ed = pkt->pkt.encrypted =  xmalloc(sizeof *pkt->pkt.encrypted );
     ed->len = pktlen;
     /* we don't know the extralen which is (cipher_blocksize+2)
        because the algorithm ist not specified in this packet.
     ed->len = pktlen;
     /* we don't know the extralen which is (cipher_blocksize+2)
        because the algorithm ist not specified in this packet.
@@ -2109,6 +2220,7 @@ parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
     ed->extralen = 0;
     ed->buf = NULL;
     ed->new_ctb = new_ctb;
     ed->extralen = 0;
     ed->buf = NULL;
     ed->new_ctb = new_ctb;
+    ed->is_partial = partial;
     ed->mdc_method = 0;
     if( pkttype == PKT_ENCRYPTED_MDC ) {
        /* fixme: add some pktlen sanity checks */
     ed->mdc_method = 0;
     if( pkttype == PKT_ENCRYPTED_MDC ) {
        /* fixme: add some pktlen sanity checks */
@@ -2129,20 +2241,20 @@ parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
     if( orig_pktlen && pktlen < 10 ) { /* actually this is blocksize+2 */
        log_error("packet(%d) too short\n", pkttype);
         rc = G10ERR_INVALID_PACKET;
     if( orig_pktlen && pktlen < 10 ) { /* actually this is blocksize+2 */
        log_error("packet(%d) too short\n", pkttype);
         rc = G10ERR_INVALID_PACKET;
-       skip_rest(inp, pktlen);
+       iobuf_skip_rest(inp, pktlen, partial);
        goto leave;
     }
     if( list_mode ) {
        if( orig_pktlen )
        goto leave;
     }
     if( list_mode ) {
        if( orig_pktlen )
-           printf(":encrypted data packet:\n\tlength: %lu\n", orig_pktlen);
+           fprintf (listfp, ":encrypted data packet:\n\tlength: %lu\n",
+                     orig_pktlen);
        else
        else
-           printf(":encrypted data packet:\n\tlength: unknown\n");
+           fprintf (listfp, ":encrypted data packet:\n\tlength: unknown\n");
        if( ed->mdc_method )
        if( ed->mdc_method )
-           printf("\tmdc_method: %d\n", ed->mdc_method );
+           fprintf (listfp, "\tmdc_method: %d\n", ed->mdc_method );
     }
 
     ed->buf = inp;
     }
 
     ed->buf = inp;
-    pktlen = 0;
 
   leave:
     return rc;
 
   leave:
     return rc;
@@ -2157,9 +2269,9 @@ parse_mdc( IOBUF inp, int pkttype, unsigned long pktlen,
     PKT_mdc *mdc;
     byte *p;
 
     PKT_mdc *mdc;
     byte *p;
 
-    mdc = pkt->pkt.mdc=  m_alloc(sizeof *pkt->pkt.mdc );
+    mdc = pkt->pkt.mdc=  xmalloc(sizeof *pkt->pkt.mdc );
     if( list_mode )
     if( list_mode )
-       printf(":mdc packet: length=%lu\n", pktlen);
+       fprintf (listfp, ":mdc packet: length=%lu\n", pktlen);
     if( !new_ctb || pktlen != 20 ) {
        log_error("mdc_packet with invalid encoding\n");
         rc = G10ERR_INVALID_PACKET;
     if( !new_ctb || pktlen != 20 ) {
        log_error("mdc_packet with invalid encoding\n");
         rc = G10ERR_INVALID_PACKET;
@@ -2186,8 +2298,8 @@ parse_mdc( IOBUF inp, int pkttype, unsigned long pktlen,
  */
 
 static int
  */
 
 static int
-parse_gpg_control( IOBUF inp,
-                   int pkttype, unsigned long pktlen, PACKET *packet )
+parse_gpg_control( IOBUF inp, int pkttype,
+                  unsigned long pktlen, PACKET *packet, int partial )
 {
     byte *p;
     const byte *sesmark;
 {
     byte *p;
     const byte *sesmark;
@@ -2195,7 +2307,7 @@ parse_gpg_control( IOBUF inp,
     int i;
 
     if ( list_mode )
     int i;
 
     if ( list_mode )
-        printf(":packet 63: length %lu ",  pktlen);
+        fprintf (listfp, ":packet 63: length %lu ",  pktlen);
 
     sesmark = get_session_marker ( &sesmarklen );
     if ( pktlen < sesmarklen+1 ) /* 1 is for the control bytes */
 
     sesmark = get_session_marker ( &sesmarklen );
     if ( pktlen < sesmarklen+1 ) /* 1 is for the control bytes */
@@ -2207,7 +2319,7 @@ parse_gpg_control( IOBUF inp,
     if ( list_mode )
         puts ("- gpg control packet");
 
     if ( list_mode )
         puts ("- gpg control packet");
 
-    packet->pkt.gpg_control = m_alloc(sizeof *packet->pkt.gpg_control
+    packet->pkt.gpg_control = xmalloc(sizeof *packet->pkt.gpg_control
                                       + pktlen - 1);
     packet->pkt.gpg_control->control = iobuf_get_noeof(inp); pktlen--;
     packet->pkt.gpg_control->datalen = pktlen;
                                       + pktlen - 1);
     packet->pkt.gpg_control->control = iobuf_get_noeof(inp); pktlen--;
     packet->pkt.gpg_control->datalen = pktlen;
@@ -2222,8 +2334,8 @@ parse_gpg_control( IOBUF inp,
         int c;
 
         i=0;
         int c;
 
         i=0;
-        printf("- private (rest length %lu)\n",  pktlen);
-        if( iobuf_in_block_mode(inp) ) {
+        fprintf (listfp, "- private (rest length %lu)\n",  pktlen);
+        if( partial ) {
             while( (c=iobuf_get(inp)) != -1 )
                 dump_hex_line(c, &i);
         }
             while( (c=iobuf_get(inp)) != -1 )
                 dump_hex_line(c, &i);
         }
@@ -2231,9 +2343,9 @@ parse_gpg_control( IOBUF inp,
             for( ; pktlen; pktlen-- )
                 dump_hex_line(iobuf_get(inp), &i);
         }
             for( ; pktlen; pktlen-- )
                 dump_hex_line(iobuf_get(inp), &i);
         }
-        putchar('\n');
+        putc ('\n', listfp);
     }
     }
-    skip_rest(inp,pktlen);
+    iobuf_skip_rest(inp,pktlen, 0);
     return G10ERR_INVALID_PACKET;
 }
 
     return G10ERR_INVALID_PACKET;
 }
 
@@ -2244,10 +2356,10 @@ create_gpg_control( ctrlpkttype_t type, const byte *data, size_t datalen )
     PACKET *packet;
     byte *p;
 
     PACKET *packet;
     byte *p;
 
-    packet = m_alloc( sizeof *packet );
+    packet = xmalloc( sizeof *packet );
     init_packet(packet);
     packet->pkttype = PKT_GPG_CONTROL;
     init_packet(packet);
     packet->pkttype = PKT_GPG_CONTROL;
-    packet->pkt.gpg_control = m_alloc(sizeof *packet->pkt.gpg_control
+    packet->pkt.gpg_control = xmalloc(sizeof *packet->pkt.gpg_control
                                       + datalen - 1);
     packet->pkt.gpg_control->control = type;
     packet->pkt.gpg_control->datalen = datalen;
                                       + datalen - 1);
     packet->pkt.gpg_control->control = type;
     packet->pkt.gpg_control->datalen = datalen;