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