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