Sicherung
[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            : type == SIGSUBPKT_PRIV_ADD_SIG? "signs additional user id"
619                               : "?");
620         }
621         else if( type == reqtype )
622             break; /* found */
623         buffer += n; buflen -=n;
624     }
625     buffer++;
626     n--;
627     if( n > buflen )
628         goto too_short;
629     if( ret_n )
630         *ret_n = n;
631     switch( type ) {
632       case SIGSUBPKT_SIG_CREATED:
633         if( n < 4 )
634             break;
635         return buffer;
636       case SIGSUBPKT_ISSUER:/* issuer key ID */
637         if( n < 8 )
638             break;
639         return buffer;
640       case SIGSUBPKT_PRIV_ADD_SIG:
641         /* because we use private data, we check the GNUPG marker */
642         if( n < 24 )
643             break;
644         if( buffer[0] != 'G' || buffer[1] != 'P' || buffer[2] != 'G' )
645             return NULL;
646         return buffer+3;
647       default: BUG(); /* not yet needed */
648     }
649     log_error("subpacket of type %d too short\n", type);
650     return NULL;
651
652   too_short:
653     log_error("buffer shorter than subpacket\n");
654     return NULL;
655 }
656
657
658 static int
659 parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
660                                           PKT_signature *sig )
661 {
662     int md5_len=0;
663     unsigned n;
664     int is_v4=0;
665     int rc=0;
666
667     if( pktlen < 16 ) {
668         log_error("packet(%d) too short\n", pkttype);
669         goto leave;
670     }
671     sig->version = iobuf_get_noeof(inp); pktlen--;
672     if( sig->version == 4 )
673         is_v4=1;
674     else if( sig->version != 2 && sig->version != 3 ) {
675         log_error("packet(%d) with unknown version %d\n", pkttype, sig->version);
676         goto leave;
677     }
678
679     if( !is_v4 ) {
680         md5_len = iobuf_get_noeof(inp); pktlen--;
681     }
682     sig->sig_class = iobuf_get_noeof(inp); pktlen--;
683     if( !is_v4 ) {
684         sig->timestamp = read_32(inp); pktlen -= 4;
685         sig->keyid[0] = read_32(inp); pktlen -= 4;
686         sig->keyid[1] = read_32(inp); pktlen -= 4;
687     }
688     sig->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
689     sig->digest_algo = iobuf_get_noeof(inp); pktlen--;
690     if( is_v4 ) { /* read subpackets */
691         n = read_16(inp); pktlen -= 2; /* length of hashed data */
692         if( n > 10000 ) {
693             log_error("signature packet: hashed data too long\n");
694             rc = G10ERR_INVALID_PACKET;
695             goto leave;
696         }
697         if( n ) {
698             sig->hashed_data = m_alloc( n + 2 );
699             sig->hashed_data[0] = n << 8;
700             sig->hashed_data[1] = n;
701             if( iobuf_read(inp, sig->hashed_data+2, n ) != n ) {
702                 log_error("premature eof while reading hashed signature data\n");
703                 rc = -1;
704                 goto leave;
705             }
706             pktlen -= n;
707         }
708         n = read_16(inp); pktlen -= 2; /* length of unhashed data */
709         if( n > 10000 ) {
710             log_error("signature packet: unhashed data too long\n");
711             rc = G10ERR_INVALID_PACKET;
712             goto leave;
713         }
714         if( n ) {
715             sig->unhashed_data = m_alloc( n + 2 );
716             sig->unhashed_data[0] = n << 8;
717             sig->unhashed_data[1] = n;
718             if( iobuf_read(inp, sig->unhashed_data+2, n ) != n ) {
719                 log_error("premature eof while reading unhashed signature data\n");
720                 rc = -1;
721                 goto leave;
722             }
723             pktlen -= n;
724         }
725     }
726
727     if( pktlen < 5 ) { /* sanity check */
728         log_error("packet(%d) too short\n", pkttype);
729         rc = G10ERR_INVALID_PACKET;
730         goto leave;
731     }
732
733     sig->digest_start[0] = iobuf_get_noeof(inp); pktlen--;
734     sig->digest_start[1] = iobuf_get_noeof(inp); pktlen--;
735
736     if( is_v4 ) { /*extract required information */
737         const byte *p;
738         p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_SIG_CREATED, NULL );
739         if( !p )
740             log_error("signature packet without timestamp\n");
741         else
742             sig->timestamp = buffer_to_u32(p);
743         p = parse_sig_subpkt( sig->unhashed_data, SIGSUBPKT_ISSUER, NULL );
744         if( !p )
745             log_error("signature packet without keyid\n");
746         else {
747             sig->keyid[0] = buffer_to_u32(p);
748             sig->keyid[1] = buffer_to_u32(p+4);
749         }
750     }
751
752     if( list_mode ) {
753         printf(":signature packet: algo %d, keyid %08lX%08lX\n"
754                "\tversion %d, created %lu, md5len %d, sigclass %02x\n"
755                "\tdigest algo %d, begin of digest %02x %02x\n",
756                 sig->pubkey_algo,
757                 (ulong)sig->keyid[0], (ulong)sig->keyid[1],
758                 sig->version, (ulong)sig->timestamp, md5_len, sig->sig_class,
759                 sig->digest_algo,
760                 sig->digest_start[0], sig->digest_start[1] );
761         if( is_v4 ) {
762             parse_sig_subpkt( sig->hashed_data,  SIGSUBPKT_LIST_HASHED, NULL );
763             parse_sig_subpkt( sig->unhashed_data,SIGSUBPKT_LIST_UNHASHED, NULL);
764         }
765     }
766     if( is_ELGAMAL(sig->pubkey_algo) ) {
767         n = pktlen;
768         sig->d.elg.a = mpi_read(inp, &n, 0 ); pktlen -=n;
769         n = pktlen;
770         sig->d.elg.b = mpi_read(inp, &n, 0 ); pktlen -=n;
771         if( list_mode ) {
772             printf("\telg a: ");
773             mpi_print(stdout, sig->d.elg.a, mpi_print_mode );
774             printf("\n\telg b: ");
775             mpi_print(stdout, sig->d.elg.b, mpi_print_mode );
776             putchar('\n');
777         }
778     }
779     else if( sig->pubkey_algo == PUBKEY_ALGO_DSA ) {
780         n = pktlen;
781         sig->d.dsa.r = mpi_read(inp, &n, 0 ); pktlen -=n;
782         n = pktlen;
783         sig->d.dsa.s = mpi_read(inp, &n, 0 ); pktlen -=n;
784         if( list_mode ) {
785             printf("\tdsa r: ");
786             mpi_print(stdout, sig->d.elg.a, mpi_print_mode );
787             printf("\n\tdsa s: ");
788             mpi_print(stdout, sig->d.elg.b, mpi_print_mode );
789             putchar('\n');
790         }
791     }
792     else if( is_RSA(sig->pubkey_algo) ) {
793         n = pktlen;
794         sig->d.rsa.rsa_integer = mpi_read(inp, &n, 0 ); pktlen -=n;
795         if( list_mode ) {
796             printf("\trsa integer: ");
797             mpi_print(stdout, sig->d.rsa.rsa_integer, mpi_print_mode );
798             putchar('\n');
799         }
800     }
801     else if( list_mode )
802         printf("\tunknown algorithm %d\n", sig->pubkey_algo );
803
804
805   leave:
806     skip_rest(inp, pktlen);
807     return rc;
808 }
809
810
811 static int
812 parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
813                                              PKT_onepass_sig *ops )
814 {
815     int version;
816
817     if( pktlen < 13 ) {
818         log_error("packet(%d) too short\n", pkttype);
819         goto leave;
820     }
821     version = iobuf_get_noeof(inp); pktlen--;
822     if( version != 3 ) {
823         log_error("onepass_sig with unknown version %d\n", version);
824         goto leave;
825     }
826     ops->sig_class = iobuf_get_noeof(inp); pktlen--;
827     ops->digest_algo = iobuf_get_noeof(inp); pktlen--;
828     ops->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
829     ops->keyid[0] = read_32(inp); pktlen -= 4;
830     ops->keyid[1] = read_32(inp); pktlen -= 4;
831     ops->last = iobuf_get_noeof(inp); pktlen--;
832     if( list_mode )
833         printf(":onepass_sig packet: keyid %08lX%08lX\n"
834                "\tversion %d, sigclass %02x, digest %d, pubkey %d, last=%d\n",
835                 (ulong)ops->keyid[0], (ulong)ops->keyid[1],
836                 version, ops->sig_class,
837                 ops->digest_algo, ops->pubkey_algo, ops->last );
838
839
840   leave:
841     skip_rest(inp, pktlen);
842     return 0;
843 }
844
845
846
847
848 static int
849 parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
850                               byte *hdr, int hdrlen, PACKET *pkt )
851 {
852     int i, version, algorithm;
853     unsigned n;
854     unsigned long timestamp;
855     unsigned short valid_period;
856     int is_v4=0;
857     int rc=0;
858
859     version = iobuf_get_noeof(inp); pktlen--;
860     if( pkttype == PKT_PUBKEY_SUBCERT && version == '#' ) {
861         /* early versions of G10 use old PGP comments packets;
862          * luckily all those comments are started by a hash */
863         if( list_mode ) {
864             printf(":rfc1991 comment packet: \"" );
865             for( ; pktlen; pktlen-- ) {
866                 int c;
867                 c = iobuf_get_noeof(inp);
868                 if( c >= ' ' && c <= 'z' )
869                     putchar(c);
870                 else
871                     printf("\\x%02x", c );
872             }
873             printf("\"\n");
874         }
875         skip_rest(inp, pktlen);
876         return 0;
877     }
878     else if( version == 4 )
879         is_v4=1;
880     else if( version != 2 && version != 3 ) {
881         log_error("packet(%d) with unknown version %d\n", pkttype, version);
882         goto leave;
883     }
884
885     if( pktlen < 11 ) {
886         log_error("packet(%d) too short\n", pkttype);
887         goto leave;
888     }
889
890     timestamp = read_32(inp); pktlen -= 4;
891     if( is_v4 )
892         valid_period = 0;
893     else {
894         valid_period = read_16(inp); pktlen -= 2;
895     }
896     algorithm = iobuf_get_noeof(inp); pktlen--;
897     if( list_mode )
898         printf(":%s key packet:\n"
899                "\tversion %d, algo %d, created %lu, valid for %hu days\n",
900                 pkttype == PKT_PUBLIC_CERT? "public" :
901                 pkttype == PKT_SECRET_CERT? "secret" :
902                 pkttype == PKT_PUBKEY_SUBCERT? "public sub" :
903                 pkttype == PKT_SECKEY_SUBCERT? "secret sub" : "??",
904                 version, algorithm, timestamp, valid_period );
905     if( pkttype == PKT_SECRET_CERT || pkttype == PKT_SECKEY_SUBCERT )  {
906         pkt->pkt.secret_cert->timestamp = timestamp;
907         pkt->pkt.secret_cert->valid_days = valid_period;
908         pkt->pkt.secret_cert->hdrbytes = hdrlen;
909         pkt->pkt.secret_cert->version = version;
910         pkt->pkt.secret_cert->pubkey_algo = algorithm;
911     }
912     else {
913         pkt->pkt.public_cert->timestamp = timestamp;
914         pkt->pkt.public_cert->valid_days = valid_period;
915         pkt->pkt.public_cert->hdrbytes    = hdrlen;
916         pkt->pkt.public_cert->version     = version;
917         pkt->pkt.public_cert->pubkey_algo = algorithm;
918     }
919
920     if( is_ELGAMAL(algorithm) ) {
921         MPI elg_p, elg_g, elg_y;
922         n = pktlen; elg_p = mpi_read(inp, &n, 0 ); pktlen -=n;
923         n = pktlen; elg_g = mpi_read(inp, &n, 0 ); pktlen -=n;
924         n = pktlen; elg_y = mpi_read(inp, &n, 0 ); pktlen -=n;
925         if( list_mode ) {
926             printf(  "\telg p: ");
927             mpi_print(stdout, elg_p, mpi_print_mode  );
928             printf("\n\telg g: ");
929             mpi_print(stdout, elg_g, mpi_print_mode  );
930             printf("\n\telg y: ");
931             mpi_print(stdout, elg_y, mpi_print_mode  );
932             putchar('\n');
933         }
934         if( pkttype == PKT_PUBLIC_CERT || pkttype == PKT_PUBKEY_SUBCERT ) {
935             pkt->pkt.public_cert->d.elg.p = elg_p;
936             pkt->pkt.public_cert->d.elg.g = elg_g;
937             pkt->pkt.public_cert->d.elg.y = elg_y;
938         }
939         else {
940             PKT_secret_cert *cert = pkt->pkt.secret_cert;
941             byte temp[8];
942
943             pkt->pkt.secret_cert->d.elg.p = elg_p;
944             pkt->pkt.secret_cert->d.elg.g = elg_g;
945             pkt->pkt.secret_cert->d.elg.y = elg_y;
946             cert->protect.algo = iobuf_get_noeof(inp); pktlen--;
947             if( cert->protect.algo ) {
948                 cert->is_protected = 1;
949                 cert->protect.s2k.count = 0;
950                 if( cert->protect.algo == 255 ) {
951                     if( pktlen < 3 ) {
952                         rc = G10ERR_INVALID_PACKET;
953                         goto leave;
954                     }
955                     cert->protect.algo = iobuf_get_noeof(inp); pktlen--;
956                     cert->protect.s2k.mode  = iobuf_get_noeof(inp); pktlen--;
957                     cert->protect.s2k.hash_algo = iobuf_get_noeof(inp); pktlen--;
958                     switch( cert->protect.s2k.mode ) {
959                       case 1:
960                       case 4:
961                         for(i=0; i < 8 && pktlen; i++, pktlen-- )
962                             temp[i] = iobuf_get_noeof(inp);
963                         memcpy(cert->protect.s2k.salt, temp, 8 );
964                         break;
965                     }
966                     switch( cert->protect.s2k.mode ) {
967                       case 0: if( list_mode ) printf(  "\tsimple S2K" );
968                         break;
969                       case 1: if( list_mode ) printf(  "\tsalted S2K" );
970                         break;
971                       case 4: if( list_mode ) printf(  "\titer+salt S2K" );
972                         break;
973                       default:
974                         if( list_mode )
975                             printf(  "\tunknown S2K %d\n",
976                                                 cert->protect.s2k.mode );
977                         rc = G10ERR_INVALID_PACKET;
978                         goto leave;
979                     }
980
981                     if( list_mode ) {
982                         printf(", algo: %d, hash: %d",
983                                          cert->protect.algo,
984                                          cert->protect.s2k.hash_algo );
985                         if( cert->protect.s2k.mode == 1
986                             || cert->protect.s2k.mode == 4 ) {
987                             printf(", salt: ");
988                             for(i=0; i < 8; i++ )
989                                 printf("%02x", cert->protect.s2k.salt[i]);
990                         }
991                         putchar('\n');
992                     }
993
994                     if( cert->protect.s2k.mode == 4 ) {
995                         if( pktlen < 4 ) {
996                             rc = G10ERR_INVALID_PACKET;
997                             goto leave;
998                         }
999                         cert->protect.s2k.count = read_32(inp);
1000                         pktlen -= 4;
1001                     }
1002
1003                 }
1004                 else {
1005                     if( list_mode )
1006                         printf(  "\tprotect algo: %d\n",
1007                                                 cert->protect.algo);
1008                     /* old version, we don't have a S2K, so we fake one */
1009                     cert->protect.s2k.mode = 0;
1010                     /* We need this kludge to cope with old GNUPG versions */
1011                     cert->protect.s2k.hash_algo =
1012                          cert->protect.algo == CIPHER_ALGO_BLOWFISH160?
1013                                       DIGEST_ALGO_RMD160 : DIGEST_ALGO_MD5;
1014                 }
1015                 if( pktlen < 8 ) {
1016                     rc = G10ERR_INVALID_PACKET;
1017                     goto leave;
1018                 }
1019                 for(i=0; i < 8 && pktlen; i++, pktlen-- )
1020                     temp[i] = iobuf_get_noeof(inp);
1021                 if( list_mode ) {
1022                     printf(  "\tprotect IV: ");
1023                     for(i=0; i < 8; i++ )
1024                         printf(" %02x", temp[i] );
1025                     putchar('\n');
1026                 }
1027                 memcpy(cert->protect.iv, temp, 8 );
1028             }
1029             else
1030                 cert->is_protected = 0;
1031             /* It does not make sense to read it into secure memory.
1032              * If the user is so careless, not to protect his secret key,
1033              * we can assume, that he operates an open system :=(.
1034              * So we put the key into secure memory when we unprotect it. */
1035             n = pktlen; cert->d.elg.x = mpi_read(inp, &n, 0 ); pktlen -=n;
1036
1037             cert->csum = read_16(inp); pktlen -= 2;
1038             if( list_mode ) {
1039             printf("\telg x: ");
1040             mpi_print(stdout, cert->d.elg.x, mpi_print_mode  );
1041             putchar('\n');
1042                 printf("\t[secret value x is not shown]\n"
1043                        "\tchecksum: %04hx\n", cert->csum);
1044             }
1045           /*log_mpidump("elg p=", cert->d.elg.p );
1046             log_mpidump("elg g=", cert->d.elg.g );
1047             log_mpidump("elg y=", cert->d.elg.y );
1048             log_mpidump("elg x=", cert->d.elg.x ); */
1049         }
1050     }
1051     else if( algorithm == PUBKEY_ALGO_DSA ) {
1052         MPI dsa_p, dsa_q, dsa_g, dsa_y;
1053         n = pktlen; dsa_p = mpi_read(inp, &n, 0 ); pktlen -=n;
1054         n = pktlen; dsa_q = mpi_read(inp, &n, 0 ); pktlen -=n;
1055         n = pktlen; dsa_g = mpi_read(inp, &n, 0 ); pktlen -=n;
1056         n = pktlen; dsa_y = mpi_read(inp, &n, 0 ); pktlen -=n;
1057         if( list_mode ) {
1058             printf(  "\tdsa p: ");
1059             mpi_print(stdout, dsa_p, mpi_print_mode  );
1060             printf("\n\tdsa q: ");
1061             mpi_print(stdout, dsa_q, mpi_print_mode  );
1062             printf("\n\tdsa g: ");
1063             mpi_print(stdout, dsa_g, mpi_print_mode  );
1064             printf("\n\tdsa y: ");
1065             mpi_print(stdout, dsa_y, mpi_print_mode  );
1066             putchar('\n');
1067         }
1068         if( pkttype == PKT_PUBLIC_CERT || pkttype == PKT_PUBKEY_SUBCERT ) {
1069             pkt->pkt.public_cert->d.dsa.p = dsa_p;
1070             pkt->pkt.public_cert->d.dsa.q = dsa_q;
1071             pkt->pkt.public_cert->d.dsa.g = dsa_g;
1072             pkt->pkt.public_cert->d.dsa.y = dsa_y;
1073         }
1074         else {
1075             PKT_secret_cert *cert = pkt->pkt.secret_cert;
1076             byte temp[8];
1077
1078             pkt->pkt.secret_cert->d.dsa.p = dsa_p;
1079             pkt->pkt.secret_cert->d.dsa.q = dsa_q;
1080             pkt->pkt.secret_cert->d.dsa.g = dsa_g;
1081             pkt->pkt.secret_cert->d.dsa.y = dsa_y;
1082             cert->protect.algo = iobuf_get_noeof(inp); pktlen--;
1083             if( cert->protect.algo ) {
1084                 cert->is_protected = 1;
1085                 cert->protect.s2k.count = 0;
1086                 if( cert->protect.algo == 255 ) {
1087                     if( pktlen < 3 ) {
1088                         rc = G10ERR_INVALID_PACKET;
1089                         goto leave;
1090                     }
1091                     cert->protect.algo = iobuf_get_noeof(inp); pktlen--;
1092                     cert->protect.s2k.mode  = iobuf_get_noeof(inp); pktlen--;
1093                     cert->protect.s2k.hash_algo = iobuf_get_noeof(inp); pktlen--;
1094                     switch( cert->protect.s2k.mode ) {
1095                       case 1:
1096                       case 4:
1097                         for(i=0; i < 8 && pktlen; i++, pktlen-- )
1098                             temp[i] = iobuf_get_noeof(inp);
1099                         memcpy(cert->protect.s2k.salt, temp, 8 );
1100                         break;
1101                     }
1102                     switch( cert->protect.s2k.mode ) {
1103                       case 0: if( list_mode ) printf(  "\tsimple S2K" );
1104                         break;
1105                       case 1: if( list_mode ) printf(  "\tsalted S2K" );
1106                         break;
1107                       case 4: if( list_mode ) printf(  "\titer+salt S2K" );
1108                         break;
1109                       default:
1110                         if( list_mode )
1111                             printf(  "\tunknown S2K %d\n",
1112                                                     cert->protect.s2k.mode );
1113                         rc = G10ERR_INVALID_PACKET;
1114                         goto leave;
1115                     }
1116
1117                     if( list_mode ) {
1118                         printf(", algo: %d, hash: %d",
1119                                          cert->protect.algo,
1120                                          cert->protect.s2k.hash_algo );
1121                         if( cert->protect.s2k.mode == 1
1122                             || cert->protect.s2k.mode == 4 ){
1123                             printf(", salt: ");
1124                             for(i=0; i < 8; i++ )
1125                                 printf("%02x", cert->protect.s2k.salt[i]);
1126                         }
1127                         putchar('\n');
1128                     }
1129
1130                     if( cert->protect.s2k.mode == 4 ) {
1131                         if( pktlen < 4 ) {
1132                             rc = G10ERR_INVALID_PACKET;
1133                             goto leave;
1134                         }
1135                         cert->protect.s2k.count = read_32(inp);
1136                         pktlen -= 4;
1137                     }
1138
1139                 }
1140                 else {
1141                     if( list_mode )
1142                         printf(  "\tprotect algo: %d\n", cert->protect.algo);
1143                     /* old version, we don't have a S2K, so we fake one */
1144                     cert->protect.s2k.mode = 0;
1145                     cert->protect.s2k.hash_algo = DIGEST_ALGO_MD5;
1146                 }
1147                 if( pktlen < 8 ) {
1148                     rc = G10ERR_INVALID_PACKET;
1149                     goto leave;
1150                 }
1151                 for(i=0; i < 8 && pktlen; i++, pktlen-- )
1152                     temp[i] = iobuf_get_noeof(inp);
1153                 if( list_mode ) {
1154                     printf(  "\tprotect IV: ");
1155                     for(i=0; i < 8; i++ )
1156                         printf(" %02x", temp[i] );
1157                     putchar('\n');
1158                 }
1159                 memcpy(cert->protect.iv, temp, 8 );
1160             }
1161             else
1162                 cert->is_protected = 0;
1163             /* It does not make sense to read it into secure memory.
1164              * If the user is so careless, not to protect his secret key,
1165              * we can assume, that he operates an open system :=(.
1166              * So we put the key into secure memory when we unprotect it. */
1167             n = pktlen; cert->d.dsa.x = mpi_read(inp, &n, 0 ); pktlen -=n;
1168
1169             cert->csum = read_16(inp); pktlen -= 2;
1170             if( list_mode ) {
1171                 printf("\t[secret value x is not shown]\n"
1172                        "\tchecksum: %04hx\n", cert->csum);
1173             }
1174           /*log_mpidump("dsa p=", cert->d.dsa.p );
1175             log_mpidump("dsa q=", cert->d.dsa.q );
1176             log_mpidump("dsa g=", cert->d.dsa.g );
1177             log_mpidump("dsa y=", cert->d.dsa.y );
1178             log_mpidump("dsa x=", cert->d.dsa.x ); */
1179         }
1180     }
1181     else if( is_RSA(algorithm) ) {
1182         MPI rsa_pub_mod, rsa_pub_exp;
1183
1184         n = pktlen; rsa_pub_mod = mpi_read(inp, &n, 0); pktlen -=n;
1185         n = pktlen; rsa_pub_exp = mpi_read(inp, &n, 0 ); pktlen -=n;
1186         if( list_mode ) {
1187             printf(  "\tpublic modulus  n:  ");
1188             mpi_print(stdout, rsa_pub_mod, mpi_print_mode  );
1189             printf("\n\tpublic exponent e: ");
1190             mpi_print(stdout, rsa_pub_exp, mpi_print_mode  );
1191             putchar('\n');
1192         }
1193         if( pkttype == PKT_PUBLIC_CERT || pkttype == PKT_PUBKEY_SUBCERT ) {
1194             pkt->pkt.public_cert->d.rsa.n = rsa_pub_mod;
1195             pkt->pkt.public_cert->d.rsa.e = rsa_pub_exp;
1196         }
1197         else {
1198             PKT_secret_cert *cert = pkt->pkt.secret_cert;
1199             byte temp[8];
1200
1201             pkt->pkt.secret_cert->d.rsa.n = rsa_pub_mod;
1202             pkt->pkt.secret_cert->d.rsa.e = rsa_pub_exp;
1203             cert->protect.algo = iobuf_get_noeof(inp); pktlen--;
1204             if( list_mode )
1205                 printf(  "\tprotect algo: %d\n", cert->protect.algo);
1206             if( cert->protect.algo ) {
1207                 cert->is_protected = 1;
1208                 for(i=0; i < 8 && pktlen; i++, pktlen-- )
1209                     temp[i] = iobuf_get_noeof(inp);
1210                 if( list_mode ) {
1211                     printf(  "\tprotect IV: ");
1212                     for(i=0; i < 8; i++ )
1213                         printf(" %02x", temp[i] );
1214                     putchar('\n');
1215                 }
1216                 if( cert->protect.algo == CIPHER_ALGO_BLOWFISH160 )
1217                     memcpy(cert->protect.iv, temp, 8 );
1218             }
1219             else
1220                 cert->is_protected = 0;
1221             /* (See comments at the code for elg keys) */
1222             n = pktlen; cert->d.rsa.d = mpi_read(inp, &n, 0 ); pktlen -=n;
1223             n = pktlen; cert->d.rsa.p = mpi_read(inp, &n, 0 ); pktlen -=n;
1224             n = pktlen; cert->d.rsa.q = mpi_read(inp, &n, 0 ); pktlen -=n;
1225             n = pktlen; cert->d.rsa.u = mpi_read(inp, &n, 0 ); pktlen -=n;
1226
1227             cert->csum = read_16(inp); pktlen -= 2;
1228             if( list_mode ) {
1229                 printf("\t[secret values d,p,q,u are not shown]\n"
1230                        "\tchecksum: %04hx\n", cert->csum);
1231             }
1232          /* log_mpidump("rsa n=", cert->d.rsa.n );
1233             log_mpidump("rsa e=", cert->d.rsa.e );
1234             log_mpidump("rsa d=", cert->d.rsa.d );
1235             log_mpidump("rsa p=", cert->d.rsa.p );
1236             log_mpidump("rsa q=", cert->d.rsa.q );
1237             log_mpidump("rsa u=", cert->d.rsa.u ); */
1238         }
1239     }
1240     else if( list_mode )
1241         printf("\tunknown algorithm %d\n", algorithm );
1242
1243
1244   leave:
1245     skip_rest(inp, pktlen);
1246     return rc;
1247 }
1248
1249
1250 static int
1251 parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
1252 {
1253     byte *p;
1254
1255     packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id  + pktlen - 1);
1256     packet->pkt.user_id->len = pktlen;
1257     p = packet->pkt.user_id->name;
1258     for( ; pktlen; pktlen--, p++ )
1259         *p = iobuf_get_noeof(inp);
1260
1261     if( list_mode ) {
1262         int n = packet->pkt.user_id->len;
1263         printf(":user id packet: \"");
1264         for(p=packet->pkt.user_id->name; n; p++, n-- ) {
1265             if( *p >= ' ' && *p <= 'z' )
1266                 putchar(*p);
1267             else
1268                 printf("\\x%02x", *p );
1269         }
1270         printf("\"\n");
1271     }
1272     return 0;
1273 }
1274
1275
1276
1277 static int
1278 parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
1279 {
1280     byte *p;
1281
1282     packet->pkt.comment = m_alloc(sizeof *packet->pkt.comment + pktlen - 1);
1283     packet->pkt.comment->len = pktlen;
1284     p = packet->pkt.comment->data;
1285     for( ; pktlen; pktlen--, p++ )
1286         *p = iobuf_get_noeof(inp);
1287
1288     if( list_mode ) {
1289         int n = packet->pkt.comment->len;
1290         printf(":%scomment packet: \"", pkttype == PKT_OLD_COMMENT?
1291                                          "OpenPGP draft " : "" );
1292         for(p=packet->pkt.comment->data; n; p++, n-- ) {
1293             if( *p >= ' ' && *p <= 'z' )
1294                 putchar(*p);
1295             else
1296                 printf("\\x%02x", *p );
1297         }
1298         printf("\"\n");
1299     }
1300     return 0;
1301 }
1302
1303
1304 static void
1305 parse_trust( IOBUF inp, int pkttype, unsigned long pktlen )
1306 {
1307     int c;
1308
1309     c = iobuf_get_noeof(inp);
1310     if( list_mode )
1311         printf(":trust packet: flag=%02x\n", c );
1312 }
1313
1314
1315 static int
1316 parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
1317 {
1318     int mode, namelen;
1319     PKT_plaintext *pt;
1320     byte *p;
1321     int c, i;
1322
1323     if( pktlen && pktlen < 6 ) {
1324         log_error("packet(%d) too short (%lu)\n", pkttype, (ulong)pktlen);
1325         goto leave;
1326     }
1327     mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
1328     namelen = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
1329     pt = pkt->pkt.plaintext = m_alloc(sizeof *pkt->pkt.plaintext + namelen -1);
1330     pt->mode = mode;
1331     pt->namelen = namelen;
1332     if( pktlen ) {
1333         for( i=0; pktlen > 4 && i < namelen; pktlen--, i++ )
1334             pt->name[i] = iobuf_get_noeof(inp);
1335     }
1336     else {
1337         for( i=0; i < namelen; i++ )
1338             if( (c=iobuf_get(inp)) == -1 )
1339                 break;
1340             else
1341                 pt->name[i] = c;
1342     }
1343     pt->timestamp = read_32(inp); if( pktlen) pktlen -= 4;
1344     pt->len = pktlen;
1345     pt->buf = inp;
1346     pktlen = 0;
1347
1348     if( list_mode ) {
1349         printf(":literal data packet:\n"
1350                "\tmode %c, created %lu, name=\"",
1351                     mode >= ' ' && mode <'z'? mode : '?',
1352                     (ulong)pt->timestamp );
1353         for(p=pt->name,i=0; i < namelen; p++, i++ ) {
1354             if( *p >= ' ' && *p <= 'z' )
1355                 putchar(*p);
1356             else
1357                 printf("\\x%02x", *p );
1358         }
1359         printf("\",\n\traw data: %lu bytes\n", (ulong)pt->len );
1360     }
1361
1362   leave:
1363     return 0;
1364 }
1365
1366
1367 static int
1368 parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
1369 {
1370     PKT_compressed *zd;
1371
1372     /* pktlen is here 0, but data follows
1373      * (this should be the last object in a file or
1374      *  the compress algorithm should know the length)
1375      */
1376     zd = pkt->pkt.compressed =  m_alloc(sizeof *pkt->pkt.compressed );
1377     zd->len = 0; /* not yet used */
1378     zd->algorithm = iobuf_get_noeof(inp);
1379     zd->buf = inp;
1380     if( list_mode )
1381         printf(":compressed packet: algo=%d\n", zd->algorithm);
1382     return 0;
1383 }
1384
1385
1386 static int
1387 parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
1388 {
1389     PKT_encrypted *ed;
1390
1391     ed = pkt->pkt.encrypted =  m_alloc(sizeof *pkt->pkt.encrypted );
1392     ed->len = pktlen;
1393     ed->buf = NULL;
1394     if( pktlen && pktlen < 10 ) {
1395         log_error("packet(%d) too short\n", pkttype);
1396         skip_rest(inp, pktlen);
1397         goto leave;
1398     }
1399     if( list_mode ) {
1400         if( pktlen )
1401             printf(":encrypted data packet:\n\tlength: %lu\n", pktlen-10);
1402         else
1403             printf(":encrypted data packet:\n\tlength: unknown\n");
1404     }
1405
1406     ed->buf = inp;
1407     pktlen = 0;
1408
1409   leave:
1410     return 0;
1411 }
1412
1413
1414