0ee6e7d37be4cb9db2472b98ba19622da926d6ff
[gnupg.git] / g10 / parse-packet.c
1 /* parse-packet.c  - read packets
2  *      Copyright (C) 1998 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 "options.h"
35
36 static int mpi_print_mode = 0;
37 static int list_mode = 0;
38
39 static int  parse( IOBUF inp, PACKET *pkt, int reqtype,
40                    ulong *retpos, int *skip, IOBUF out, int do_skip );
41 static int  copy_packet( IOBUF inp, IOBUF out, int pkttype,
42                                                unsigned long pktlen );
43 static void skip_packet( IOBUF inp, int pkttype, unsigned long pktlen );
44 static void skip_rest( IOBUF inp, unsigned long pktlen );
45 static int  parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen,
46                                                              PACKET *packet );
47 static int  parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen,
48                                                              PACKET *packet );
49 static int  parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
50                                                          PKT_signature *sig );
51 static int  parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
52                                                         PKT_onepass_sig *ops );
53 static int  parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
54                                       byte *hdr, int hdrlen, PACKET *packet );
55 static int  parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen,
56                                                            PACKET *packet );
57 static int  parse_comment( IOBUF inp, int pkttype, unsigned long pktlen,
58                                                            PACKET *packet );
59 static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen );
60 static int  parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
61                                                                 PACKET *pkt );
62 static int  parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
63                                                            PACKET *packet );
64 static int  parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
65                                                            PACKET *packet );
66
67 static unsigned short
68 read_16(IOBUF inp)
69 {
70     unsigned short a;
71     a = iobuf_get_noeof(inp) << 8;
72     a |= iobuf_get_noeof(inp);
73     return a;
74 }
75
76 static unsigned long
77 read_32(IOBUF inp)
78 {
79     unsigned long a;
80     a =  iobuf_get_noeof(inp) << 24;
81     a |= iobuf_get_noeof(inp) << 16;
82     a |= iobuf_get_noeof(inp) << 8;
83     a |= iobuf_get_noeof(inp);
84     return a;
85 }
86
87 static unsigned long
88 buffer_to_u32( const byte *buffer )
89 {
90     unsigned long a;
91     a =  *buffer << 24;
92     a |= buffer[1] << 16;
93     a |= buffer[2] << 8;
94     a |= buffer[3];
95     return a;
96 }
97
98 int
99 set_packet_list_mode( int mode )
100 {
101     int old = list_mode;
102     list_mode = mode;
103     mpi_print_mode = DBG_MPI;
104     return old;
105 }
106
107 /****************
108  * Parse a Packet and return it in packet
109  * Returns: 0 := valid packet in pkt
110  *         -1 := no more packets
111  *         >0 := error
112  * Note: The function may return an error and a partly valid packet;
113  * caller must free this packet.
114  */
115 int
116 parse_packet( IOBUF inp, PACKET *pkt )
117 {
118     int skip, rc;
119
120     do {
121         rc = parse( inp, pkt, 0, NULL, &skip, NULL, 0 );
122     } while( skip );
123     return rc;
124 }
125
126 /****************
127  * Like parse packet, but only return packets of the given type.
128  */
129 int
130 search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos )
131 {
132     int skip, rc;
133
134     do {
135         rc = parse( inp, pkt, pkttype, retpos, &skip, NULL, 0 );
136     } while( skip );
137     return rc;
138 }
139
140 /****************
141  * Copy all packets from INP to OUT, thereby removing unused spaces.
142  */
143 int
144 copy_all_packets( IOBUF inp, IOBUF out )
145 {
146     PACKET pkt;
147     int skip, rc=0;
148     do {
149         init_packet(&pkt);
150     } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0 )));
151     return rc;
152 }
153
154 /****************
155  * Copy some packets from INP to OUT, thereby removing unused spaces.
156  * Stop at offset STOPoff (i.e. don't copy packets at this or later offsets)
157  */
158 int
159 copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff )
160 {
161     PACKET pkt;
162     int skip, rc=0;
163     do {
164         if( iobuf_tell(inp) >= stopoff )
165             return 0;
166         init_packet(&pkt);
167     } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0 )) );
168     return rc;
169 }
170
171 /****************
172  * Skip over N packets
173  */
174 int
175 skip_some_packets( IOBUF inp, unsigned n )
176 {
177     int skip, rc=0;
178     PACKET pkt;
179
180     for( ;n && !rc; n--) {
181         init_packet(&pkt);
182         rc = parse( inp, &pkt, 0, NULL, &skip, NULL, 1 );
183     }
184     return rc;
185 }
186
187 /****************
188  * Parse packet. Set the variable skip points to to 1 if the packet
189  * should be skipped; this is the case if either there is a
190  * requested packet type and the parsed packet doesn't match or the
191  * packet-type is 0, indicating deleted stuff.
192  * if OUT is not NULL, a special copymode is used.
193  */
194 static int
195 parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos,
196        int *skip, IOBUF out, int do_skip )
197 {
198     int rc, c, ctb, pkttype, lenbytes;
199     unsigned long pktlen;
200     byte hdr[8];
201     int hdrlen;
202     int pgp3 = 0;
203
204     *skip = 0;
205     assert( !pkt->pkt.generic );
206     if( retpos )
207         *retpos = iobuf_tell(inp);
208     if( (ctb = iobuf_get(inp)) == -1 )
209         return -1;
210     hdrlen=0;
211     hdr[hdrlen++] = ctb;
212     if( !(ctb & 0x80) ) {
213         log_error("%s: invalid packet (ctb=%02x)\n", iobuf_where(inp), ctb );
214         return G10ERR_INVALID_PACKET;
215     }
216     pktlen = 0;
217     pgp3 = !!(ctb & 0x40);
218     if( pgp3 ) {
219         pkttype =  ctb & 0x3f;
220         if( (c = iobuf_get(inp)) == -1 ) {
221             log_error("%s: 1st length byte missing\n", iobuf_where(inp) );
222             return G10ERR_INVALID_PACKET;
223         }
224         hdr[hdrlen++] = c;
225         if( c < 192 )
226             pktlen = c;
227         else if( c < 224 ) {
228             pktlen = (c - 192) * 256;
229             if( (c = iobuf_get(inp)) == -1 ) {
230                 log_error("%s: 2nd length byte missing\n", iobuf_where(inp) );
231                 return G10ERR_INVALID_PACKET;
232             }
233             hdr[hdrlen++] = c;
234             pktlen += c + 192;
235         }
236         else if( c < 255 ) {
237             pktlen  = (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 24;
238             pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 16;
239             pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 8;
240             if( (c = iobuf_get(inp)) == -1 ) {
241                 log_error("%s: 4 byte length invalid\n", iobuf_where(inp) );
242                 return G10ERR_INVALID_PACKET;
243             }
244             pktlen |= (hdr[hdrlen++] = c );
245         }
246         else { /* partial body length */
247             log_debug("partial body length of %lu bytes\n", pktlen );
248             iobuf_set_partial_block_mode(inp, pktlen);
249             pktlen = 0;/* to indicate partial length */
250         }
251     }
252     else {
253         pkttype = (ctb>>2)&0xf;
254         lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3));
255         if( !lenbytes ) {
256             pktlen = 0; /* don't know the value */
257             if( pkttype != PKT_COMPRESSED )
258                 iobuf_set_block_mode(inp, 1);
259         }
260         else {
261             for( ; lenbytes; lenbytes-- ) {
262                 pktlen <<= 8;
263                 pktlen |= hdr[hdrlen++] = iobuf_get_noeof(inp);
264             }
265         }
266     }
267
268     if( out && pkttype  ) {
269         if( iobuf_write( out, hdr, hdrlen ) == -1 )
270             rc = G10ERR_WRITE_FILE;
271         else
272             rc = copy_packet(inp, out, pkttype, pktlen );
273         return rc;
274     }
275
276     if( do_skip || !pkttype || (reqtype && pkttype != reqtype) ) {
277         skip_packet(inp, pkttype, pktlen);
278         *skip = 1;
279         return 0;
280     }
281
282     if( DBG_PACKET )
283         log_debug("parse_packet(iob=%d): type=%d length=%lu%s\n",
284                    iobuf_id(inp), pkttype, pktlen, pgp3?" (pgp3)":"" );
285     pkt->pkttype = pkttype;
286     rc = G10ERR_UNKNOWN_PACKET; /* default error */
287     switch( pkttype ) {
288       case PKT_PUBLIC_CERT:
289       case PKT_PUBKEY_SUBCERT:
290         pkt->pkt.public_cert = m_alloc_clear(sizeof *pkt->pkt.public_cert );
291         rc = parse_certificate(inp, pkttype, pktlen, hdr, hdrlen, pkt );
292         break;
293       case PKT_SECRET_CERT:
294       case PKT_SECKEY_SUBCERT:
295         pkt->pkt.secret_cert = m_alloc_clear(sizeof *pkt->pkt.secret_cert );
296         rc = parse_certificate(inp, pkttype, pktlen, hdr, hdrlen, pkt );
297         break;
298       case PKT_SYMKEY_ENC:
299         rc = parse_symkeyenc( inp, pkttype, pktlen, pkt );
300         break;
301       case PKT_PUBKEY_ENC:
302         rc = parse_pubkeyenc(inp, pkttype, pktlen, pkt );
303         break;
304       case PKT_SIGNATURE:
305         pkt->pkt.signature = m_alloc_clear(sizeof *pkt->pkt.signature );
306         rc = parse_signature(inp, pkttype, pktlen, pkt->pkt.signature );
307         break;
308       case PKT_ONEPASS_SIG:
309         pkt->pkt.onepass_sig = m_alloc_clear(sizeof *pkt->pkt.onepass_sig );
310         rc = parse_onepass_sig(inp, pkttype, pktlen, pkt->pkt.onepass_sig );
311         break;
312       case PKT_USER_ID:
313         rc = parse_user_id(inp, pkttype, pktlen, pkt );
314         break;
315       case PKT_OLD_COMMENT:
316       case PKT_COMMENT:
317         rc = parse_comment(inp, pkttype, pktlen, pkt);
318         break;
319       case PKT_RING_TRUST:
320         parse_trust(inp, pkttype, pktlen);
321         rc = 0;
322         break;
323       case PKT_PLAINTEXT:
324         rc = parse_plaintext(inp, pkttype, pktlen, pkt );
325         break;
326       case PKT_COMPRESSED:
327         rc = parse_compressed(inp, pkttype, pktlen, pkt );
328         break;
329       case PKT_ENCRYPTED:
330         rc = parse_encrypted(inp, pkttype, pktlen, pkt );
331         break;
332       default:
333         skip_packet(inp, pkttype, pktlen);
334         break;
335     }
336
337     return rc;
338 }
339
340 static void
341 dump_hex_line( int c, int *i )
342 {
343     if( *i && !(*i%8) ) {
344         if( *i && !(*i%24) )
345             printf("\n%4d:", *i );
346         else
347             putchar(' ');
348     }
349     if( c == -1 )
350         printf(" EOF" );
351     else
352         printf(" %02x", c );
353     ++*i;
354 }
355
356
357 static int
358 copy_packet( IOBUF inp, IOBUF out, int pkttype, unsigned long pktlen )
359 {
360     int n;
361     char buf[100];
362
363     if( iobuf_in_block_mode(inp) ) {
364         while( (n = iobuf_read( inp, buf, 100 )) != -1 )
365             if( iobuf_write(out, buf, n ) )
366                 return G10ERR_WRITE_FILE; /* write error */
367     }
368     else if( !pktlen && pkttype == PKT_COMPRESSED ) {
369         /* compressed packet, copy till EOF */
370         while( (n = iobuf_read( inp, buf, 100 )) != -1 )
371             if( iobuf_write(out, buf, n ) )
372                 return G10ERR_WRITE_FILE; /* write error */
373     }
374     else {
375         for( ; pktlen; pktlen -= n ) {
376             n = pktlen > 100 ? 100 : pktlen;
377             n = iobuf_read( inp, buf, n );
378             if( n == -1 )
379                 return G10ERR_READ_FILE;
380             if( iobuf_write(out, buf, n ) )
381                 return G10ERR_WRITE_FILE; /* write error */
382         }
383     }
384     return 0;
385 }
386
387
388 static void
389 skip_packet( IOBUF inp, int pkttype, unsigned long pktlen )
390 {
391     if( list_mode ) {
392         printf(":unknown packet: type %2d, length %lu\n", pkttype, pktlen );
393         if( pkttype ) {
394             int c, i=0 ;
395             printf("dump:");
396             if( iobuf_in_block_mode(inp) ) {
397                 while( (c=iobuf_get(inp)) != -1 )
398                     dump_hex_line(c, &i);
399             }
400             else {
401                 for( ; pktlen; pktlen-- )
402                     dump_hex_line(iobuf_get(inp), &i);
403             }
404             putchar('\n');
405             return;
406         }
407     }
408     skip_rest(inp,pktlen);
409 }
410
411 static void
412 skip_rest( IOBUF inp, unsigned long pktlen )
413 {
414     if( iobuf_in_block_mode(inp) ) {
415         while( iobuf_get(inp) != -1 )
416                 ;
417     }
418     else {
419         for( ; pktlen; pktlen-- )
420             iobuf_get(inp);
421     }
422 }
423
424
425 static int
426 parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
427 {
428     PKT_symkey_enc *k;
429     int i, version, s2kmode, cipher_algo, hash_algo, seskeylen, minlen;
430
431     if( pktlen < 4 ) {
432         log_error("packet(%d) too short\n", pkttype);
433         goto leave;
434     }
435     version = iobuf_get_noeof(inp); pktlen--;
436     if( version != 4 ) {
437         log_error("packet(%d) with unknown version %d\n", pkttype, version);
438         goto leave;
439     }
440     if( pktlen > 200 ) { /* (we encode the seskeylen in a byte) */
441         log_error("packet(%d) too large\n", pkttype);
442         goto leave;
443     }
444     cipher_algo = iobuf_get_noeof(inp); pktlen--;
445     s2kmode = iobuf_get_noeof(inp); pktlen--;
446     hash_algo = iobuf_get_noeof(inp); pktlen--;
447     switch( s2kmode ) {
448       case 0:  /* simple s2k */
449         minlen = 0;
450         break;
451       case 1:  /* salted s2k */
452         minlen = 8;
453         break;
454       case 4:  /* iterated+salted s2k */
455         minlen = 12;
456         break;
457       default:
458         log_error("unknown S2K %d\n", s2kmode );
459         goto leave;
460     }
461     if( minlen > pktlen ) {
462         log_error("packet with S2K %d too short\n", s2kmode );
463         goto leave;
464     }
465     seskeylen = pktlen - minlen;
466     k = packet->pkt.symkey_enc = m_alloc_clear( sizeof *packet->pkt.symkey_enc
467                                                 + seskeylen - 1 );
468     k->version = version;
469     k->cipher_algo = cipher_algo;
470     k->s2k.mode = s2kmode;
471     k->s2k.hash_algo = hash_algo;
472     if( s2kmode == 1 || s2kmode == 4 ) {
473         for(i=0; i < 8 && pktlen; i++, pktlen-- )
474             k->s2k.salt[i] = iobuf_get_noeof(inp);
475     }
476     if( s2kmode == 4 ) {
477         k->s2k.count = read_32(inp); pktlen -= 4;
478     }
479     k->seskeylen = seskeylen;
480     for(i=0; i < seskeylen && pktlen; i++, pktlen-- )
481         k->seskey[i] = iobuf_get_noeof(inp);
482     assert( !pktlen );
483
484     if( list_mode ) {
485         printf(":symkey enc packet: version %d, cipher %d, s2k %d, hash %d\n",
486                             version, cipher_algo, s2kmode, hash_algo);
487         if( s2kmode == 1  || s2kmode == 4 ) {
488             printf("\tsalt ");
489             for(i=0; i < 8; i++ )
490                 printf("%02x", k->s2k.salt[i]);
491             if( s2kmode == 4 )
492                 printf(", count %lu\n", (ulong)k->s2k.count );
493             printf("\n");
494         }
495     }
496
497   leave:
498     skip_rest(inp, pktlen);
499     return 0;
500 }
501
502 static int
503 parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
504 {
505     unsigned n;
506     int i, ndata;
507     PKT_pubkey_enc *k;
508
509     k = packet->pkt.pubkey_enc = m_alloc(sizeof *packet->pkt.pubkey_enc );
510     if( pktlen < 12 ) {
511         log_error("packet(%d) too short\n", pkttype);
512         goto leave;
513     }
514     k->version = iobuf_get_noeof(inp); pktlen--;
515     if( k->version != 2 && k->version != 3 ) {
516         log_error("packet(%d) with unknown version %d\n", pkttype, k->version);
517         goto leave;
518     }
519     k->keyid[0] = read_32(inp); pktlen -= 4;
520     k->keyid[1] = read_32(inp); pktlen -= 4;
521     k->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
522     if( list_mode )
523         printf(":pubkey enc packet: version %d, algo %d, keyid %08lX%08lX\n",
524           k->version, k->pubkey_algo, (ulong)k->keyid[0], (ulong)k->keyid[1]);
525
526     ndata = pubkey_get_nenc(k->pubkey_algo);
527     if( !ndata && list_mode )
528         printf("\tunsupported algorithm %d\n", k->pubkey_algo );
529
530     for( i=0; i < ndata; i++ ) {
531         n = pktlen;
532         k->data[i] = mpi_read(inp, &n, 0); pktlen -=n;
533         if( list_mode ) {
534             printf("\tdata: ");
535             mpi_print(stdout, k->data[i], mpi_print_mode );
536             putchar('\n');
537         }
538     }
539
540   leave:
541     skip_rest(inp, pktlen);
542     return 0;
543 }
544
545
546 const byte *
547 parse_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype, size_t *ret_n )
548 {
549     int buflen;
550     int type;
551     int critical;
552     size_t n;
553
554     if( !buffer )
555         return NULL;
556     buflen = (*buffer << 8) | buffer[1];
557     buffer += 2;
558     for(;;) {
559         if( !buflen )
560             return NULL; /* end of packets; not found */
561         n = *buffer++; buflen--;
562         if( n == 255 ) {
563             if( buflen < 4 )
564                 goto too_short;
565             n = (buffer[0] << 24) | (buffer[1] << 16)
566                                   | (buffer[2] << 8) | buffer[3];
567             buffer += 4;
568             buflen -= 4;
569
570         }
571         else if( n >= 192 ) {
572             if( buflen < 2 )
573                 goto too_short;
574             n = (( n - 192 ) << 8) + *buffer + 192;
575             buflen--;
576         }
577         if( buflen < n )
578             goto too_short;
579         type = *buffer;
580         if( type & 0x80 ) {
581             type &= 0x7f;
582             critical = 1;
583         }
584         else
585             critical = 0;
586         if( reqtype < 0 ) { /* list packets */
587             printf("\t%ssubpacket %d of length %u (%s)\n",
588             reqtype == SIGSUBPKT_LIST_HASHED ? "hashed ":"", type, (unsigned)n,
589              type == SIGSUBPKT_SIG_CREATED ? "signature creation time"
590            : type == SIGSUBPKT_SIG_EXPIRE  ? "signature expiration time"
591            : type == SIGSUBPKT_EXPORTABLE  ? "exportable"
592            : type == SIGSUBPKT_TRUST       ? "trust signature"
593            : type == SIGSUBPKT_REGEXP      ? "regular expression"
594            : type == SIGSUBPKT_REVOCABLE   ? "revocable"
595            : type == SIGSUBPKT_KEY_EXPIRE  ? "key expiration time"
596            : type == SIGSUBPKT_ARR         ? "additional recipient request"
597            : type == SIGSUBPKT_PREF_SYM    ? "preferred symmetric algorithms"
598            : type == SIGSUBPKT_REV_KEY     ? "revocation key"
599            : type == SIGSUBPKT_ISSUER      ? "issuer key ID"
600            : type == SIGSUBPKT_NOTATION    ? "notation data"
601            : type == SIGSUBPKT_PREF_HASH   ? "preferred hash algorithms"
602            : type == SIGSUBPKT_PREF_COMPR  ? "preferred compression algorithms"
603            : type == SIGSUBPKT_KS_FLAGS    ? "key server preferences"
604            : type == SIGSUBPKT_PREF_KS     ? "preferred key server"
605            : type == SIGSUBPKT_PRIMARY_UID ? "primary user id"
606            : type == SIGSUBPKT_POLICY      ? "policy URL"
607            : type == SIGSUBPKT_KEY_FLAGS   ? "key flags"
608            : type == SIGSUBPKT_SIGNERS_UID ? "signer's user id"
609            : type == SIGSUBPKT_PRIV_ADD_SIG? "signs additional user id"
610                               : "?");
611         }
612         else if( type == reqtype )
613             break; /* found */
614         buffer += n; buflen -=n;
615     }
616     buffer++;
617     n--;
618     if( n > buflen )
619         goto too_short;
620     if( ret_n )
621         *ret_n = n;
622     switch( type ) {
623       case SIGSUBPKT_SIG_CREATED:
624         if( n < 4 )
625             break;
626         return buffer;
627       case SIGSUBPKT_ISSUER:/* issuer key ID */
628         if( n < 8 )
629             break;
630         return buffer;
631       case SIGSUBPKT_PRIV_ADD_SIG:
632         /* because we use private data, we check the GNUPG marker */
633         if( n < 24 )
634             break;
635         if( buffer[0] != 'G' || buffer[1] != 'P' || buffer[2] != 'G' )
636             return NULL;
637         return buffer+3;
638       default: BUG(); /* not yet needed */
639     }
640     log_error("subpacket of type %d too short\n", type);
641     return NULL;
642
643   too_short:
644     log_error("buffer shorter than subpacket\n");
645     return NULL;
646 }
647
648
649 static int
650 parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
651                                           PKT_signature *sig )
652 {
653     int md5_len=0;
654     unsigned n;
655     int is_v4=0;
656     int rc=0;
657     int i, ndata;
658
659     if( pktlen < 16 ) {
660         log_error("packet(%d) too short\n", pkttype);
661         goto leave;
662     }
663     sig->version = iobuf_get_noeof(inp); pktlen--;
664     if( sig->version == 4 )
665         is_v4=1;
666     else if( sig->version != 2 && sig->version != 3 ) {
667         log_error("packet(%d) with unknown version %d\n", pkttype, sig->version);
668         goto leave;
669     }
670
671     if( !is_v4 ) {
672         md5_len = iobuf_get_noeof(inp); pktlen--;
673     }
674     sig->sig_class = iobuf_get_noeof(inp); pktlen--;
675     if( !is_v4 ) {
676         sig->timestamp = read_32(inp); pktlen -= 4;
677         sig->keyid[0] = read_32(inp); pktlen -= 4;
678         sig->keyid[1] = read_32(inp); pktlen -= 4;
679     }
680     sig->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
681     sig->digest_algo = iobuf_get_noeof(inp); pktlen--;
682     if( is_v4 ) { /* read subpackets */
683         n = read_16(inp); pktlen -= 2; /* length of hashed data */
684         if( n > 10000 ) {
685             log_error("signature packet: hashed data too long\n");
686             rc = G10ERR_INVALID_PACKET;
687             goto leave;
688         }
689         if( n ) {
690             sig->hashed_data = m_alloc( n + 2 );
691             sig->hashed_data[0] = n << 8;
692             sig->hashed_data[1] = n;
693             if( iobuf_read(inp, sig->hashed_data+2, n ) != n ) {
694                 log_error("premature eof while reading hashed signature data\n");
695                 rc = -1;
696                 goto leave;
697             }
698             pktlen -= n;
699         }
700         n = read_16(inp); pktlen -= 2; /* length of unhashed data */
701         if( n > 10000 ) {
702             log_error("signature packet: unhashed data too long\n");
703             rc = G10ERR_INVALID_PACKET;
704             goto leave;
705         }
706         if( n ) {
707             sig->unhashed_data = m_alloc( n + 2 );
708             sig->unhashed_data[0] = n << 8;
709             sig->unhashed_data[1] = n;
710             if( iobuf_read(inp, sig->unhashed_data+2, n ) != n ) {
711                 log_error("premature eof while reading unhashed signature data\n");
712                 rc = -1;
713                 goto leave;
714             }
715             pktlen -= n;
716         }
717     }
718
719     if( pktlen < 5 ) { /* sanity check */
720         log_error("packet(%d) too short\n", pkttype);
721         rc = G10ERR_INVALID_PACKET;
722         goto leave;
723     }
724
725     sig->digest_start[0] = iobuf_get_noeof(inp); pktlen--;
726     sig->digest_start[1] = iobuf_get_noeof(inp); pktlen--;
727
728     if( is_v4 ) { /*extract required information */
729         const byte *p;
730         p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_SIG_CREATED, NULL );
731         if( !p )
732             log_error("signature packet without timestamp\n");
733         else
734             sig->timestamp = buffer_to_u32(p);
735         p = parse_sig_subpkt( sig->unhashed_data, SIGSUBPKT_ISSUER, NULL );
736         if( !p )
737             log_error("signature packet without keyid\n");
738         else {
739             sig->keyid[0] = buffer_to_u32(p);
740             sig->keyid[1] = buffer_to_u32(p+4);
741         }
742     }
743
744     if( list_mode ) {
745         printf(":signature packet: algo %d, keyid %08lX%08lX\n"
746                "\tversion %d, created %lu, md5len %d, sigclass %02x\n"
747                "\tdigest algo %d, begin of digest %02x %02x\n",
748                 sig->pubkey_algo,
749                 (ulong)sig->keyid[0], (ulong)sig->keyid[1],
750                 sig->version, (ulong)sig->timestamp, md5_len, sig->sig_class,
751                 sig->digest_algo,
752                 sig->digest_start[0], sig->digest_start[1] );
753         if( is_v4 ) {
754             parse_sig_subpkt( sig->hashed_data,  SIGSUBPKT_LIST_HASHED, NULL );
755             parse_sig_subpkt( sig->unhashed_data,SIGSUBPKT_LIST_UNHASHED, NULL);
756         }
757     }
758
759     ndata = pubkey_get_nsig(sig->pubkey_algo);
760     if( !ndata && list_mode )
761         printf("\tunknown algorithm %d\n", sig->pubkey_algo );
762
763     for( i=0; i < ndata; i++ ) {
764         n = pktlen;
765         sig->data[i] = mpi_read(inp, &n, 0 );
766         pktlen -=n;
767         if( list_mode ) {
768             printf("\tdata: ");
769             mpi_print(stdout, sig->data[i], mpi_print_mode );
770             putchar('\n');
771         }
772     }
773
774
775   leave:
776     skip_rest(inp, pktlen);
777     return rc;
778 }
779
780
781 static int
782 parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
783                                              PKT_onepass_sig *ops )
784 {
785     int version;
786
787     if( pktlen < 13 ) {
788         log_error("packet(%d) too short\n", pkttype);
789         goto leave;
790     }
791     version = iobuf_get_noeof(inp); pktlen--;
792     if( version != 3 ) {
793         log_error("onepass_sig with unknown version %d\n", version);
794         goto leave;
795     }
796     ops->sig_class = iobuf_get_noeof(inp); pktlen--;
797     ops->digest_algo = iobuf_get_noeof(inp); pktlen--;
798     ops->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
799     ops->keyid[0] = read_32(inp); pktlen -= 4;
800     ops->keyid[1] = read_32(inp); pktlen -= 4;
801     ops->last = iobuf_get_noeof(inp); pktlen--;
802     if( list_mode )
803         printf(":onepass_sig packet: keyid %08lX%08lX\n"
804                "\tversion %d, sigclass %02x, digest %d, pubkey %d, last=%d\n",
805                 (ulong)ops->keyid[0], (ulong)ops->keyid[1],
806                 version, ops->sig_class,
807                 ops->digest_algo, ops->pubkey_algo, ops->last );
808
809
810   leave:
811     skip_rest(inp, pktlen);
812     return 0;
813 }
814
815
816
817
818 static int
819 parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
820                               byte *hdr, int hdrlen, PACKET *pkt )
821 {
822     int i, version, algorithm;
823     unsigned n;
824     unsigned long timestamp;
825     unsigned short valid_period;
826     int is_v4=0;
827     int rc=0;
828
829     version = iobuf_get_noeof(inp); pktlen--;
830     if( pkttype == PKT_PUBKEY_SUBCERT && version == '#' ) {
831         /* early versions of G10 use old PGP comments packets;
832          * luckily all those comments are started by a hash */
833         if( list_mode ) {
834             printf(":rfc1991 comment packet: \"" );
835             for( ; pktlen; pktlen-- ) {
836                 int c;
837                 c = iobuf_get_noeof(inp);
838                 if( c >= ' ' && c <= 'z' )
839                     putchar(c);
840                 else
841                     printf("\\x%02x", c );
842             }
843             printf("\"\n");
844         }
845         skip_rest(inp, pktlen);
846         return 0;
847     }
848     else if( version == 4 )
849         is_v4=1;
850     else if( version != 2 && version != 3 ) {
851         log_error("packet(%d) with unknown version %d\n", pkttype, version);
852         goto leave;
853     }
854
855     if( pktlen < 11 ) {
856         log_error("packet(%d) too short\n", pkttype);
857         goto leave;
858     }
859
860     timestamp = read_32(inp); pktlen -= 4;
861     if( is_v4 )
862         valid_period = 0;
863     else {
864         valid_period = read_16(inp); pktlen -= 2;
865     }
866     algorithm = iobuf_get_noeof(inp); pktlen--;
867     if( list_mode )
868         printf(":%s key packet:\n"
869                "\tversion %d, algo %d, created %lu, valid for %hu days\n",
870                 pkttype == PKT_PUBLIC_CERT? "public" :
871                 pkttype == PKT_SECRET_CERT? "secret" :
872                 pkttype == PKT_PUBKEY_SUBCERT? "public sub" :
873                 pkttype == PKT_SECKEY_SUBCERT? "secret sub" : "??",
874                 version, algorithm, timestamp, valid_period );
875     if( pkttype == PKT_SECRET_CERT || pkttype == PKT_SECKEY_SUBCERT )  {
876         pkt->pkt.secret_cert->timestamp = timestamp;
877         pkt->pkt.secret_cert->valid_days = valid_period;
878         pkt->pkt.secret_cert->hdrbytes = hdrlen;
879         pkt->pkt.secret_cert->version = version;
880         pkt->pkt.secret_cert->pubkey_algo = algorithm;
881     }
882     else {
883         pkt->pkt.public_cert->timestamp = timestamp;
884         pkt->pkt.public_cert->valid_days = valid_period;
885         pkt->pkt.public_cert->hdrbytes    = hdrlen;
886         pkt->pkt.public_cert->version     = version;
887         pkt->pkt.public_cert->pubkey_algo = algorithm;
888     }
889
890     if( is_ELGAMAL(algorithm) ) {
891         MPI elg_p, elg_g, elg_y;
892         n = pktlen; elg_p = mpi_read(inp, &n, 0 ); pktlen -=n;
893         n = pktlen; elg_g = mpi_read(inp, &n, 0 ); pktlen -=n;
894         n = pktlen; elg_y = mpi_read(inp, &n, 0 ); pktlen -=n;
895         if( list_mode ) {
896             printf(  "\telg p: ");
897             mpi_print(stdout, elg_p, mpi_print_mode  );
898             printf("\n\telg g: ");
899             mpi_print(stdout, elg_g, mpi_print_mode  );
900             printf("\n\telg y: ");
901             mpi_print(stdout, elg_y, mpi_print_mode  );
902             putchar('\n');
903         }
904         if( pkttype == PKT_PUBLIC_CERT || pkttype == PKT_PUBKEY_SUBCERT ) {
905             pkt->pkt.public_cert->pkey[0] = elg_p;
906             pkt->pkt.public_cert->pkey[1] = elg_g;
907             pkt->pkt.public_cert->pkey[2] = elg_y;
908         }
909         else {
910             PKT_secret_cert *cert = pkt->pkt.secret_cert;
911             byte temp[8];
912
913             pkt->pkt.secret_cert->skey[0] = elg_p;
914             pkt->pkt.secret_cert->skey[1] = elg_g;
915             pkt->pkt.secret_cert->skey[2] = elg_y;
916             cert->protect.algo = iobuf_get_noeof(inp); pktlen--;
917             if( cert->protect.algo ) {
918                 cert->is_protected = 1;
919                 cert->protect.s2k.count = 0;
920                 if( cert->protect.algo == 255 ) {
921                     if( pktlen < 3 ) {
922                         rc = G10ERR_INVALID_PACKET;
923                         goto leave;
924                     }
925                     cert->protect.algo = iobuf_get_noeof(inp); pktlen--;
926                     cert->protect.s2k.mode  = iobuf_get_noeof(inp); pktlen--;
927                     cert->protect.s2k.hash_algo = iobuf_get_noeof(inp); pktlen--;
928                     switch( cert->protect.s2k.mode ) {
929                       case 1:
930                       case 4:
931                         for(i=0; i < 8 && pktlen; i++, pktlen-- )
932                             temp[i] = iobuf_get_noeof(inp);
933                         memcpy(cert->protect.s2k.salt, temp, 8 );
934                         break;
935                     }
936                     switch( cert->protect.s2k.mode ) {
937                       case 0: if( list_mode ) printf(  "\tsimple S2K" );
938                         break;
939                       case 1: if( list_mode ) printf(  "\tsalted S2K" );
940                         break;
941                       case 4: if( list_mode ) printf(  "\titer+salt S2K" );
942                         break;
943                       default:
944                         if( list_mode )
945                             printf(  "\tunknown S2K %d\n",
946                                                 cert->protect.s2k.mode );
947                         rc = G10ERR_INVALID_PACKET;
948                         goto leave;
949                     }
950
951                     if( list_mode ) {
952                         printf(", algo: %d, hash: %d",
953                                          cert->protect.algo,
954                                          cert->protect.s2k.hash_algo );
955                         if( cert->protect.s2k.mode == 1
956                             || cert->protect.s2k.mode == 4 ) {
957                             printf(", salt: ");
958                             for(i=0; i < 8; i++ )
959                                 printf("%02x", cert->protect.s2k.salt[i]);
960                         }
961                         putchar('\n');
962                     }
963
964                     if( cert->protect.s2k.mode == 4 ) {
965                         if( pktlen < 4 ) {
966                             rc = G10ERR_INVALID_PACKET;
967                             goto leave;
968                         }
969                         cert->protect.s2k.count = read_32(inp);
970                         pktlen -= 4;
971                     }
972
973                 }
974                 else {
975                     if( list_mode )
976                         printf(  "\tprotect algo: %d\n",
977                                                 cert->protect.algo);
978                     /* old version, we don't have a S2K, so we fake one */
979                     cert->protect.s2k.mode = 0;
980                     /* We need this kludge to cope with old GNUPG versions */
981                     cert->protect.s2k.hash_algo =
982                          cert->protect.algo == CIPHER_ALGO_BLOWFISH160?
983                                       DIGEST_ALGO_RMD160 : DIGEST_ALGO_MD5;
984                 }
985                 if( pktlen < 8 ) {
986                     rc = G10ERR_INVALID_PACKET;
987                     goto leave;
988                 }
989                 for(i=0; i < 8 && pktlen; i++, pktlen-- )
990                     temp[i] = iobuf_get_noeof(inp);
991                 if( list_mode ) {
992                     printf(  "\tprotect IV: ");
993                     for(i=0; i < 8; i++ )
994                         printf(" %02x", temp[i] );
995                     putchar('\n');
996                 }
997                 memcpy(cert->protect.iv, temp, 8 );
998             }
999             else
1000                 cert->is_protected = 0;
1001             /* It does not make sense to read it into secure memory.
1002              * If the user is so careless, not to protect his secret key,
1003              * we can assume, that he operates an open system :=(.
1004              * So we put the key into secure memory when we unprotect it. */
1005             n = pktlen; cert->skey[3] = mpi_read(inp, &n, 0 ); pktlen -=n;
1006
1007             cert->csum = read_16(inp); pktlen -= 2;
1008             if( list_mode ) {
1009             printf("\telg x: ");
1010             mpi_print(stdout, cert->skey[3], mpi_print_mode  );
1011             putchar('\n');
1012                 printf("\t[secret value x is not shown]\n"
1013                        "\tchecksum: %04hx\n", cert->csum);
1014             }
1015         }
1016     }
1017     else if( algorithm == PUBKEY_ALGO_DSA ) {
1018         MPI dsa_p, dsa_q, dsa_g, dsa_y;
1019         n = pktlen; dsa_p = mpi_read(inp, &n, 0 ); pktlen -=n;
1020         n = pktlen; dsa_q = mpi_read(inp, &n, 0 ); pktlen -=n;
1021         n = pktlen; dsa_g = mpi_read(inp, &n, 0 ); pktlen -=n;
1022         n = pktlen; dsa_y = mpi_read(inp, &n, 0 ); pktlen -=n;
1023         if( list_mode ) {
1024             printf(  "\tdsa p: ");
1025             mpi_print(stdout, dsa_p, mpi_print_mode  );
1026             printf("\n\tdsa q: ");
1027             mpi_print(stdout, dsa_q, mpi_print_mode  );
1028             printf("\n\tdsa g: ");
1029             mpi_print(stdout, dsa_g, mpi_print_mode  );
1030             printf("\n\tdsa y: ");
1031             mpi_print(stdout, dsa_y, mpi_print_mode  );
1032             putchar('\n');
1033         }
1034         if( pkttype == PKT_PUBLIC_CERT || pkttype == PKT_PUBKEY_SUBCERT ) {
1035             pkt->pkt.public_cert->pkey[0] = dsa_p;
1036             pkt->pkt.public_cert->pkey[1] = dsa_q;
1037             pkt->pkt.public_cert->pkey[2] = dsa_g;
1038             pkt->pkt.public_cert->pkey[3] = dsa_y;
1039         }
1040         else {
1041             PKT_secret_cert *cert = pkt->pkt.secret_cert;
1042             byte temp[8];
1043
1044             pkt->pkt.secret_cert->skey[0] = dsa_p;
1045             pkt->pkt.secret_cert->skey[1] = dsa_q;
1046             pkt->pkt.secret_cert->skey[2] = dsa_g;
1047             pkt->pkt.secret_cert->skey[3] = dsa_y;
1048             cert->protect.algo = iobuf_get_noeof(inp); pktlen--;
1049             if( cert->protect.algo ) {
1050                 cert->is_protected = 1;
1051                 cert->protect.s2k.count = 0;
1052                 if( cert->protect.algo == 255 ) {
1053                     if( pktlen < 3 ) {
1054                         rc = G10ERR_INVALID_PACKET;
1055                         goto leave;
1056                     }
1057                     cert->protect.algo = iobuf_get_noeof(inp); pktlen--;
1058                     cert->protect.s2k.mode  = iobuf_get_noeof(inp); pktlen--;
1059                     cert->protect.s2k.hash_algo = iobuf_get_noeof(inp); pktlen--;
1060                     switch( cert->protect.s2k.mode ) {
1061                       case 1:
1062                       case 4:
1063                         for(i=0; i < 8 && pktlen; i++, pktlen-- )
1064                             temp[i] = iobuf_get_noeof(inp);
1065                         memcpy(cert->protect.s2k.salt, temp, 8 );
1066                         break;
1067                     }
1068                     switch( cert->protect.s2k.mode ) {
1069                       case 0: if( list_mode ) printf(  "\tsimple S2K" );
1070                         break;
1071                       case 1: if( list_mode ) printf(  "\tsalted S2K" );
1072                         break;
1073                       case 4: if( list_mode ) printf(  "\titer+salt S2K" );
1074                         break;
1075                       default:
1076                         if( list_mode )
1077                             printf(  "\tunknown S2K %d\n",
1078                                                     cert->protect.s2k.mode );
1079                         rc = G10ERR_INVALID_PACKET;
1080                         goto leave;
1081                     }
1082
1083                     if( list_mode ) {
1084                         printf(", algo: %d, hash: %d",
1085                                          cert->protect.algo,
1086                                          cert->protect.s2k.hash_algo );
1087                         if( cert->protect.s2k.mode == 1
1088                             || cert->protect.s2k.mode == 4 ){
1089                             printf(", salt: ");
1090                             for(i=0; i < 8; i++ )
1091                                 printf("%02x", cert->protect.s2k.salt[i]);
1092                         }
1093                         putchar('\n');
1094                     }
1095
1096                     if( cert->protect.s2k.mode == 4 ) {
1097                         if( pktlen < 4 ) {
1098                             rc = G10ERR_INVALID_PACKET;
1099                             goto leave;
1100                         }
1101                         cert->protect.s2k.count = read_32(inp);
1102                         pktlen -= 4;
1103                     }
1104
1105                 }
1106                 else {
1107                     if( list_mode )
1108                         printf(  "\tprotect algo: %d\n", cert->protect.algo);
1109                     /* old version, we don't have a S2K, so we fake one */
1110                     cert->protect.s2k.mode = 0;
1111                     cert->protect.s2k.hash_algo = DIGEST_ALGO_MD5;
1112                 }
1113                 if( pktlen < 8 ) {
1114                     rc = G10ERR_INVALID_PACKET;
1115                     goto leave;
1116                 }
1117                 for(i=0; i < 8 && pktlen; i++, pktlen-- )
1118                     temp[i] = iobuf_get_noeof(inp);
1119                 if( list_mode ) {
1120                     printf(  "\tprotect IV: ");
1121                     for(i=0; i < 8; i++ )
1122                         printf(" %02x", temp[i] );
1123                     putchar('\n');
1124                 }
1125                 memcpy(cert->protect.iv, temp, 8 );
1126             }
1127             else
1128                 cert->is_protected = 0;
1129             /* It does not make sense to read it into secure memory.
1130              * If the user is so careless, not to protect his secret key,
1131              * we can assume, that he operates an open system :=(.
1132              * So we put the key into secure memory when we unprotect it. */
1133             n = pktlen; cert->skey[4] = mpi_read(inp, &n, 0 ); pktlen -=n;
1134
1135             cert->csum = read_16(inp); pktlen -= 2;
1136             if( list_mode ) {
1137                 printf("\t[secret value x is not shown]\n"
1138                        "\tchecksum: %04hx\n", cert->csum);
1139             }
1140         }
1141     }
1142     else if( is_RSA(algorithm) ) {
1143         MPI rsa_pub_mod, rsa_pub_exp;
1144
1145         n = pktlen; rsa_pub_mod = mpi_read(inp, &n, 0); pktlen -=n;
1146         n = pktlen; rsa_pub_exp = mpi_read(inp, &n, 0 ); pktlen -=n;
1147         if( list_mode ) {
1148             printf(  "\tpublic modulus  n:  ");
1149             mpi_print(stdout, rsa_pub_mod, mpi_print_mode  );
1150             printf("\n\tpublic exponent e: ");
1151             mpi_print(stdout, rsa_pub_exp, mpi_print_mode  );
1152             putchar('\n');
1153         }
1154         if( pkttype == PKT_PUBLIC_CERT || pkttype == PKT_PUBKEY_SUBCERT ) {
1155             pkt->pkt.public_cert->pkey[0] = rsa_pub_mod;
1156             pkt->pkt.public_cert->pkey[1] = rsa_pub_exp;
1157         }
1158         else {
1159             PKT_secret_cert *cert = pkt->pkt.secret_cert;
1160             byte temp[8];
1161
1162             pkt->pkt.secret_cert->skey[0] = rsa_pub_mod;
1163             pkt->pkt.secret_cert->skey[1] = rsa_pub_exp;
1164             cert->protect.algo = iobuf_get_noeof(inp); pktlen--;
1165             if( list_mode )
1166                 printf(  "\tprotect algo: %d\n", cert->protect.algo);
1167             if( cert->protect.algo ) {
1168                 cert->is_protected = 1;
1169                 for(i=0; i < 8 && pktlen; i++, pktlen-- )
1170                     temp[i] = iobuf_get_noeof(inp);
1171                 if( list_mode ) {
1172                     printf(  "\tprotect IV: ");
1173                     for(i=0; i < 8; i++ )
1174                         printf(" %02x", temp[i] );
1175                     putchar('\n');
1176                 }
1177                 if( cert->protect.algo == CIPHER_ALGO_BLOWFISH160 )
1178                     memcpy(cert->protect.iv, temp, 8 );
1179             }
1180             else
1181                 cert->is_protected = 0;
1182             /* (See comments at the code for elg keys) */
1183             n = pktlen; cert->skey[2] = mpi_read(inp, &n, 0 ); pktlen -=n;
1184             n = pktlen; cert->skey[3] = mpi_read(inp, &n, 0 ); pktlen -=n;
1185             n = pktlen; cert->skey[4] = mpi_read(inp, &n, 0 ); pktlen -=n;
1186             n = pktlen; cert->skey[5] = mpi_read(inp, &n, 0 ); pktlen -=n;
1187
1188             cert->csum = read_16(inp); pktlen -= 2;
1189             if( list_mode ) {
1190                 printf("\t[secret values d,p,q,u are not shown]\n"
1191                        "\tchecksum: %04hx\n", cert->csum);
1192             }
1193         }
1194     }
1195     else if( list_mode )
1196         printf("\tunknown algorithm %d\n", algorithm );
1197
1198
1199   leave:
1200     skip_rest(inp, pktlen);
1201     return rc;
1202 }
1203
1204
1205 static int
1206 parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
1207 {
1208     byte *p;
1209
1210     packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id  + pktlen - 1);
1211     packet->pkt.user_id->len = pktlen;
1212     p = packet->pkt.user_id->name;
1213     for( ; pktlen; pktlen--, p++ )
1214         *p = iobuf_get_noeof(inp);
1215
1216     if( list_mode ) {
1217         int n = packet->pkt.user_id->len;
1218         printf(":user id packet: \"");
1219         for(p=packet->pkt.user_id->name; n; p++, n-- ) {
1220             if( *p >= ' ' && *p <= 'z' )
1221                 putchar(*p);
1222             else
1223                 printf("\\x%02x", *p );
1224         }
1225         printf("\"\n");
1226     }
1227     return 0;
1228 }
1229
1230
1231
1232 static int
1233 parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
1234 {
1235     byte *p;
1236
1237     packet->pkt.comment = m_alloc(sizeof *packet->pkt.comment + pktlen - 1);
1238     packet->pkt.comment->len = pktlen;
1239     p = packet->pkt.comment->data;
1240     for( ; pktlen; pktlen--, p++ )
1241         *p = iobuf_get_noeof(inp);
1242
1243     if( list_mode ) {
1244         int n = packet->pkt.comment->len;
1245         printf(":%scomment packet: \"", pkttype == PKT_OLD_COMMENT?
1246                                          "OpenPGP draft " : "" );
1247         for(p=packet->pkt.comment->data; n; p++, n-- ) {
1248             if( *p >= ' ' && *p <= 'z' )
1249                 putchar(*p);
1250             else
1251                 printf("\\x%02x", *p );
1252         }
1253         printf("\"\n");
1254     }
1255     return 0;
1256 }
1257
1258
1259 static void
1260 parse_trust( IOBUF inp, int pkttype, unsigned long pktlen )
1261 {
1262     int c;
1263
1264     c = iobuf_get_noeof(inp);
1265     if( list_mode )
1266         printf(":trust packet: flag=%02x\n", c );
1267 }
1268
1269
1270 static int
1271 parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
1272 {
1273     int mode, namelen;
1274     PKT_plaintext *pt;
1275     byte *p;
1276     int c, i;
1277
1278     if( pktlen && pktlen < 6 ) {
1279         log_error("packet(%d) too short (%lu)\n", pkttype, (ulong)pktlen);
1280         goto leave;
1281     }
1282     mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
1283     namelen = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
1284     pt = pkt->pkt.plaintext = m_alloc(sizeof *pkt->pkt.plaintext + namelen -1);
1285     pt->mode = mode;
1286     pt->namelen = namelen;
1287     if( pktlen ) {
1288         for( i=0; pktlen > 4 && i < namelen; pktlen--, i++ )
1289             pt->name[i] = iobuf_get_noeof(inp);
1290     }
1291     else {
1292         for( i=0; i < namelen; i++ )
1293             if( (c=iobuf_get(inp)) == -1 )
1294                 break;
1295             else
1296                 pt->name[i] = c;
1297     }
1298     pt->timestamp = read_32(inp); if( pktlen) pktlen -= 4;
1299     pt->len = pktlen;
1300     pt->buf = inp;
1301     pktlen = 0;
1302
1303     if( list_mode ) {
1304         printf(":literal data packet:\n"
1305                "\tmode %c, created %lu, name=\"",
1306                     mode >= ' ' && mode <'z'? mode : '?',
1307                     (ulong)pt->timestamp );
1308         for(p=pt->name,i=0; i < namelen; p++, i++ ) {
1309             if( *p >= ' ' && *p <= 'z' )
1310                 putchar(*p);
1311             else
1312                 printf("\\x%02x", *p );
1313         }
1314         printf("\",\n\traw data: %lu bytes\n", (ulong)pt->len );
1315     }
1316
1317   leave:
1318     return 0;
1319 }
1320
1321
1322 static int
1323 parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
1324 {
1325     PKT_compressed *zd;
1326
1327     /* pktlen is here 0, but data follows
1328      * (this should be the last object in a file or
1329      *  the compress algorithm should know the length)
1330      */
1331     zd = pkt->pkt.compressed =  m_alloc(sizeof *pkt->pkt.compressed );
1332     zd->len = 0; /* not yet used */
1333     zd->algorithm = iobuf_get_noeof(inp);
1334     zd->buf = inp;
1335     if( list_mode )
1336         printf(":compressed packet: algo=%d\n", zd->algorithm);
1337     return 0;
1338 }
1339
1340
1341 static int
1342 parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
1343 {
1344     PKT_encrypted *ed;
1345
1346     ed = pkt->pkt.encrypted =  m_alloc(sizeof *pkt->pkt.encrypted );
1347     ed->len = pktlen;
1348     ed->buf = NULL;
1349     if( pktlen && pktlen < 10 ) {
1350         log_error("packet(%d) too short\n", pkttype);
1351         skip_rest(inp, pktlen);
1352         goto leave;
1353     }
1354     if( list_mode ) {
1355         if( pktlen )
1356             printf(":encrypted data packet:\n\tlength: %lu\n", pktlen-10);
1357         else
1358             printf(":encrypted data packet:\n\tlength: unknown\n");
1359     }
1360
1361     ed->buf = inp;
1362     pktlen = 0;
1363
1364   leave:
1365     return 0;
1366 }
1367
1368
1369