Cleanups and minor fixes.
[gnupg.git] / g10 / parse-packet.c
1 /* parse-packet.c  - read packets
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <assert.h>
26
27 #include "packet.h"
28 #include "iobuf.h"
29 #include "mpi.h"
30 #include "util.h"
31 #include "cipher.h"
32 #include "memory.h"
33 #include "filter.h"
34 #include "photoid.h"
35 #include "options.h"
36 #include "main.h"
37 #include "i18n.h"
38
39 static int mpi_print_mode = 0;
40 static int list_mode = 0;
41
42 static int  parse( IOBUF inp, PACKET *pkt, int onlykeypkts,
43                   off_t *retpos, int *skip, IOBUF out, int do_skip
44             #ifdef DEBUG_PARSE_PACKET
45                    ,const char *dbg_w, const char *dbg_f, int dbg_l
46             #endif
47                  );
48 static int  copy_packet( IOBUF inp, IOBUF out, int pkttype,
49                                                unsigned long pktlen );
50 static void skip_packet( IOBUF inp, int pkttype, unsigned long pktlen );
51 static void skip_rest( IOBUF inp, unsigned long pktlen );
52 static void *read_rest( IOBUF inp, size_t pktlen );
53 static int  parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen,
54                                                              PACKET *packet );
55 static int  parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen,
56                                                              PACKET *packet );
57 static int  parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
58                                                          PKT_signature *sig );
59 static int  parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
60                                                         PKT_onepass_sig *ops );
61 static int  parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
62                                       byte *hdr, int hdrlen, PACKET *packet );
63 static int  parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen,
64                                                            PACKET *packet );
65 static int  parse_attribute( IOBUF inp, int pkttype, unsigned long pktlen,
66                                                            PACKET *packet );
67 static int  parse_comment( IOBUF inp, int pkttype, unsigned long pktlen,
68                                                            PACKET *packet );
69 static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen,
70                                                            PACKET *packet );
71 static int  parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
72                                                PACKET *packet, int new_ctb);
73 static int  parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
74                                                PACKET *packet, int new_ctb );
75 static int  parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
76                                                PACKET *packet, int new_ctb);
77 static int  parse_mdc( IOBUF inp, int pkttype, unsigned long pktlen,
78                                                PACKET *packet, int new_ctb);
79 static int  parse_gpg_control( IOBUF inp, int pkttype, unsigned long pktlen,
80                                PACKET *packet );
81
82 static unsigned short
83 read_16(IOBUF inp)
84 {
85     unsigned short a;
86     a = iobuf_get_noeof(inp) << 8;
87     a |= iobuf_get_noeof(inp);
88     return a;
89 }
90
91 static unsigned long
92 read_32(IOBUF inp)
93 {
94     unsigned long a;
95     a =  iobuf_get_noeof(inp) << 24;
96     a |= iobuf_get_noeof(inp) << 16;
97     a |= iobuf_get_noeof(inp) << 8;
98     a |= iobuf_get_noeof(inp);
99     return a;
100 }
101
102
103 int
104 set_packet_list_mode( int mode )
105 {
106     int old = list_mode;
107     list_mode = mode;
108     mpi_print_mode = DBG_MPI;
109     return old;
110 }
111
112 static void
113 unknown_pubkey_warning( int algo )
114 {
115     static byte unknown_pubkey_algos[256];
116
117     algo &= 0xff;
118     if( !unknown_pubkey_algos[algo] ) {
119         if( opt.verbose )
120             log_info(_("can't handle public key algorithm %d\n"), algo );
121         unknown_pubkey_algos[algo] = 1;
122     }
123 }
124
125 /****************
126  * Parse a Packet and return it in packet
127  * Returns: 0 := valid packet in pkt
128  *         -1 := no more packets
129  *         >0 := error
130  * Note: The function may return an error and a partly valid packet;
131  * caller must free this packet.
132  */
133 #ifdef DEBUG_PARSE_PACKET
134 int
135 dbg_parse_packet( IOBUF inp, PACKET *pkt, const char *dbg_f, int dbg_l )
136 {
137     int skip, rc;
138
139     do {
140         rc = parse( inp, pkt, 0, NULL, &skip, NULL, 0, "parse", dbg_f, dbg_l );
141     } while( skip );
142     return rc;
143 }
144 #else
145 int
146 parse_packet( IOBUF inp, PACKET *pkt )
147 {
148     int skip, rc;
149
150     do {
151         rc = parse( inp, pkt, 0, NULL, &skip, NULL, 0 );
152     } while( skip );
153     return rc;
154 }
155 #endif
156
157 /****************
158  * Like parse packet, but only return secret or public (sub)key packets.
159  */
160 #ifdef DEBUG_PARSE_PACKET
161 int
162 dbg_search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid,
163                    const char *dbg_f, int dbg_l )
164 {
165     int skip, rc;
166
167     do {
168         rc = parse( inp, pkt, with_uid?2:1, retpos, &skip, NULL, 0, "search", dbg_f, dbg_l );
169     } while( skip );
170     return rc;
171 }
172 #else
173 int
174 search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid )
175 {
176     int skip, rc;
177
178     do {
179         rc = parse( inp, pkt, with_uid?2:1, retpos, &skip, NULL, 0 );
180     } while( skip );
181     return rc;
182 }
183 #endif
184
185 /****************
186  * Copy all packets from INP to OUT, thereby removing unused spaces.
187  */
188 #ifdef DEBUG_PARSE_PACKET
189 int
190 dbg_copy_all_packets( IOBUF inp, IOBUF out,
191                    const char *dbg_f, int dbg_l )
192 {
193     PACKET pkt;
194     int skip, rc=0;
195     do {
196         init_packet(&pkt);
197     } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0, "copy", dbg_f, dbg_l )));
198     return rc;
199 }
200 #else
201 int
202 copy_all_packets( IOBUF inp, IOBUF out )
203 {
204     PACKET pkt;
205     int skip, rc=0;
206     do {
207         init_packet(&pkt);
208     } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0 )));
209     return rc;
210 }
211 #endif
212
213 /****************
214  * Copy some packets from INP to OUT, thereby removing unused spaces.
215  * Stop at offset STOPoff (i.e. don't copy packets at this or later offsets)
216  */
217 #ifdef DEBUG_PARSE_PACKET
218 int
219 dbg_copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff,
220                    const char *dbg_f, int dbg_l )
221 {
222     PACKET pkt;
223     int skip, rc=0;
224     do {
225         if( iobuf_tell(inp) >= stopoff )
226             return 0;
227         init_packet(&pkt);
228     } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0,
229                                      "some", dbg_f, dbg_l )) );
230     return rc;
231 }
232 #else
233 int
234 copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff )
235 {
236     PACKET pkt;
237     int skip, rc=0;
238     do {
239         if( iobuf_tell(inp) >= stopoff )
240             return 0;
241         init_packet(&pkt);
242     } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0 )) );
243     return rc;
244 }
245 #endif
246
247 /****************
248  * Skip over N packets
249  */
250 #ifdef DEBUG_PARSE_PACKET
251 int
252 dbg_skip_some_packets( IOBUF inp, unsigned n,
253                    const char *dbg_f, int dbg_l )
254 {
255     int skip, rc=0;
256     PACKET pkt;
257
258     for( ;n && !rc; n--) {
259         init_packet(&pkt);
260         rc = parse( inp, &pkt, 0, NULL, &skip, NULL, 1, "skip", dbg_f, dbg_l );
261     }
262     return rc;
263 }
264 #else
265 int
266 skip_some_packets( IOBUF inp, unsigned n )
267 {
268     int skip, rc=0;
269     PACKET pkt;
270
271     for( ;n && !rc; n--) {
272         init_packet(&pkt);
273         rc = parse( inp, &pkt, 0, NULL, &skip, NULL, 1 );
274     }
275     return rc;
276 }
277 #endif
278
279
280 /****************
281  * Parse packet. Set the variable skip points to 1 if the packet
282  * should be skipped; this is the case if either ONLYKEYPKTS is set
283  * and the parsed packet isn't one or the
284  * packet-type is 0, indicating deleted stuff.
285  * if OUT is not NULL, a special copymode is used.
286  */
287 static int
288 parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
289        int *skip, IOBUF out, int do_skip
290 #ifdef DEBUG_PARSE_PACKET
291        ,const char *dbg_w, const char *dbg_f, int dbg_l
292 #endif
293      )
294 {
295     int rc=0, c, ctb, pkttype, lenbytes;
296     unsigned long pktlen;
297     byte hdr[8];
298     int hdrlen;
299     int new_ctb = 0;
300     int with_uid = (onlykeypkts == 2);
301
302     *skip = 0;
303     assert( !pkt->pkt.generic );
304     if( retpos )
305         *retpos = iobuf_tell(inp);
306
307     if( (ctb = iobuf_get(inp)) == -1 ) {
308         rc = -1;
309         goto leave;
310     }
311     hdrlen=0;
312     hdr[hdrlen++] = ctb;
313     if( !(ctb & 0x80) ) {
314         log_error("%s: invalid packet (ctb=%02x)\n", iobuf_where(inp), ctb );
315         rc = G10ERR_INVALID_PACKET;
316         goto leave;
317     }
318     pktlen = 0;
319     new_ctb = !!(ctb & 0x40);
320     if( new_ctb ) {
321         pkttype = ctb & 0x3f;
322         if( (c = iobuf_get(inp)) == -1 ) {
323             log_error("%s: 1st length byte missing\n", iobuf_where(inp) );
324             rc = G10ERR_INVALID_PACKET;
325             goto leave;
326         }
327         if (pkttype == PKT_COMPRESSED) {
328              iobuf_set_partial_block_mode(inp, c & 0xff);
329              pktlen = 0;/* to indicate partial length */
330         }
331         else {
332              hdr[hdrlen++] = c;
333              if( c < 192 )
334                   pktlen = c;
335              else if( c < 224 ) {
336                   pktlen = (c - 192) * 256;
337                   if( (c = iobuf_get(inp)) == -1 ) {
338                        log_error("%s: 2nd length byte missing\n",
339                                  iobuf_where(inp) );
340                        rc = G10ERR_INVALID_PACKET;
341                        goto leave;
342                   }
343                   hdr[hdrlen++] = c;
344                   pktlen += c + 192;
345              }
346              else if( c == 255 ) {
347                   pktlen  = (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 24;
348                   pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 16;
349                   pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 8;
350                   if( (c = iobuf_get(inp)) == -1 ) {
351                        log_error("%s: 4 byte length invalid\n",
352                                  iobuf_where(inp) );
353                        rc = G10ERR_INVALID_PACKET;
354                        goto leave;
355                   }
356                   pktlen |= (hdr[hdrlen++] = c );
357              }
358              else { /* partial body length */
359                   iobuf_set_partial_block_mode(inp, c & 0xff);
360                   pktlen = 0;/* to indicate partial length */
361              }
362         }
363     }
364     else {
365         pkttype = (ctb>>2)&0xf;
366         lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3));
367         if( !lenbytes ) {
368             pktlen = 0; /* don't know the value */
369             if( pkttype != PKT_COMPRESSED )
370                 iobuf_set_block_mode(inp, 1);
371         }
372         else {
373             for( ; lenbytes; lenbytes-- ) {
374                 pktlen <<= 8;
375                 pktlen |= hdr[hdrlen++] = iobuf_get_noeof(inp);
376             }
377         }
378     }
379
380     if (pktlen == 0xffffffff) {
381         /* with a some probability this is caused by a problem in the
382          * the uncompressing layer - in some error cases it just loops
383          * and spits out 0xff bytes. */
384         log_error ("%s: garbled packet detected\n", iobuf_where(inp) );
385         g10_exit (2);
386     }
387
388     if( out && pkttype  ) {
389         if( iobuf_write( out, hdr, hdrlen ) == -1 )
390             rc = G10ERR_WRITE_FILE;
391         else
392             rc = copy_packet(inp, out, pkttype, pktlen );
393         goto leave;
394     }
395
396     if (with_uid && pkttype == PKT_USER_ID)
397         ;
398     else if( do_skip 
399         || !pkttype
400         || (onlykeypkts && pkttype != PKT_PUBLIC_SUBKEY
401                         && pkttype != PKT_PUBLIC_KEY
402                         && pkttype != PKT_SECRET_SUBKEY
403                         && pkttype != PKT_SECRET_KEY  ) ) {
404         skip_rest(inp, pktlen);
405         *skip = 1;
406         rc = 0;
407         goto leave;
408     }
409
410     if( DBG_PACKET ) {
411 #ifdef DEBUG_PARSE_PACKET
412         log_debug("parse_packet(iob=%d): type=%d length=%lu%s (%s.%s.%d)\n",
413                    iobuf_id(inp), pkttype, pktlen, new_ctb?" (new_ctb)":"",
414                     dbg_w, dbg_f, dbg_l );
415 #else
416         log_debug("parse_packet(iob=%d): type=%d length=%lu%s\n",
417                    iobuf_id(inp), pkttype, pktlen, new_ctb?" (new_ctb)":"" );
418 #endif
419     }
420     pkt->pkttype = pkttype;
421     rc = G10ERR_UNKNOWN_PACKET; /* default error */
422     switch( pkttype ) {
423       case PKT_PUBLIC_KEY:
424       case PKT_PUBLIC_SUBKEY:
425         pkt->pkt.public_key = m_alloc_clear(sizeof *pkt->pkt.public_key );
426         rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt );
427         break;
428       case PKT_SECRET_KEY:
429       case PKT_SECRET_SUBKEY:
430         pkt->pkt.secret_key = m_alloc_clear(sizeof *pkt->pkt.secret_key );
431         rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt );
432         break;
433       case PKT_SYMKEY_ENC:
434         rc = parse_symkeyenc( inp, pkttype, pktlen, pkt );
435         break;
436       case PKT_PUBKEY_ENC:
437         rc = parse_pubkeyenc(inp, pkttype, pktlen, pkt );
438         break;
439       case PKT_SIGNATURE:
440         pkt->pkt.signature = m_alloc_clear(sizeof *pkt->pkt.signature );
441         rc = parse_signature(inp, pkttype, pktlen, pkt->pkt.signature );
442         break;
443       case PKT_ONEPASS_SIG:
444         pkt->pkt.onepass_sig = m_alloc_clear(sizeof *pkt->pkt.onepass_sig );
445         rc = parse_onepass_sig(inp, pkttype, pktlen, pkt->pkt.onepass_sig );
446         break;
447       case PKT_USER_ID:
448         rc = parse_user_id(inp, pkttype, pktlen, pkt );
449         break;
450       case PKT_ATTRIBUTE:
451         pkt->pkttype = pkttype = PKT_USER_ID;  /* we store it in the userID */
452         rc = parse_attribute(inp, pkttype, pktlen, pkt);
453         break;
454       case PKT_OLD_COMMENT:
455       case PKT_COMMENT:
456         rc = parse_comment(inp, pkttype, pktlen, pkt);
457         break;
458       case PKT_RING_TRUST:
459         parse_trust(inp, pkttype, pktlen, pkt);
460         rc = 0;
461         break;
462       case PKT_PLAINTEXT:
463         rc = parse_plaintext(inp, pkttype, pktlen, pkt, new_ctb );
464         break;
465       case PKT_COMPRESSED:
466         rc = parse_compressed(inp, pkttype, pktlen, pkt, new_ctb );
467         break;
468       case PKT_ENCRYPTED:
469       case PKT_ENCRYPTED_MDC:
470         rc = parse_encrypted(inp, pkttype, pktlen, pkt, new_ctb );
471         break;
472       case PKT_MDC:
473         rc = parse_mdc(inp, pkttype, pktlen, pkt, new_ctb );
474         break;
475       case PKT_GPG_CONTROL:
476         rc = parse_gpg_control(inp, pkttype, pktlen, pkt );
477         break;
478       default:
479         skip_packet(inp, pkttype, pktlen);
480         break;
481     }
482
483   leave:
484     if( !rc && iobuf_error(inp) )
485         rc = G10ERR_INV_KEYRING;
486     return rc;
487 }
488
489 static void
490 dump_hex_line( int c, int *i )
491 {
492     if( *i && !(*i%8) ) {
493         if( *i && !(*i%24) )
494             printf("\n%4d:", *i );
495         else
496             putchar(' ');
497     }
498     if( c == -1 )
499         printf(" EOF" );
500     else
501         printf(" %02x", c );
502     ++*i;
503 }
504
505
506 static int
507 copy_packet( IOBUF inp, IOBUF out, int pkttype, unsigned long pktlen )
508 {
509     int n;
510     char buf[100];
511
512     if( iobuf_in_block_mode(inp) ) {
513         while( (n = iobuf_read( inp, buf, 100 )) != -1 )
514             if( iobuf_write(out, buf, n ) )
515                 return G10ERR_WRITE_FILE; /* write error */
516     }
517     else if( !pktlen && pkttype == PKT_COMPRESSED ) {
518         log_debug("copy_packet: compressed!\n");
519         /* compressed packet, copy till EOF */
520         while( (n = iobuf_read( inp, buf, 100 )) != -1 )
521             if( iobuf_write(out, buf, n ) )
522                 return G10ERR_WRITE_FILE; /* write error */
523     }
524     else {
525         for( ; pktlen; pktlen -= n ) {
526             n = pktlen > 100 ? 100 : pktlen;
527             n = iobuf_read( inp, buf, n );
528             if( n == -1 )
529                 return G10ERR_READ_FILE;
530             if( iobuf_write(out, buf, n ) )
531                 return G10ERR_WRITE_FILE; /* write error */
532         }
533     }
534     return 0;
535 }
536
537
538 static void
539 skip_packet( IOBUF inp, int pkttype, unsigned long pktlen )
540 {
541     if( list_mode ) {
542         if( pkttype == PKT_MARKER )
543             fputs(":marker packet:\n", stdout );
544         else
545             printf(":unknown packet: type %2d, length %lu\n", pkttype, pktlen);
546         if( pkttype ) {
547             int c, i=0 ;
548             if( pkttype != PKT_MARKER )
549                 fputs("dump:", stdout );
550             if( iobuf_in_block_mode(inp) ) {
551                 while( (c=iobuf_get(inp)) != -1 )
552                     dump_hex_line(c, &i);
553             }
554             else {
555                 for( ; pktlen; pktlen-- )
556                     dump_hex_line(iobuf_get(inp), &i);
557             }
558             putchar('\n');
559             return;
560         }
561     }
562     skip_rest(inp,pktlen);
563 }
564
565 static void
566 skip_rest( IOBUF inp, unsigned long pktlen )
567 {
568     if( iobuf_in_block_mode(inp) ) {
569         while( iobuf_get(inp) != -1 )
570                 ;
571     }
572     else {
573         for( ; pktlen; pktlen-- )
574             if( iobuf_get(inp) == -1 )
575                 break;
576     }
577 }
578
579
580 static void *
581 read_rest( IOBUF inp, size_t pktlen )
582 {
583     byte *p;
584     int i;
585
586     if( iobuf_in_block_mode(inp) ) {
587         log_error("read_rest: can't store stream data\n");
588         p = NULL;
589     }
590     else {
591         p = m_alloc( pktlen );
592         for(i=0; pktlen; pktlen--, i++ )
593             p[i] = iobuf_get(inp);
594     }
595     return p;
596 }
597
598
599
600 static int
601 parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
602 {
603     PKT_symkey_enc *k;
604     int rc = 0;
605     int i, version, s2kmode, cipher_algo, hash_algo, seskeylen, minlen;
606
607     if( pktlen < 4 ) {
608         log_error("packet(%d) too short\n", pkttype);
609         rc = G10ERR_INVALID_PACKET;
610         goto leave;
611     }
612     version = iobuf_get_noeof(inp); pktlen--;
613     if( version != 4 ) {
614         log_error("packet(%d) with unknown version %d\n", pkttype, version);
615         rc = G10ERR_INVALID_PACKET;
616         goto leave;
617     }
618     if( pktlen > 200 ) { /* (we encode the seskeylen in a byte) */
619         log_error("packet(%d) too large\n", pkttype);
620         rc = G10ERR_INVALID_PACKET;
621         goto leave;
622     }
623     cipher_algo = iobuf_get_noeof(inp); pktlen--;
624     s2kmode = iobuf_get_noeof(inp); pktlen--;
625     hash_algo = iobuf_get_noeof(inp); pktlen--;
626     switch( s2kmode ) {
627       case 0:  /* simple s2k */
628         minlen = 0;
629         break;
630       case 1:  /* salted s2k */
631         minlen = 8;
632         break;
633       case 3:  /* iterated+salted s2k */
634         minlen = 9;
635         break;
636       default:
637         log_error("unknown S2K %d\n", s2kmode );
638         goto leave;
639     }
640     if( minlen > pktlen ) {
641         log_error("packet with S2K %d too short\n", s2kmode );
642         rc = G10ERR_INVALID_PACKET;
643         goto leave;
644     }
645     seskeylen = pktlen - minlen;
646     k = packet->pkt.symkey_enc = m_alloc_clear( sizeof *packet->pkt.symkey_enc
647                                                 + seskeylen - 1 );
648     k->version = version;
649     k->cipher_algo = cipher_algo;
650     k->s2k.mode = s2kmode;
651     k->s2k.hash_algo = hash_algo;
652     if( s2kmode == 1 || s2kmode == 3 ) {
653         for(i=0; i < 8 && pktlen; i++, pktlen-- )
654             k->s2k.salt[i] = iobuf_get_noeof(inp);
655     }
656     if( s2kmode == 3 ) {
657         k->s2k.count = iobuf_get(inp); pktlen--;
658     }
659     k->seskeylen = seskeylen;
660     for(i=0; i < seskeylen && pktlen; i++, pktlen-- )
661         k->seskey[i] = iobuf_get_noeof(inp);
662     assert( !pktlen );
663
664     if( list_mode ) {
665         printf(":symkey enc packet: version %d, cipher %d, s2k %d, hash %d\n",
666                             version, cipher_algo, s2kmode, hash_algo);
667         if( s2kmode == 1 || s2kmode == 3 ) {
668             printf("\tsalt ");
669             for(i=0; i < 8; i++ )
670                 printf("%02x", k->s2k.salt[i]);
671             if( s2kmode == 3 )
672                 printf(", count %lu\n", (ulong)k->s2k.count );
673             printf("\n");
674         }
675     }
676
677   leave:
678     skip_rest(inp, pktlen);
679     return rc;
680 }
681
682 static int
683 parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
684 {
685     unsigned int n;
686     int rc = 0;
687     int i, ndata;
688     PKT_pubkey_enc *k;
689
690     k = packet->pkt.pubkey_enc = m_alloc_clear(sizeof *packet->pkt.pubkey_enc);
691     if( pktlen < 12 ) {
692         log_error("packet(%d) too short\n", pkttype);
693         rc = G10ERR_INVALID_PACKET;
694         goto leave;
695     }
696     k->version = iobuf_get_noeof(inp); pktlen--;
697     if( k->version != 2 && k->version != 3 ) {
698         log_error("packet(%d) with unknown version %d\n", pkttype, k->version);
699         rc = G10ERR_INVALID_PACKET;
700         goto leave;
701     }
702     k->keyid[0] = read_32(inp); pktlen -= 4;
703     k->keyid[1] = read_32(inp); pktlen -= 4;
704     k->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
705     k->throw_keyid = 0; /* only used as flag for build_packet */
706     if( list_mode )
707         printf(":pubkey enc packet: version %d, algo %d, keyid %08lX%08lX\n",
708           k->version, k->pubkey_algo, (ulong)k->keyid[0], (ulong)k->keyid[1]);
709
710     ndata = pubkey_get_nenc(k->pubkey_algo);
711     if( !ndata ) {
712         if( list_mode )
713             printf("\tunsupported algorithm %d\n", k->pubkey_algo );
714         unknown_pubkey_warning( k->pubkey_algo );
715         k->data[0] = NULL;  /* no need to store the encrypted data */
716     }
717     else {
718         for( i=0; i < ndata; i++ ) {
719             n = pktlen;
720             k->data[i] = mpi_read(inp, &n, 0); pktlen -=n;
721             if( list_mode ) {
722                 printf("\tdata: ");
723                 mpi_print(stdout, k->data[i], mpi_print_mode );
724                 putchar('\n');
725             }
726             if (!k->data[i])
727                 rc = G10ERR_INVALID_PACKET;
728         }
729     }
730
731   leave:
732     skip_rest(inp, pktlen);
733     return rc;
734 }
735
736
737 static void
738 dump_sig_subpkt( int hashed, int type, int critical,
739                  const byte *buffer, size_t buflen, size_t length )
740 {
741     const char *p=NULL;
742     int i;
743
744     /* The CERT has warning out with explains how to use GNUPG to
745      * detect the ARRs - we print our old message here when it is a faked
746      * ARR and add an additional notice */
747     if ( type == SIGSUBPKT_ARR && !hashed ) {
748         printf("\tsubpkt %d len %u (additional recipient request)\n"
749                "WARNING: PGP versions > 5.0 and < 6.5.8 will automagically "
750                "encrypt to this key and thereby reveal the plaintext to "
751                "the owner of this ARR key. Detailed info follows:\n",
752                type, (unsigned)length );
753     }
754     
755    
756     printf("\t%s%ssubpkt %d len %u (", /*)*/
757               critical ? "critical ":"",
758               hashed ? "hashed ":"", type, (unsigned)length );
759     buffer++;
760     length--;
761     if( length > buflen ) {
762         printf("too short: buffer is only %u)\n", (unsigned)buflen );
763         return;
764     }
765     switch( type ) {
766       case SIGSUBPKT_SIG_CREATED:
767         if( length >= 4 )
768             printf("sig created %s", strtimestamp( buffer_to_u32(buffer) ) );
769         break;
770       case SIGSUBPKT_SIG_EXPIRE:
771         if( length >= 4 )
772             printf("sig expires after %s",
773                                      strtimevalue( buffer_to_u32(buffer) ) );
774         break;
775       case SIGSUBPKT_EXPORTABLE:
776         if( length )
777             printf("%sexportable", *buffer? "":"not ");
778         break;
779       case SIGSUBPKT_TRUST:
780         if(length!=2)
781           p="[invalid trust signature]";
782         else
783           printf("trust signature of level %d, amount %d",buffer[0],buffer[1]);
784         break;
785       case SIGSUBPKT_REGEXP:
786         if(!length)
787           p="[invalid regexp]";
788         else
789           printf("regular expression: \"%s\"",buffer);
790         break;
791       case SIGSUBPKT_REVOCABLE:
792         if( length )
793             printf("%srevocable", *buffer? "":"not ");
794         break;
795       case SIGSUBPKT_KEY_EXPIRE:
796         if( length >= 4 )
797             printf("key expires after %s",
798                                     strtimevalue( buffer_to_u32(buffer) ) );
799         break;
800       case SIGSUBPKT_PREF_SYM:
801         fputs("pref-sym-algos:", stdout );
802         for( i=0; i < length; i++ )
803             printf(" %d", buffer[i] );
804         break;
805       case SIGSUBPKT_REV_KEY:
806         fputs("revocation key: ", stdout );
807         if( length < 22 )
808             p = "[too short]";
809         else {
810             printf("c=%02x a=%d f=", buffer[0], buffer[1] );
811             for( i=2; i < length; i++ )
812                 printf("%02X", buffer[i] );
813         }
814         break;
815       case SIGSUBPKT_ISSUER:
816         if( length >= 8 )
817             printf("issuer key ID %08lX%08lX",
818                       (ulong)buffer_to_u32(buffer),
819                       (ulong)buffer_to_u32(buffer+4) );
820         break;
821       case SIGSUBPKT_NOTATION:
822         {
823             fputs("notation: ", stdout );
824             if( length < 8 )
825                 p = "[too short]";
826             else if( !(*buffer & 0x80) )
827                 p = "[not human readable]";
828             else {
829                 const byte *s = buffer;
830                 size_t n1, n2;
831
832                 n1 = (s[4] << 8) | s[5];
833                 n2 = (s[6] << 8) | s[7];
834                 s += 8;
835                 if( 8+n1+n2 != length )
836                     p = "[error]";
837                 else {
838                     print_string( stdout, s, n1, ')' );
839                     putc( '=', stdout );
840                     print_string( stdout, s+n1, n2, ')' );
841                 }
842             }
843         }
844         break;
845       case SIGSUBPKT_PREF_HASH:
846         fputs("pref-hash-algos:", stdout );
847         for( i=0; i < length; i++ )
848             printf(" %d", buffer[i] );
849         break;
850       case SIGSUBPKT_PREF_COMPR:
851         fputs("pref-zip-algos:", stdout );
852         for( i=0; i < length; i++ )
853             printf(" %d", buffer[i] );
854         break;
855       case SIGSUBPKT_KS_FLAGS:
856         fputs("key server preferences:",stdout);
857         for(i=0;i<length;i++)
858           printf(" %02X", buffer[i]);
859         break;
860       case SIGSUBPKT_PREF_KS:
861         p = "preferred key server";
862         break;
863       case SIGSUBPKT_PRIMARY_UID:
864         p = "primary user ID";
865         break;
866       case SIGSUBPKT_POLICY:
867         fputs("policy: ", stdout );
868         print_string( stdout, buffer, length, ')' );
869         break;
870       case SIGSUBPKT_KEY_FLAGS:
871         fputs ( "key flags:", stdout );
872         for( i=0; i < length; i++ )
873             printf(" %02X", buffer[i] );
874         break;
875       case SIGSUBPKT_SIGNERS_UID:
876         p = "signer's user ID";
877         break;
878       case SIGSUBPKT_REVOC_REASON:
879         if( length ) {
880             printf("revocation reason 0x%02x (", *buffer );
881             print_string( stdout, buffer+1, length-1, ')' );
882             p = ")";
883         }
884         break;
885       case SIGSUBPKT_ARR:
886         fputs("Big Brother's key (ignored): ", stdout );
887         if( length < 22 )
888             p = "[too short]";
889         else {
890             printf("c=%02x a=%d f=", buffer[0], buffer[1] );
891             for( i=2; i < length; i++ )
892                 printf("%02X", buffer[i] );
893         }
894         break;
895       case SIGSUBPKT_FEATURES:
896         fputs ( "features:", stdout );
897         for( i=0; i < length; i++ )
898             printf(" %02x", buffer[i] );
899         break;
900       case SIGSUBPKT_PRIV_VERIFY_CACHE:
901         p = "obsolete verification cache";
902         break;
903       default: p = "?"; break;
904     }
905
906     printf("%s)\n", p? p: "");
907 }
908
909 /****************
910  * Returns: >= 0 offset into buffer
911  *          -1 unknown type
912  *          -2 unsupported type
913  *          -3 subpacket too short
914  */
915 int
916 parse_one_sig_subpkt( const byte *buffer, size_t n, int type )
917 {
918     switch( type ) {
919       case SIGSUBPKT_REV_KEY:
920         if(n < 22)
921           break;
922         return 0;
923       case SIGSUBPKT_SIG_CREATED:
924       case SIGSUBPKT_SIG_EXPIRE:
925       case SIGSUBPKT_KEY_EXPIRE:
926         if( n < 4 )
927             break;
928         return 0;
929       case SIGSUBPKT_KEY_FLAGS:
930       case SIGSUBPKT_KS_FLAGS:
931       case SIGSUBPKT_PREF_SYM:
932       case SIGSUBPKT_PREF_HASH:
933       case SIGSUBPKT_PREF_COMPR:
934       case SIGSUBPKT_POLICY:
935       case SIGSUBPKT_FEATURES:
936         return 0;
937       case SIGSUBPKT_EXPORTABLE:
938       case SIGSUBPKT_REVOCABLE:
939         if( !n )
940             break;
941         return 0;
942       case SIGSUBPKT_ISSUER: /* issuer key ID */
943         if( n < 8 )
944             break;
945         return 0;
946       case SIGSUBPKT_NOTATION:
947         if( n < 8 ) /* minimum length needed */
948             break;
949         return 0;
950       case SIGSUBPKT_REVOC_REASON:
951         if( !n  )
952             break;
953         return 0;
954       case SIGSUBPKT_PRIMARY_UID:
955           if ( n != 1 )
956               break;
957           return 0;   
958       case SIGSUBPKT_PRIV_VERIFY_CACHE:
959         /* We used this in gpg 1.0.5 and 1.0.6 to cache signature
960          * verification results - it is no longer used.
961          * "GPG" 0x00 <mode> <stat>
962          * where mode == 1: valid data, stat == 0: invalid signature
963          * stat == 1: valid signature 
964          * (because we use private data, we check our marker) */
965         if( n < 6 )
966             break;
967         if( buffer[0] != 'G' || buffer[1] != 'P'
968             || buffer[2] != 'G' || buffer[3] )
969             return -2;
970         return 4;
971       default: return -1;
972     }
973     return -3;
974 }
975
976
977 static int
978 can_handle_critical( const byte *buffer, size_t n, int type )
979 {
980     switch( type ) {
981       case SIGSUBPKT_NOTATION:
982         if( n >= 8 && (*buffer & 0x80) )
983             return 1; /* human readable is handled */
984         return 0;
985
986       case SIGSUBPKT_SIG_CREATED:
987       case SIGSUBPKT_SIG_EXPIRE:
988       case SIGSUBPKT_KEY_EXPIRE:
989       case SIGSUBPKT_EXPORTABLE:
990       case SIGSUBPKT_REVOCABLE:
991       case SIGSUBPKT_REV_KEY:
992       case SIGSUBPKT_ISSUER:/* issuer key ID */
993       case SIGSUBPKT_PREF_SYM:
994       case SIGSUBPKT_PREF_HASH:
995       case SIGSUBPKT_PREF_COMPR:
996       case SIGSUBPKT_KEY_FLAGS:
997       case SIGSUBPKT_PRIMARY_UID:
998       case SIGSUBPKT_FEATURES:
999       case SIGSUBPKT_POLICY: /* Is it enough to show the policy? */
1000         return 1;
1001
1002       default:
1003         return 0;
1004     }
1005 }
1006
1007
1008 const byte *
1009 enum_sig_subpkt( const subpktarea_t *pktbuf, sigsubpkttype_t reqtype,
1010                  size_t *ret_n, int *start, int *critical )
1011 {
1012     const byte *buffer;
1013     int buflen;
1014     int type;
1015     int critical_dummy;
1016     int offset;
1017     size_t n;
1018     int seq = 0;
1019     int reqseq = start? *start: 0;
1020
1021     if(!critical)
1022       critical=&critical_dummy;
1023
1024     if( !pktbuf || reqseq == -1 ) {
1025         /* return some value different from NULL to indicate that
1026          * there is no critical bit we do not understand.  The caller
1027          * will never use the value.  Yes I know, it is an ugly hack */
1028         return reqtype == SIGSUBPKT_TEST_CRITICAL? (const byte*)&pktbuf : NULL;
1029     }
1030     buffer = pktbuf->data;
1031     buflen = pktbuf->len;
1032     while( buflen ) {
1033         n = *buffer++; buflen--;
1034         if( n == 255 ) { /* 4 byte length header */
1035             if( buflen < 4 )
1036                 goto too_short;
1037             n = (buffer[0] << 24) | (buffer[1] << 16)
1038                 | (buffer[2] << 8) | buffer[3];
1039             buffer += 4;
1040             buflen -= 4;
1041         }
1042         else if( n >= 192 ) { /* 2 byte special encoded length header */
1043             if( buflen < 2 )
1044                 goto too_short;
1045             n = (( n - 192 ) << 8) + *buffer + 192;
1046             buffer++;
1047             buflen--;
1048         }
1049         if( buflen < n )
1050             goto too_short;
1051         type = *buffer;
1052         if( type & 0x80 ) {
1053             type &= 0x7f;
1054             *critical = 1;
1055         }
1056         else
1057             *critical = 0;
1058         if( !(++seq > reqseq) )
1059             ;
1060         else if( reqtype == SIGSUBPKT_TEST_CRITICAL ) {
1061             if( *critical ) {
1062                 if( n-1 > buflen+1 )
1063                     goto too_short;
1064                 if( !can_handle_critical(buffer+1, n-1, type ) ) {
1065                     log_info(_("subpacket of type %d has critical bit set\n"),
1066                                                                         type);
1067                     if( start )
1068                         *start = seq;
1069                     return NULL; /* this is an error */
1070                 }
1071             }
1072         }
1073         else if( reqtype < 0 ) /* list packets */
1074             dump_sig_subpkt( reqtype == SIGSUBPKT_LIST_HASHED,
1075                                     type, *critical, buffer, buflen, n );
1076         else if( type == reqtype ) { /* found */
1077             buffer++;
1078             n--;
1079             if( n > buflen )
1080                 goto too_short;
1081             if( ret_n )
1082                 *ret_n = n;
1083             offset = parse_one_sig_subpkt(buffer, n, type );
1084             switch( offset ) {
1085               case -3:
1086                 log_error("subpacket of type %d too short\n", type);
1087                 return NULL;
1088               case -2:
1089                 return NULL;
1090               case -1:
1091                 BUG(); /* not yet needed */
1092               default:
1093                 break;
1094             }
1095             if( start )
1096                 *start = seq;
1097             return buffer+offset;
1098         }
1099         buffer += n; buflen -=n;
1100     }
1101     if( reqtype == SIGSUBPKT_TEST_CRITICAL )
1102         return buffer; /* as value true to indicate that there is no */
1103                        /* critical bit we don't understand */
1104     if( start )
1105         *start = -1;
1106     return NULL; /* end of packets; not found */
1107
1108   too_short:
1109     log_error("buffer shorter than subpacket\n");
1110     if( start )
1111         *start = -1;
1112     return NULL;
1113 }
1114
1115
1116 const byte *
1117 parse_sig_subpkt (const subpktarea_t *buffer, sigsubpkttype_t reqtype,
1118                   size_t *ret_n)
1119 {
1120     return enum_sig_subpkt( buffer, reqtype, ret_n, NULL, NULL );
1121 }
1122
1123 const byte *
1124 parse_sig_subpkt2 (PKT_signature *sig, sigsubpkttype_t reqtype,
1125                    size_t *ret_n )
1126 {
1127     const byte *p;
1128
1129     p = parse_sig_subpkt (sig->hashed, reqtype, ret_n );
1130     if( !p )
1131         p = parse_sig_subpkt (sig->unhashed, reqtype, ret_n );
1132     return p;
1133 }
1134
1135 /* Find all revocation keys. Look in hashed area only. */
1136 void parse_revkeys(PKT_signature *sig)
1137 {
1138   struct revocation_key *revkey;
1139   int seq=0;
1140   size_t len;
1141
1142   if(sig->sig_class!=0x1F)
1143     return;
1144
1145   while((revkey=
1146          (struct revocation_key *)enum_sig_subpkt(sig->hashed,
1147                                                   SIGSUBPKT_REV_KEY,
1148                                                   &len,&seq,NULL)))
1149     {
1150       if(len==sizeof(struct revocation_key) &&
1151          (revkey->class&0x80)) /* 0x80 bit must be set */
1152         {
1153           sig->revkey=m_realloc(sig->revkey,
1154                           sizeof(struct revocation_key *)*(sig->numrevkeys+1));
1155           sig->revkey[sig->numrevkeys]=revkey;
1156           sig->numrevkeys++;
1157         }
1158     }
1159 }
1160
1161 static int
1162 parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
1163                                           PKT_signature *sig )
1164 {
1165     int md5_len=0;
1166     unsigned n;
1167     int is_v4=0;
1168     int rc=0;
1169     int i, ndata;
1170
1171     if( pktlen < 16 ) {
1172         log_error("packet(%d) too short\n", pkttype);
1173         goto leave;
1174     }
1175     sig->version = iobuf_get_noeof(inp); pktlen--;
1176     if( sig->version == 4 )
1177         is_v4=1;
1178     else if( sig->version != 2 && sig->version != 3 ) {
1179         log_error("packet(%d) with unknown version %d\n", pkttype, sig->version);
1180         rc = G10ERR_INVALID_PACKET;
1181         goto leave;
1182     }
1183
1184     if( !is_v4 ) {
1185         md5_len = iobuf_get_noeof(inp); pktlen--;
1186     }
1187     sig->sig_class = iobuf_get_noeof(inp); pktlen--;
1188     if( !is_v4 ) {
1189         sig->timestamp = read_32(inp); pktlen -= 4;
1190         sig->keyid[0] = read_32(inp); pktlen -= 4;
1191         sig->keyid[1] = read_32(inp); pktlen -= 4;
1192     }
1193     sig->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
1194     sig->digest_algo = iobuf_get_noeof(inp); pktlen--;
1195     sig->flags.exportable=1;
1196     sig->flags.revocable=1;
1197     if( is_v4 ) { /* read subpackets */
1198         n = read_16(inp); pktlen -= 2; /* length of hashed data */
1199         if( n > 10000 ) {
1200             log_error("signature packet: hashed data too long\n");
1201             rc = G10ERR_INVALID_PACKET;
1202             goto leave;
1203         }
1204         if( n ) {
1205             sig->hashed = m_alloc (sizeof (*sig->hashed) + n - 1 );
1206             sig->hashed->size = n;
1207             sig->hashed->len = n;
1208             if( iobuf_read (inp, sig->hashed->data, n ) != n ) {
1209                 log_error ("premature eof while reading "
1210                            "hashed signature data\n");
1211                 rc = -1;
1212                 goto leave;
1213             }
1214             pktlen -= n;
1215         }
1216         n = read_16(inp); pktlen -= 2; /* length of unhashed data */
1217         if( n > 10000 ) {
1218             log_error("signature packet: unhashed data too long\n");
1219             rc = G10ERR_INVALID_PACKET;
1220             goto leave;
1221         }
1222         if( n ) {
1223             /* we add 8 extra bytes so that we have space for the signature
1224              * status cache.  Well we are wastin this if there is a cache
1225              * packet already, but in the other case it avoids an realloc */
1226             sig->unhashed = m_alloc (sizeof(*sig->unhashed) + n + 8 - 1 );
1227             sig->unhashed->size = n + 8;
1228             sig->unhashed->len = n;
1229             if( iobuf_read(inp, sig->unhashed->data, n ) != n ) {
1230                 log_error("premature eof while reading "
1231                           "unhashed signature data\n");
1232                 rc = -1;
1233                 goto leave;
1234             }
1235             pktlen -= n;
1236         }
1237     }
1238
1239     if( pktlen < 5 ) { /* sanity check */
1240         log_error("packet(%d) too short\n", pkttype);
1241         rc = G10ERR_INVALID_PACKET;
1242         goto leave;
1243     }
1244
1245     sig->digest_start[0] = iobuf_get_noeof(inp); pktlen--;
1246     sig->digest_start[1] = iobuf_get_noeof(inp); pktlen--;
1247
1248     if( is_v4 && sig->pubkey_algo ) { /*extract required information */
1249         const byte *p;
1250
1251         /* set sig->flags.unknown_critical if there is a
1252          * critical bit set for packets which we do not understand */
1253         if( !parse_sig_subpkt (sig->hashed, SIGSUBPKT_TEST_CRITICAL, NULL)
1254            || !parse_sig_subpkt (sig->unhashed, SIGSUBPKT_TEST_CRITICAL,
1255                                                                         NULL) )
1256         {
1257             sig->flags.unknown_critical = 1;
1258         }
1259
1260         p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIG_CREATED, NULL );
1261         if( !p )
1262             log_error("signature packet without timestamp\n");
1263         else
1264             sig->timestamp = buffer_to_u32(p);
1265         p = parse_sig_subpkt2( sig, SIGSUBPKT_ISSUER, NULL );
1266         if( !p )
1267             log_error("signature packet without keyid\n");
1268         else {
1269             sig->keyid[0] = buffer_to_u32(p);
1270             sig->keyid[1] = buffer_to_u32(p+4);
1271         }
1272
1273         p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_SIG_EXPIRE,NULL);
1274         if(p)
1275           sig->expiredate=sig->timestamp+buffer_to_u32(p);
1276         if(sig->expiredate && sig->expiredate<=make_timestamp())
1277             sig->flags.expired=1;
1278
1279         p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_POLICY,NULL);
1280         if(p)
1281           sig->flags.policy_url=1;
1282
1283         p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_NOTATION,NULL);
1284         if(p)
1285           sig->flags.notation=1;
1286
1287         p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_REVOCABLE,NULL);
1288         if(p && *p==0)
1289           sig->flags.revocable=0;
1290
1291         /* We accept the exportable subpacket from either the hashed
1292            or unhashed areas as older versions of gpg put it in the
1293            unhashed area.  In theory, anyway, we should never see this
1294            packet off of a local keyring. */
1295
1296         p=parse_sig_subpkt2(sig,SIGSUBPKT_EXPORTABLE,NULL);
1297         if(p && *p==0)
1298           sig->flags.exportable=0;
1299
1300         /* Find all revocation keys. */
1301         if(sig->sig_class==0x1F)
1302           parse_revkeys(sig);
1303     }
1304
1305     if( list_mode ) {
1306         printf(":signature packet: algo %d, keyid %08lX%08lX\n"
1307                "\tversion %d, created %lu, md5len %d, sigclass %02x\n"
1308                "\tdigest algo %d, begin of digest %02x %02x\n",
1309                 sig->pubkey_algo,
1310                 (ulong)sig->keyid[0], (ulong)sig->keyid[1],
1311                 sig->version, (ulong)sig->timestamp, md5_len, sig->sig_class,
1312                 sig->digest_algo,
1313                 sig->digest_start[0], sig->digest_start[1] );
1314         if( is_v4 ) {
1315             parse_sig_subpkt (sig->hashed,   SIGSUBPKT_LIST_HASHED, NULL );
1316             parse_sig_subpkt (sig->unhashed, SIGSUBPKT_LIST_UNHASHED, NULL);
1317         }
1318     }
1319
1320     ndata = pubkey_get_nsig(sig->pubkey_algo);
1321     if( !ndata ) {
1322         if( list_mode )
1323             printf("\tunknown algorithm %d\n", sig->pubkey_algo );
1324         unknown_pubkey_warning( sig->pubkey_algo );
1325         /* we store the plain material in data[0], so that we are able
1326          * to write it back with build_packet() */
1327         sig->data[0] = mpi_set_opaque(NULL, read_rest(inp, pktlen), pktlen );
1328         pktlen = 0;
1329     }
1330     else {
1331         for( i=0; i < ndata; i++ ) {
1332             n = pktlen;
1333             sig->data[i] = mpi_read(inp, &n, 0 );
1334             pktlen -=n;
1335             if( list_mode ) {
1336                 printf("\tdata: ");
1337                 mpi_print(stdout, sig->data[i], mpi_print_mode );
1338                 putchar('\n');
1339             }
1340             if (!sig->data[i])
1341                 rc = G10ERR_INVALID_PACKET;
1342         }
1343     }
1344
1345   leave:
1346     skip_rest(inp, pktlen);
1347     return rc;
1348 }
1349
1350
1351 static int
1352 parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
1353                                              PKT_onepass_sig *ops )
1354 {
1355     int version;
1356     int rc = 0;
1357
1358     if( pktlen < 13 ) {
1359         log_error("packet(%d) too short\n", pkttype);
1360         rc = G10ERR_INVALID_PACKET;
1361         goto leave;
1362     }
1363     version = iobuf_get_noeof(inp); pktlen--;
1364     if( version != 3 ) {
1365         log_error("onepass_sig with unknown version %d\n", version);
1366         rc = G10ERR_INVALID_PACKET;
1367         goto leave;
1368     }
1369     ops->sig_class = iobuf_get_noeof(inp); pktlen--;
1370     ops->digest_algo = iobuf_get_noeof(inp); pktlen--;
1371     ops->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
1372     ops->keyid[0] = read_32(inp); pktlen -= 4;
1373     ops->keyid[1] = read_32(inp); pktlen -= 4;
1374     ops->last = iobuf_get_noeof(inp); pktlen--;
1375     if( list_mode )
1376         printf(":onepass_sig packet: keyid %08lX%08lX\n"
1377                "\tversion %d, sigclass %02x, digest %d, pubkey %d, last=%d\n",
1378                 (ulong)ops->keyid[0], (ulong)ops->keyid[1],
1379                 version, ops->sig_class,
1380                 ops->digest_algo, ops->pubkey_algo, ops->last );
1381
1382
1383   leave:
1384     skip_rest(inp, pktlen);
1385     return rc;
1386 }
1387
1388
1389
1390
1391 static int
1392 parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
1393                               byte *hdr, int hdrlen, PACKET *pkt )
1394 {
1395     int i, version, algorithm;
1396     unsigned n;
1397     unsigned long timestamp, expiredate, max_expiredate;
1398     int npkey, nskey;
1399     int is_v4=0;
1400     int rc=0;
1401
1402     version = iobuf_get_noeof(inp); pktlen--;
1403     if( pkttype == PKT_PUBLIC_SUBKEY && version == '#' ) {
1404         /* early versions of G10 use old PGP comments packets;
1405          * luckily all those comments are started by a hash */
1406         if( list_mode ) {
1407             printf(":rfc1991 comment packet: \"" );
1408             for( ; pktlen; pktlen-- ) {
1409                 int c;
1410                 c = iobuf_get_noeof(inp);
1411                 if( c >= ' ' && c <= 'z' )
1412                     putchar(c);
1413                 else
1414                     printf("\\x%02x", c );
1415             }
1416             printf("\"\n");
1417         }
1418         skip_rest(inp, pktlen);
1419         return 0;
1420     }
1421     else if( version == 4 )
1422         is_v4=1;
1423     else if( version != 2 && version != 3 ) {
1424         log_error("packet(%d) with unknown version %d\n", pkttype, version);
1425         rc = G10ERR_INVALID_PACKET;
1426         goto leave;
1427     }
1428
1429     if( pktlen < 11 ) {
1430         log_error("packet(%d) too short\n", pkttype);
1431         rc = G10ERR_INVALID_PACKET;
1432         goto leave;
1433     }
1434
1435     timestamp = read_32(inp); pktlen -= 4;
1436     if( is_v4 ) {
1437         expiredate = 0; /* have to get it from the selfsignature */
1438         max_expiredate = 0;
1439     }
1440     else {
1441         unsigned short ndays;
1442         ndays = read_16(inp); pktlen -= 2;
1443         if( ndays )
1444             expiredate = timestamp + ndays * 86400L;
1445         else
1446             expiredate = 0;
1447
1448         max_expiredate=expiredate;
1449     }
1450     algorithm = iobuf_get_noeof(inp); pktlen--;
1451     if( list_mode )
1452         printf(":%s key packet:\n"
1453                "\tversion %d, algo %d, created %lu, expires %lu\n",
1454                 pkttype == PKT_PUBLIC_KEY? "public" :
1455                 pkttype == PKT_SECRET_KEY? "secret" :
1456                 pkttype == PKT_PUBLIC_SUBKEY? "public sub" :
1457                 pkttype == PKT_SECRET_SUBKEY? "secret sub" : "??",
1458                 version, algorithm, timestamp, expiredate );
1459
1460     if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY )  {
1461         PKT_secret_key *sk = pkt->pkt.secret_key;
1462
1463         sk->timestamp = timestamp;
1464         sk->expiredate = expiredate;
1465         sk->max_expiredate = max_expiredate;
1466         sk->hdrbytes = hdrlen;
1467         sk->version = version;
1468         sk->is_primary = pkttype == PKT_SECRET_KEY;
1469         sk->pubkey_algo = algorithm;
1470         sk->req_usage = 0; 
1471         sk->pubkey_usage = 0; /* not yet used */
1472     }
1473     else {
1474         PKT_public_key *pk = pkt->pkt.public_key;
1475
1476         pk->timestamp = timestamp;
1477         pk->expiredate = expiredate;
1478         pk->max_expiredate = max_expiredate;
1479         pk->hdrbytes    = hdrlen;
1480         pk->version     = version;
1481         pk->pubkey_algo = algorithm;
1482         pk->req_usage = 0; 
1483         pk->pubkey_usage = 0; /* not yet used */
1484         pk->is_revoked = 0;
1485         pk->keyid[0] = 0;
1486         pk->keyid[1] = 0;
1487     }
1488     nskey = pubkey_get_nskey( algorithm );
1489     npkey = pubkey_get_npkey( algorithm );
1490     if( !npkey ) {
1491         if( list_mode )
1492             printf("\tunknown algorithm %d\n", algorithm );
1493         unknown_pubkey_warning( algorithm );
1494     }
1495
1496
1497     if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) {
1498         PKT_secret_key *sk = pkt->pkt.secret_key;
1499         byte temp[16];
1500
1501         if( !npkey ) {
1502             sk->skey[0] = mpi_set_opaque( NULL,
1503                                           read_rest(inp, pktlen), pktlen );
1504             pktlen = 0;
1505             goto leave;
1506         }
1507
1508         for(i=0; i < npkey; i++ ) {
1509             n = pktlen; sk->skey[i] = mpi_read(inp, &n, 0 ); pktlen -=n;
1510             if( list_mode ) {
1511                 printf(  "\tskey[%d]: ", i);
1512                 mpi_print(stdout, sk->skey[i], mpi_print_mode  );
1513                 putchar('\n');
1514             }
1515             if (!sk->skey[i])
1516                 rc = G10ERR_INVALID_PACKET;
1517         }
1518         if (rc) /* one of the MPIs were bad */
1519             goto leave;
1520         sk->protect.algo = iobuf_get_noeof(inp); pktlen--;
1521         sk->protect.sha1chk = 0;
1522         if( sk->protect.algo ) {
1523             sk->is_protected = 1;
1524             sk->protect.s2k.count = 0;
1525             if( sk->protect.algo == 254 || sk->protect.algo == 255 ) {
1526                 if( pktlen < 3 ) {
1527                     rc = G10ERR_INVALID_PACKET;
1528                     goto leave;
1529                 }
1530                 sk->protect.sha1chk = (sk->protect.algo == 254);
1531                 sk->protect.algo = iobuf_get_noeof(inp); pktlen--;
1532                 sk->protect.s2k.mode  = iobuf_get_noeof(inp); pktlen--;
1533                 sk->protect.s2k.hash_algo = iobuf_get_noeof(inp); pktlen--;
1534                 /* check for the special GNU extension */
1535                 if( is_v4 && sk->protect.s2k.mode == 101 ) {
1536                     for(i=0; i < 4 && pktlen; i++, pktlen-- )
1537                         temp[i] = iobuf_get_noeof(inp);
1538                     if( i < 4 || memcmp( temp, "GNU", 3 ) ) {
1539                         if( list_mode )
1540                             printf(  "\tunknown S2K %d\n",
1541                                                 sk->protect.s2k.mode );
1542                         rc = G10ERR_INVALID_PACKET;
1543                         goto leave;
1544                     }
1545                     /* here we know that it is a gnu extension
1546                      * What follows is the GNU protection mode:
1547                      * All values have special meanings
1548                      * and they are mapped in the mode with a base of 1000.
1549                      */
1550                     sk->protect.s2k.mode = 1000 + temp[3];
1551                 }
1552                 switch( sk->protect.s2k.mode ) {
1553                   case 1:
1554                   case 3:
1555                     for(i=0; i < 8 && pktlen; i++, pktlen-- )
1556                         temp[i] = iobuf_get_noeof(inp);
1557                     memcpy(sk->protect.s2k.salt, temp, 8 );
1558                     break;
1559                 }
1560                 switch( sk->protect.s2k.mode ) {
1561                   case 0: if( list_mode ) printf(  "\tsimple S2K" );
1562                     break;
1563                   case 1: if( list_mode ) printf(  "\tsalted S2K" );
1564                     break;
1565                   case 3: if( list_mode ) printf(  "\titer+salt S2K" );
1566                     break;
1567                   case 1001: if( list_mode ) printf(  "\tgnu-dummy S2K" );
1568                     break;
1569                   default:
1570                     if( list_mode )
1571                         printf(  "\tunknown %sS2K %d\n",
1572                                  sk->protect.s2k.mode < 1000? "":"GNU ",
1573                                                    sk->protect.s2k.mode );
1574                     rc = G10ERR_INVALID_PACKET;
1575                     goto leave;
1576                 }
1577
1578                 if( list_mode ) {
1579                     printf(", algo: %d,%s hash: %d",
1580                                      sk->protect.algo,
1581                                      sk->protect.sha1chk?" SHA1 protection,"
1582                                                         :" simple checksum,",
1583                                      sk->protect.s2k.hash_algo );
1584                     if( sk->protect.s2k.mode == 1
1585                         || sk->protect.s2k.mode == 3 ) {
1586                         printf(", salt: ");
1587                         for(i=0; i < 8; i++ )
1588                             printf("%02x", sk->protect.s2k.salt[i]);
1589                     }
1590                     putchar('\n');
1591                 }
1592
1593                 if( sk->protect.s2k.mode == 3 ) {
1594                     if( pktlen < 1 ) {
1595                         rc = G10ERR_INVALID_PACKET;
1596                         goto leave;
1597                     }
1598                     sk->protect.s2k.count = iobuf_get(inp);
1599                     pktlen--;
1600                     if( list_mode )
1601                         printf("\tprotect count: %lu\n",
1602                                             (ulong)sk->protect.s2k.count);
1603                 }
1604             }
1605             else { /* old version; no S2K, so we set mode to 0, hash MD5 */
1606                 sk->protect.s2k.mode = 0;
1607                 sk->protect.s2k.hash_algo = DIGEST_ALGO_MD5;
1608                 if( list_mode )
1609                     printf(  "\tprotect algo: %d  (hash algo: %d)\n",
1610                          sk->protect.algo, sk->protect.s2k.hash_algo );
1611             }
1612             /* It is really ugly that we don't know the size
1613              * of the IV here in cases we are not aware of the algorithm.
1614              * so a
1615              *   sk->protect.ivlen = cipher_get_blocksize(sk->protect.algo);
1616              * won't work.  The only solution I see is to hardwire it here.
1617              * NOTE: if you change the ivlen above 16, don't forget to
1618              * enlarge temp.
1619              */
1620             switch( sk->protect.algo ) {
1621               case 7: case 8: case 9: /* reserved for AES */
1622               case 10: /* Twofish */
1623                 sk->protect.ivlen = 16;
1624                 break;
1625               default:
1626                 sk->protect.ivlen = 8;
1627             }
1628             if( sk->protect.s2k.mode == 1001 )
1629                 sk->protect.ivlen = 0;
1630
1631             if( pktlen < sk->protect.ivlen ) {
1632                 rc = G10ERR_INVALID_PACKET;
1633                 goto leave;
1634             }
1635             for(i=0; i < sk->protect.ivlen && pktlen; i++, pktlen-- )
1636                 temp[i] = iobuf_get_noeof(inp);
1637             if( list_mode ) {
1638                 printf(  "\tprotect IV: ");
1639                 for(i=0; i < sk->protect.ivlen; i++ )
1640                     printf(" %02x", temp[i] );
1641                 putchar('\n');
1642             }
1643             memcpy(sk->protect.iv, temp, sk->protect.ivlen );
1644         }
1645         else
1646             sk->is_protected = 0;
1647         /* It does not make sense to read it into secure memory.
1648          * If the user is so careless, not to protect his secret key,
1649          * we can assume, that he operates an open system :=(.
1650          * So we put the key into secure memory when we unprotect it. */
1651         if( sk->protect.s2k.mode == 1001 ) {
1652             /* better set some dummy stuff here */
1653             sk->skey[npkey] = mpi_set_opaque(NULL, m_strdup("dummydata"), 10);
1654             pktlen = 0;
1655         }
1656         else if( is_v4 && sk->is_protected ) {
1657             /* ugly; the length is encrypted too, so we read all
1658              * stuff up to the end of the packet into the first
1659              * skey element */
1660             sk->skey[npkey] = mpi_set_opaque(NULL,
1661                                              read_rest(inp, pktlen), pktlen );
1662             pktlen = 0;
1663             if( list_mode ) {
1664                 printf("\tencrypted stuff follows\n");
1665             }
1666         }
1667         else { /* v3 method: the mpi length is not encrypted */
1668             for(i=npkey; i < nskey; i++ ) {
1669                 n = pktlen; sk->skey[i] = mpi_read(inp, &n, 0 ); pktlen -=n;
1670                 if( sk->is_protected && sk->skey[i] )
1671                     mpi_set_protect_flag(sk->skey[i]);
1672                 if( list_mode ) {
1673                     printf(  "\tskey[%d]: ", i);
1674                     if( sk->is_protected )
1675                         printf(  "[encrypted]\n");
1676                     else {
1677                         mpi_print(stdout, sk->skey[i], mpi_print_mode  );
1678                         putchar('\n');
1679                     }
1680                 }
1681                 if (!sk->skey[i])
1682                     rc = G10ERR_INVALID_PACKET;
1683             }
1684             if (rc)
1685                 goto leave;
1686
1687             sk->csum = read_16(inp); pktlen -= 2;
1688             if( list_mode ) {
1689                 printf("\tchecksum: %04hx\n", sk->csum);
1690             }
1691         }
1692     }
1693     else {
1694         PKT_public_key *pk = pkt->pkt.public_key;
1695
1696         if( !npkey ) {
1697             pk->pkey[0] = mpi_set_opaque( NULL,
1698                                           read_rest(inp, pktlen), pktlen );
1699             pktlen = 0;
1700             goto leave;
1701         }
1702
1703         for(i=0; i < npkey; i++ ) {
1704             n = pktlen; pk->pkey[i] = mpi_read(inp, &n, 0 ); pktlen -=n;
1705             if( list_mode ) {
1706                 printf(  "\tpkey[%d]: ", i);
1707                 mpi_print(stdout, pk->pkey[i], mpi_print_mode  );
1708                 putchar('\n');
1709             }
1710             if (!pk->pkey[i])
1711                 rc = G10ERR_INVALID_PACKET;
1712         }
1713         if (rc)
1714             goto leave;
1715     }
1716
1717   leave:
1718     skip_rest(inp, pktlen);
1719     return rc;
1720 }
1721
1722 /* Attribute subpackets have the same format as v4 signature
1723    subpackets.  This is not part of OpenPGP, but is done in several
1724    versions of PGP nevertheless. */
1725 int
1726 parse_attribute_subpkts(PKT_user_id *uid)
1727 {
1728   size_t n;
1729   int count=0;
1730   struct user_attribute *attribs=NULL;
1731   const byte *buffer=uid->attrib_data;
1732   int buflen=uid->attrib_len;
1733   byte type;
1734
1735   m_free(uid->attribs);
1736
1737   while(buflen)
1738     {
1739       n = *buffer++; buflen--;
1740       if( n == 255 ) { /* 4 byte length header */
1741         if( buflen < 4 )
1742           goto too_short;
1743         n = (buffer[0] << 24) | (buffer[1] << 16)
1744           | (buffer[2] << 8) | buffer[3];
1745         buffer += 4;
1746         buflen -= 4;
1747       }
1748       else if( n >= 192 ) { /* 2 byte special encoded length header */
1749         if( buflen < 2 )
1750           goto too_short;
1751         n = (( n - 192 ) << 8) + *buffer + 192;
1752         buffer++;
1753         buflen--;
1754       }
1755       if( buflen < n )
1756         goto too_short;
1757
1758       attribs=m_realloc(attribs,(count+1)*sizeof(struct user_attribute));
1759       memset(&attribs[count],0,sizeof(struct user_attribute));
1760
1761       type=*buffer;
1762       buffer++;
1763       buflen--;
1764       n--;
1765
1766       attribs[count].type=type;
1767       attribs[count].data=buffer;
1768       attribs[count].len=n;
1769       buffer+=n;
1770       buflen-=n;
1771       count++;
1772     }
1773
1774   uid->attribs=attribs;
1775   uid->numattribs=count;
1776   return count;
1777
1778  too_short:
1779   log_error("buffer shorter than attribute subpacket\n");
1780   uid->attribs=attribs;
1781   uid->numattribs=count;
1782   return count;
1783 }
1784
1785 static void setup_user_id(PACKET *packet)
1786 {
1787   packet->pkt.user_id->ref = 1;
1788   packet->pkt.user_id->attribs = NULL;
1789   packet->pkt.user_id->attrib_data = NULL;
1790   packet->pkt.user_id->attrib_len = 0;
1791   packet->pkt.user_id->is_primary = 0;
1792   packet->pkt.user_id->is_revoked = 0;
1793   packet->pkt.user_id->is_expired = 0;
1794   packet->pkt.user_id->expiredate = 0;
1795   packet->pkt.user_id->created = 0;
1796   packet->pkt.user_id->help_key_usage = 0;
1797   packet->pkt.user_id->help_key_expire = 0;
1798   packet->pkt.user_id->prefs = NULL;
1799 }
1800
1801 static int
1802 parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
1803 {
1804     byte *p;
1805
1806     packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id  + pktlen);
1807     packet->pkt.user_id->len = pktlen;
1808
1809     setup_user_id(packet);
1810
1811     p = packet->pkt.user_id->name;
1812     for( ; pktlen; pktlen--, p++ )
1813         *p = iobuf_get_noeof(inp);
1814     *p = 0;
1815
1816     if( list_mode ) {
1817         int n = packet->pkt.user_id->len;
1818         printf(":user ID packet: \"");
1819         /* fixme: Hey why don't we replace this with print_string?? */
1820         for(p=packet->pkt.user_id->name; n; p++, n-- ) {
1821             if( *p >= ' ' && *p <= 'z' )
1822                 putchar(*p);
1823             else
1824                 printf("\\x%02x", *p );
1825         }
1826         printf("\"\n");
1827     }
1828     return 0;
1829 }
1830
1831
1832 void
1833 make_attribute_uidname(PKT_user_id *uid, size_t max_namelen)
1834 {
1835   assert ( max_namelen > 70 );
1836   if(uid->numattribs<=0)
1837     sprintf(uid->name,"[bad attribute packet of size %lu]",uid->attrib_len);
1838   else if(uid->numattribs>1)
1839     sprintf(uid->name,"[%d attributes of size %lu]",
1840             uid->numattribs,uid->attrib_len);
1841   else
1842     {
1843       /* Only one attribute, so list it as the "user id" */
1844
1845       if(uid->attribs->type==ATTRIB_IMAGE)
1846         {
1847           u32 len;
1848           byte type;
1849
1850           if(parse_image_header(uid->attribs,&type,&len))
1851             sprintf(uid->name,"[%.20s image of size %lu]",
1852                     image_type_to_string(type,1),(ulong)len);
1853           else
1854             sprintf(uid->name,"[invalid image]");
1855         }
1856       else
1857         sprintf(uid->name,"[unknown attribute of size %lu]",
1858                 (ulong)uid->attribs->len);
1859     }
1860
1861   uid->len = strlen(uid->name);
1862 }
1863
1864 static int
1865 parse_attribute( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
1866 {
1867     byte *p;
1868
1869 #define EXTRA_UID_NAME_SPACE 71
1870     packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id
1871                                   + EXTRA_UID_NAME_SPACE);
1872
1873     setup_user_id(packet);
1874
1875     packet->pkt.user_id->attrib_data = m_alloc(pktlen);
1876     packet->pkt.user_id->attrib_len = pktlen;
1877     p = packet->pkt.user_id->attrib_data;
1878     for( ; pktlen; pktlen--, p++ )
1879         *p = iobuf_get_noeof(inp);
1880
1881     /* Now parse out the individual attribute subpackets.  This is
1882        somewhat pointless since there is only one currently defined
1883        attribute type (jpeg), but it is correct by the spec. */
1884     parse_attribute_subpkts(packet->pkt.user_id);
1885
1886     make_attribute_uidname(packet->pkt.user_id, EXTRA_UID_NAME_SPACE);
1887
1888     if( list_mode ) {
1889         printf(":attribute packet: %s\n", packet->pkt.user_id->name );
1890     }
1891     return 0;
1892 }
1893
1894
1895 static int
1896 parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
1897 {
1898     byte *p;
1899
1900     packet->pkt.comment = m_alloc(sizeof *packet->pkt.comment + pktlen - 1);
1901     packet->pkt.comment->len = pktlen;
1902     p = packet->pkt.comment->data;
1903     for( ; pktlen; pktlen--, p++ )
1904         *p = iobuf_get_noeof(inp);
1905
1906     if( list_mode ) {
1907         int n = packet->pkt.comment->len;
1908         printf(":%scomment packet: \"", pkttype == PKT_OLD_COMMENT?
1909                                          "OpenPGP draft " : "" );
1910         for(p=packet->pkt.comment->data; n; p++, n-- ) {
1911             if( *p >= ' ' && *p <= 'z' )
1912                 putchar(*p);
1913             else
1914                 printf("\\x%02x", *p );
1915         }
1916         printf("\"\n");
1917     }
1918     return 0;
1919 }
1920
1921
1922 static void
1923 parse_trust( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
1924 {
1925   int c;
1926
1927   if (pktlen)
1928     {
1929       c = iobuf_get_noeof(inp);
1930       pktlen--;
1931       pkt->pkt.ring_trust = m_alloc( sizeof *pkt->pkt.ring_trust );
1932       pkt->pkt.ring_trust->trustval = c;
1933       pkt->pkt.ring_trust->sigcache = 0;
1934       if (!c && pktlen==1)
1935         {
1936           c = iobuf_get_noeof (inp);
1937           pktlen--;
1938           /* we require that bit 7 of the sigcache is 0 (easier eof handling)*/
1939           if ( !(c & 0x80) )
1940             pkt->pkt.ring_trust->sigcache = c;
1941         }
1942       if( list_mode )
1943         printf(":trust packet: flag=%02x sigcache=%02x\n",
1944                pkt->pkt.ring_trust->trustval,
1945                pkt->pkt.ring_trust->sigcache);
1946     }
1947   else
1948     {
1949       if( list_mode )
1950         printf(":trust packet: empty\n");
1951     }
1952   skip_rest (inp, pktlen);
1953 }
1954
1955
1956 static int
1957 parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
1958                                         PACKET *pkt, int new_ctb )
1959 {
1960     int rc = 0;
1961     int mode, namelen, partial=0;
1962     PKT_plaintext *pt;
1963     byte *p;
1964     int c, i;
1965
1966     if( pktlen && pktlen < 6 ) {
1967         log_error("packet(%d) too short (%lu)\n", pkttype, (ulong)pktlen);
1968         rc = G10ERR_INVALID_PACKET;
1969         goto leave;
1970     }
1971     /* A packet length of zero indicates partial body length.  A zero
1972        data length isn't a zero length packet due to the header (mode,
1973        name, etc), so this is accurate. */
1974     if(pktlen==0)
1975       partial=1;
1976     mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
1977     namelen = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
1978     pt = pkt->pkt.plaintext = m_alloc(sizeof *pkt->pkt.plaintext + namelen -1);
1979     pt->new_ctb = new_ctb;
1980     pt->mode = mode;
1981     pt->namelen = namelen;
1982     pt->is_partial = partial;
1983     if( pktlen ) {
1984         for( i=0; pktlen > 4 && i < namelen; pktlen--, i++ )
1985             pt->name[i] = iobuf_get_noeof(inp);
1986     }
1987     else {
1988         for( i=0; i < namelen; i++ )
1989             if( (c=iobuf_get(inp)) == -1 )
1990                 break;
1991             else
1992                 pt->name[i] = c;
1993     }
1994     pt->timestamp = read_32(inp); if( pktlen) pktlen -= 4;
1995     pt->len = pktlen;
1996     pt->buf = inp;
1997     pktlen = 0;
1998
1999     if( list_mode ) {
2000         printf(":literal data packet:\n"
2001                "\tmode %c, created %lu, name=\"",
2002                     mode >= ' ' && mode <'z'? mode : '?',
2003                     (ulong)pt->timestamp );
2004         for(p=pt->name,i=0; i < namelen; p++, i++ ) {
2005             if( *p >= ' ' && *p <= 'z' )
2006                 putchar(*p);
2007             else
2008                 printf("\\x%02x", *p );
2009         }
2010         printf("\",\n\traw data: %lu bytes\n", (ulong)pt->len );
2011     }
2012
2013   leave:
2014     return rc;
2015 }
2016
2017
2018 static int
2019 parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
2020                   PACKET *pkt, int new_ctb )
2021 {
2022     PKT_compressed *zd;
2023
2024     /* pktlen is here 0, but data follows
2025      * (this should be the last object in a file or
2026      *  the compress algorithm should know the length)
2027      */
2028     zd = pkt->pkt.compressed =  m_alloc(sizeof *pkt->pkt.compressed );
2029     zd->algorithm = iobuf_get_noeof(inp);
2030     zd->len = 0; /* not used */ 
2031     zd->new_ctb = new_ctb;
2032     zd->buf = inp;
2033     if( list_mode )
2034         printf(":compressed packet: algo=%d\n", zd->algorithm);
2035     return 0;
2036 }
2037
2038
2039 static int
2040 parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
2041                                        PACKET *pkt, int new_ctb )
2042 {
2043     int rc = 0;
2044     PKT_encrypted *ed;
2045     unsigned long orig_pktlen = pktlen;
2046
2047     ed = pkt->pkt.encrypted =  m_alloc(sizeof *pkt->pkt.encrypted );
2048     ed->len = pktlen;
2049     /* we don't know the extralen which is (cipher_blocksize+2)
2050        because the algorithm ist not specified in this packet.
2051        However, it is only important to know this for some sanity
2052        checks on the packet length - it doesn't matter that we can't
2053        do it */
2054     ed->extralen = 0;
2055     ed->buf = NULL;
2056     ed->new_ctb = new_ctb;
2057     ed->mdc_method = 0;
2058     if( pkttype == PKT_ENCRYPTED_MDC ) {
2059         /* fixme: add some pktlen sanity checks */
2060         int version;
2061
2062         version = iobuf_get_noeof(inp); 
2063         if (orig_pktlen)
2064             pktlen--;
2065         if( version != 1 ) {
2066             log_error("encrypted_mdc packet with unknown version %d\n",
2067                                                                 version);
2068             /*skip_rest(inp, pktlen); should we really do this? */
2069             rc = G10ERR_INVALID_PACKET;
2070             goto leave;
2071         }
2072         ed->mdc_method = DIGEST_ALGO_SHA1;
2073     }
2074     if( orig_pktlen && pktlen < 10 ) { /* actually this is blocksize+2 */
2075         log_error("packet(%d) too short\n", pkttype);
2076         rc = G10ERR_INVALID_PACKET;
2077         skip_rest(inp, pktlen);
2078         goto leave;
2079     }
2080     if( list_mode ) {
2081         if( orig_pktlen )
2082             printf(":encrypted data packet:\n\tlength: %lu\n", orig_pktlen);
2083         else
2084             printf(":encrypted data packet:\n\tlength: unknown\n");
2085         if( ed->mdc_method )
2086             printf("\tmdc_method: %d\n", ed->mdc_method );
2087     }
2088
2089     ed->buf = inp;
2090     pktlen = 0;
2091
2092   leave:
2093     return rc;
2094 }
2095
2096
2097 static int
2098 parse_mdc( IOBUF inp, int pkttype, unsigned long pktlen,
2099                                    PACKET *pkt, int new_ctb )
2100 {
2101     int rc = 0;
2102     PKT_mdc *mdc;
2103     byte *p;
2104
2105     mdc = pkt->pkt.mdc=  m_alloc(sizeof *pkt->pkt.mdc );
2106     if( list_mode )
2107         printf(":mdc packet: length=%lu\n", pktlen);
2108     if( !new_ctb || pktlen != 20 ) {
2109         log_error("mdc_packet with invalid encoding\n");
2110         rc = G10ERR_INVALID_PACKET;
2111         goto leave;
2112     }
2113     p = mdc->hash;
2114     for( ; pktlen; pktlen--, p++ )
2115         *p = iobuf_get_noeof(inp);
2116
2117   leave:
2118     return rc;
2119 }
2120
2121
2122 /*
2123  * This packet is internally generated by PGG (by armor.c) to
2124  * transfer some information to the lower layer.  To make sure that
2125  * this packet is really a GPG faked one and not one comming from outside,
2126  * we first check that tehre is a unique tag in it.
2127  * The format of such a control packet is:
2128  *   n byte  session marker
2129  *   1 byte  control type CTRLPKT_xxxxx
2130  *   m byte  control data
2131  */
2132
2133 static int
2134 parse_gpg_control( IOBUF inp,
2135                    int pkttype, unsigned long pktlen, PACKET *packet )
2136 {
2137     byte *p;
2138     const byte *sesmark;
2139     size_t sesmarklen;
2140     int i;
2141
2142     if ( list_mode )
2143         printf(":packet 63: length %lu ",  pktlen);
2144
2145     sesmark = get_session_marker ( &sesmarklen );
2146     if ( pktlen < sesmarklen+1 ) /* 1 is for the control bytes */
2147         goto skipit;
2148     for( i=0; i < sesmarklen; i++, pktlen-- ) {
2149         if ( sesmark[i] != iobuf_get_noeof(inp) )
2150             goto skipit;
2151     }
2152     if ( list_mode )
2153         puts ("- gpg control packet");
2154
2155     packet->pkt.gpg_control = m_alloc(sizeof *packet->pkt.gpg_control
2156                                       + pktlen - 1);
2157     packet->pkt.gpg_control->control = iobuf_get_noeof(inp); pktlen--;
2158     packet->pkt.gpg_control->datalen = pktlen;
2159     p = packet->pkt.gpg_control->data;
2160     for( ; pktlen; pktlen--, p++ )
2161         *p = iobuf_get_noeof(inp);
2162
2163     return 0;
2164
2165  skipit:
2166     if ( list_mode ) {
2167         int c;
2168
2169         i=0;
2170         printf("- private (rest length %lu)\n",  pktlen);
2171         if( iobuf_in_block_mode(inp) ) {
2172             while( (c=iobuf_get(inp)) != -1 )
2173                 dump_hex_line(c, &i);
2174         }
2175         else {
2176             for( ; pktlen; pktlen-- )
2177                 dump_hex_line(iobuf_get(inp), &i);
2178         }
2179         putchar('\n');
2180     }
2181     skip_rest(inp,pktlen);
2182     return G10ERR_INVALID_PACKET;
2183 }
2184
2185 /* create a gpg control packet to be used internally as a placeholder */
2186 PACKET *
2187 create_gpg_control( ctrlpkttype_t type, const byte *data, size_t datalen )
2188 {
2189     PACKET *packet;
2190     byte *p;
2191
2192     packet = m_alloc( sizeof *packet );
2193     init_packet(packet);
2194     packet->pkttype = PKT_GPG_CONTROL;
2195     packet->pkt.gpg_control = m_alloc(sizeof *packet->pkt.gpg_control
2196                                       + datalen - 1);
2197     packet->pkt.gpg_control->control = type;
2198     packet->pkt.gpg_control->datalen = datalen;
2199     p = packet->pkt.gpg_control->data;
2200     for( ; datalen; datalen--, p++ )
2201         *p = *data++;
2202
2203     return packet;
2204 }