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