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