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