ElGamal funktioniert und ist default
[gnupg.git] / g10 / parse-packet.c
1 /* parse-packet.c  - read packets
2  *      Copyright (c) 1997 by Werner Koch (dd9jn)
3  *
4  * This file is part of G10.
5  *
6  * G10 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  * G10 is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <assert.h>
26
27 #include "packet.h"
28 #include "iobuf.h"
29 #include "mpi.h"
30 #include "util.h"
31 #include "cipher.h"
32 #include "memory.h"
33 #include "filter.h"
34 #include "options.h"
35
36 static mpi_print_mode = 0;
37 static list_mode = 0;
38
39 static void skip_packet( IOBUF inp, int pkttype, unsigned long pktlen );
40 static void skip_rest( IOBUF inp, unsigned long pktlen );
41 static int  parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen,
42                                                              PACKET *packet );
43 static int  parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
44                                                          PKT_signature *sig );
45 static int  parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
46                                       byte *hdr, int hdrlen, PACKET *packet );
47 static int  parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen,
48                                                            PACKET *packet );
49 static void parse_comment( IOBUF inp, int pkttype, unsigned long pktlen );
50 static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen );
51 static int  parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
52                                                                 PACKET *pkt );
53 static int  parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
54                                                            PACKET *packet );
55 static int  parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
56                                                            PACKET *packet );
57
58 static u16
59 checksum( byte *p )
60 {
61     u16 n, a;
62
63     n = *p++ << 8;
64     n |= *p++;
65     for(a=0; n; n-- )
66         a += *p++;
67     return a;
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 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 rc, ctb, pkttype, lenbytes;
111     unsigned long pktlen;
112     byte hdr[5];
113     int hdrlen;
114
115     assert( !pkt->pkt.generic );
116     if( (ctb = iobuf_get(inp)) == -1 )
117         return -1;
118     hdrlen=0;
119     hdr[hdrlen++] = ctb;
120     if( !(ctb & 0x80) ) {
121         log_error("invalid packet at '%s'\n", iobuf_where(inp) );
122         return G10ERR_INVALID_PACKET;
123     }
124     /* we handle the pgp 3 extensions here, so that we can skip such packets*/
125     pkttype =  ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf);
126     lenbytes = (ctb & 0x40) || ((ctb&3)==3)? 0 : (1<<(ctb & 3));
127     pktlen = 0;
128     if( !lenbytes ) {
129         pktlen = 0; /* don't know the value */
130         if( pkttype != PKT_COMPR_DATA )
131             iobuf_set_block_mode(inp, 1);
132     }
133     else {
134         for( ; lenbytes; lenbytes-- ) {
135             pktlen <<= 8;
136             pktlen |= hdr[hdrlen++] = iobuf_get_noeof(inp);
137         }
138     }
139
140     if( DBG_PACKET )
141         log_debug("parse_packet(iob=%d): type=%d length=%lu\n",
142                                             iobuf_id(inp), pkttype, pktlen );
143     pkt->pkttype = pkttype;
144     rc = G10ERR_UNKNOWN_PACKET; /* default to no error */
145     switch( pkttype ) {
146       case PKT_PUBKEY_CERT:
147         pkt->pkt.pubkey_cert = m_alloc_clear(sizeof *pkt->pkt.pubkey_cert );
148         rc = parse_certificate(inp, pkttype, pktlen, hdr, hdrlen, pkt );
149         break;
150       case PKT_SECKEY_CERT:
151       case PKT_SECKEY_SUBCERT:
152         pkt->pkt.seckey_cert = m_alloc_clear(sizeof *pkt->pkt.seckey_cert );
153         rc = parse_certificate(inp, pkttype, pktlen, hdr, hdrlen, pkt );
154         break;
155       case PKT_PUBKEY_ENC:
156         rc = parse_publickey(inp, pkttype, pktlen, pkt );
157         break;
158       case PKT_SIGNATURE:
159         pkt->pkt.signature = m_alloc_clear(sizeof *pkt->pkt.signature );
160         rc = parse_signature(inp, pkttype, pktlen, pkt->pkt.signature );
161         break;
162       case PKT_USER_ID:
163         rc = parse_user_id(inp, pkttype, pktlen, pkt );
164         break;
165       case PKT_COMMENT:
166         parse_comment(inp, pkttype, pktlen);
167         break;
168       case PKT_RING_TRUST:
169         parse_trust(inp, pkttype, pktlen);
170         break;
171       case PKT_PLAINTEXT:
172         rc = parse_plaintext(inp, pkttype, pktlen, pkt );
173         break;
174       case PKT_COMPR_DATA:
175         rc = parse_compressed(inp, pkttype, pktlen, pkt );
176         break;
177       case PKT_ENCR_DATA:
178         rc = parse_encrypted(inp, pkttype, pktlen, pkt );
179         break;
180       default:
181         skip_packet(inp, pkttype, pktlen);
182         break;
183     }
184
185     return rc;
186 }
187
188
189 static void
190 skip_packet( IOBUF inp, int pkttype, unsigned long pktlen )
191 {
192     if( list_mode )
193         printf(":unknown packet: type %2d, length %lu\n", pkttype, pktlen );
194     skip_rest(inp,pktlen);
195 }
196
197 static void
198 skip_rest( IOBUF inp, unsigned long pktlen )
199 {
200     if( iobuf_in_block_mode(inp) ) {
201         while( iobuf_get(inp) != -1 )
202                 ;
203     }
204     else {
205         for( ; pktlen; pktlen-- )
206             iobuf_get(inp);
207     }
208 }
209
210
211 static int
212 parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
213 {
214     int version;
215     unsigned n;
216     PKT_pubkey_enc *k;
217
218     k = packet->pkt.pubkey_enc = m_alloc(sizeof *packet->pkt.pubkey_enc );
219     if( pktlen < 12 ) {
220         log_error("packet(%d) too short\n", pkttype);
221         goto leave;
222     }
223     version = iobuf_get_noeof(inp); pktlen--;
224     if( version != 2 && version != 3 ) {
225         log_error("packet(%d) with unknown version %d\n", pkttype, version);
226         goto leave;
227     }
228     k->keyid[0] = read_32(inp); pktlen -= 4;
229     k->keyid[1] = read_32(inp); pktlen -= 4;
230     k->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
231     if( list_mode )
232         printf(":public key packet: keyid %08lX%08lX\n",
233                                         k->keyid[0], k->keyid[1]);
234     if( k->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
235         n = pktlen;
236         k->d.elg.a = mpi_decode(inp, &n ); pktlen -=n;
237         k->d.elg.b = mpi_decode(inp, &n ); pktlen -=n;
238         if( list_mode ) {
239             printf("\telg a: ");
240             mpi_print(stdout, k->d.elg.a, mpi_print_mode );
241             printf("\n\telg b: ");
242             mpi_print(stdout, k->d.elg.b, mpi_print_mode );
243             putchar('\n');
244         }
245     }
246     else if( k->pubkey_algo == PUBKEY_ALGO_RSA ) {
247         n = pktlen;
248         k->d.rsa.rsa_integer = mpi_decode(inp, &n ); pktlen -=n;
249         if( list_mode ) {
250             printf("\trsa integer: ");
251             mpi_print(stdout, k->d.rsa.rsa_integer, mpi_print_mode );
252             putchar('\n');
253         }
254     }
255     else if( list_mode )
256         printf("\tunknown algorithm %d\n", k->pubkey_algo );
257
258
259   leave:
260     skip_rest(inp, pktlen);
261     return 0;
262 }
263
264
265 static int
266 parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
267                                           PKT_signature *sig )
268 {
269     int version, md5_len;
270     unsigned n;
271
272     if( pktlen < 16 ) {
273         log_error("packet(%d) too short\n", pkttype);
274         goto leave;
275     }
276     version = iobuf_get_noeof(inp); pktlen--;
277     if( version != 2 && version != 3 ) {
278         log_error("packet(%d) with unknown version %d\n", pkttype, version);
279         goto leave;
280     }
281     md5_len = iobuf_get_noeof(inp); pktlen--;
282     sig->sig_class = iobuf_get_noeof(inp); pktlen--;
283     sig->timestamp = read_32(inp); pktlen -= 4;
284     sig->keyid[0] = read_32(inp); pktlen -= 4;
285     sig->keyid[1] = read_32(inp); pktlen -= 4;
286     sig->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
287     if( list_mode )
288         printf(":signature packet: keyid %08lX%08lX\n"
289                "\tversion %d, created %lu, md5len %d, sigclass %02x\n",
290                 sig->keyid[0], sig->keyid[1],
291                 version, sig->timestamp, md5_len, sig->sig_class );
292     if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
293         if( pktlen < 5 ) {
294             log_error("packet(%d) too short\n", pkttype);
295             goto leave;
296         }
297         sig->d.elg.digest_algo = iobuf_get_noeof(inp); pktlen--;
298         sig->d.elg.digest_start[0] = iobuf_get_noeof(inp); pktlen--;
299         sig->d.elg.digest_start[1] = iobuf_get_noeof(inp); pktlen--;
300         n = pktlen;
301         sig->d.elg.a = mpi_decode(inp, &n ); pktlen -=n;
302         sig->d.elg.b = mpi_decode(inp, &n ); pktlen -=n;
303         if( list_mode ) {
304             printf("\tdigest algo %d, begin of digest %02x %02x\n",
305                     sig->d.elg.digest_algo,
306                     sig->d.elg.digest_start[0], sig->d.elg.digest_start[1] );
307             printf("\telg a: ");
308             mpi_print(stdout, sig->d.elg.a, mpi_print_mode );
309             printf("\n\telg b: ");
310             mpi_print(stdout, sig->d.elg.a, mpi_print_mode );
311             putchar('\n');
312         }
313     }
314     else if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) {
315         if( pktlen < 5 ) {
316             log_error("packet(%d) too short\n", pkttype);
317             goto leave;
318         }
319         sig->d.rsa.digest_algo = iobuf_get_noeof(inp); pktlen--;
320         sig->d.rsa.digest_start[0] = iobuf_get_noeof(inp); pktlen--;
321         sig->d.rsa.digest_start[1] = iobuf_get_noeof(inp); pktlen--;
322         n = pktlen;
323         sig->d.rsa.rsa_integer = mpi_decode(inp, &n ); pktlen -=n;
324         if( list_mode ) {
325             printf("\tdigest algo %d, begin of digest %02x %02x\n",
326                     sig->d.rsa.digest_algo,
327                     sig->d.rsa.digest_start[0], sig->d.rsa.digest_start[1] );
328             printf("\trsa integer: ");
329             mpi_print(stdout, sig->d.rsa.rsa_integer, mpi_print_mode );
330             putchar('\n');
331         }
332     }
333     else if( list_mode )
334         printf("\tunknown algorithm %d\n", sig->pubkey_algo );
335
336
337   leave:
338     skip_rest(inp, pktlen);
339     return 0;
340 }
341
342
343
344
345 static int
346 parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
347                               byte *hdr, int hdrlen, PACKET *pkt )
348 {
349     int i, version, algorithm;
350     unsigned n;
351     unsigned long timestamp;
352     unsigned short valid_period;
353     int is_v4=0;
354
355     if( pkttype == PKT_PUBKEY_CERT ) {
356         pkt->pkt.pubkey_cert->mfx.md5 = md5_open(0);
357         pkt->pkt.pubkey_cert->mfx.rmd160 = rmd160_open(0);
358         pkt->pkt.pubkey_cert->mfx.maxbuf_size = 1;
359         md5_write(pkt->pkt.pubkey_cert->mfx.md5, hdr, hdrlen);
360         rmd160_write(pkt->pkt.pubkey_cert->mfx.rmd160, hdr, hdrlen);
361         iobuf_push_filter( inp, md_filter, &pkt->pkt.pubkey_cert->mfx );
362     }
363
364     if( pktlen < 12 ) {
365         log_error("packet(%d) too short\n", pkttype);
366         goto leave;
367     }
368     version = iobuf_get_noeof(inp); pktlen--;
369     if( version == 4 )
370         is_v4=1;
371     else if( version != 2 && version != 3 ) {
372         log_error("packet(%d) with unknown version %d\n", pkttype, version);
373         goto leave;
374     }
375
376     timestamp = read_32(inp); pktlen -= 4;
377     if( is_v4 )
378         valid_period = 0;
379     else
380         valid_period = read_16(inp); pktlen -= 2;
381     algorithm = iobuf_get_noeof(inp); pktlen--;
382     if( list_mode )
383         printf(":%s key certification packet:\n"
384                "\tversion %d, created %lu, valid for %hu days\n",
385                 pkttype == PKT_PUBKEY_CERT? "public": "secret",
386                 version, timestamp, valid_period );
387     if( pkttype == PKT_SECKEY_CERT )  {
388         pkt->pkt.seckey_cert->timestamp = timestamp;
389         pkt->pkt.seckey_cert->valid_days = valid_period;
390         pkt->pkt.seckey_cert->pubkey_algo = algorithm;
391     }
392     else {
393         pkt->pkt.pubkey_cert->timestamp = timestamp;
394         pkt->pkt.pubkey_cert->valid_days = valid_period;
395         pkt->pkt.pubkey_cert->pubkey_algo = algorithm;
396     }
397
398     if( algorithm == PUBKEY_ALGO_ELGAMAL ) {
399         MPI elg_p, elg_g, elg_y;
400         n = pktlen; elg_p = mpi_decode(inp, &n ); pktlen -=n;
401         n = pktlen; elg_g = mpi_decode(inp, &n ); pktlen -=n;
402         n = pktlen; elg_y = mpi_decode(inp, &n ); pktlen -=n;
403         if( list_mode ) {
404             printf(  "\telg p:  ");
405             mpi_print(stdout, elg_p, mpi_print_mode  );
406             printf("\n\telg g: ");
407             mpi_print(stdout, elg_g, mpi_print_mode  );
408             printf("\n\telg y: ");
409             mpi_print(stdout, elg_y, mpi_print_mode  );
410             putchar('\n');
411         }
412         if( pkttype == PKT_PUBKEY_CERT ) {
413             pkt->pkt.pubkey_cert->d.elg.p = elg_p;
414             pkt->pkt.pubkey_cert->d.elg.g = elg_g;
415             pkt->pkt.pubkey_cert->d.elg.y = elg_y;
416         }
417         else {
418             PKT_seckey_cert *cert = pkt->pkt.seckey_cert;
419             byte temp[8];
420             byte *mpibuf;
421
422             pkt->pkt.seckey_cert->d.elg.p = elg_p;
423             pkt->pkt.seckey_cert->d.elg.g = elg_g;
424             pkt->pkt.seckey_cert->d.elg.y = elg_y;
425             cert->d.elg.protect_algo = iobuf_get_noeof(inp); pktlen--;
426             if( list_mode )
427                 printf(  "\tprotect algo: %d\n", cert->d.elg.protect_algo);
428             if( cert->d.elg.protect_algo ) {
429                 cert->d.elg.is_protected = 1;
430                 for(i=0; i < 8 && pktlen; i++, pktlen-- )
431                     temp[i] = iobuf_get_noeof(inp);
432                 if( list_mode ) {
433                     printf(  "\tprotect IV: ");
434                     for(i=0; i < 8; i++ )
435                         printf(" %02x", temp[i] );
436                     putchar('\n');
437                 }
438                 if( cert->d.elg.protect_algo == CIPHER_ALGO_BLOWFISH )
439                     memcpy(cert->d.elg.protect.blowfish.iv, temp, 8 );
440             }
441             else
442                 cert->d.elg.is_protected = 0;
443
444             n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2);
445             cert->d.elg.x = (MPI)mpibuf;
446
447             cert->d.elg.csum = read_16(inp); pktlen -= 2;
448             cert->d.elg.calc_csum = 0;
449             if( list_mode ) {
450                 printf("\t[secret value x is not shown]\n"
451                        "\tchecksum: %04hx\n", cert->d.elg.csum);
452             }
453             if( !cert->d.elg.is_protected ) { /* convert buffer to MPIs */
454                 mpibuf = (byte*)cert->d.elg.x;
455                 cert->d.elg.calc_csum += checksum( mpibuf );
456                 cert->d.elg.x = mpi_decode_buffer( mpibuf );
457                 m_free( mpibuf );
458                 log_mpidump("elg p=", cert->d.elg.p );
459                 log_mpidump("elg g=", cert->d.elg.g );
460                 log_mpidump("elg y=", cert->d.elg.y );
461                 log_mpidump("elg x=", cert->d.elg.x );
462             }
463         }
464     }
465     else if( algorithm == PUBKEY_ALGO_RSA ) {
466         MPI rsa_pub_mod, rsa_pub_exp;
467
468         n = pktlen; rsa_pub_mod = mpi_decode(inp, &n ); pktlen -=n;
469         n = pktlen; rsa_pub_exp = mpi_decode(inp, &n ); pktlen -=n;
470         if( list_mode ) {
471             printf(  "\tpublic modulus  n:  ");
472             mpi_print(stdout, rsa_pub_mod, mpi_print_mode  );
473             printf("\n\tpublic exponent e: ");
474             mpi_print(stdout, rsa_pub_exp, mpi_print_mode  );
475             putchar('\n');
476         }
477         if( pkttype == PKT_PUBKEY_CERT ) {
478             pkt->pkt.pubkey_cert->d.rsa.rsa_n = rsa_pub_mod;
479             pkt->pkt.pubkey_cert->d.rsa.rsa_e = rsa_pub_exp;
480         }
481         else {
482             PKT_seckey_cert *cert = pkt->pkt.seckey_cert;
483             byte temp[8];
484             byte *mpibuf;
485
486             pkt->pkt.seckey_cert->d.rsa.rsa_n = rsa_pub_mod;
487             pkt->pkt.seckey_cert->d.rsa.rsa_e = rsa_pub_exp;
488             cert->d.rsa.protect_algo = iobuf_get_noeof(inp); pktlen--;
489             if( list_mode )
490                 printf(  "\tprotect algo: %d\n", cert->d.rsa.protect_algo);
491             if( cert->d.rsa.protect_algo ) {
492                 cert->d.rsa.is_protected = 1;
493                 for(i=0; i < 8 && pktlen; i++, pktlen-- )
494                     temp[i] = iobuf_get_noeof(inp);
495                 if( list_mode ) {
496                     printf(  "\tprotect IV: ");
497                     for(i=0; i < 8; i++ )
498                         printf(" %02x", temp[i] );
499                     putchar('\n');
500                 }
501                 if( cert->d.rsa.protect_algo == CIPHER_ALGO_BLOWFISH )
502                     memcpy(cert->d.rsa.protect.blowfish.iv, temp, 8 );
503             }
504             else
505                 cert->d.rsa.is_protected = 0;
506
507             n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2);
508             cert->d.rsa.rsa_d = (MPI)mpibuf;
509
510             n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2);
511             cert->d.rsa.rsa_p = (MPI)mpibuf;
512
513             n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2);
514             cert->d.rsa.rsa_q = (MPI)mpibuf;
515
516             n = pktlen; mpibuf = mpi_read(inp, &n ); pktlen -=n; assert(n>=2);
517             cert->d.rsa.rsa_u = (MPI)mpibuf;
518
519             cert->d.rsa.csum = read_16(inp); pktlen -= 2;
520             cert->d.rsa.calc_csum = 0;
521             if( list_mode ) {
522                 printf("\t[secret values d,p,q,u are not shown]\n"
523                        "\tchecksum: %04hx\n", cert->d.rsa.csum);
524             }
525             if( !cert->d.rsa.is_protected ) { /* convert buffer to MPIs */
526               #define X(a) do {                                         \
527                     mpibuf = (byte*)cert->d.rsa.rsa_##a;                \
528                     cert->d.rsa.calc_csum += checksum( mpibuf );        \
529                     cert->d.rsa.rsa_##a = mpi_decode_buffer( mpibuf );  \
530                     m_free( mpibuf );                                   \
531                 } while(0)
532                 X(d);
533                 X(p);
534                 X(q);
535                 X(u);
536               #undef X
537              /* log_mpidump("rsa n=", cert->d.rsa.rsa_n );
538                 log_mpidump("rsa e=", cert->d.rsa.rsa_e );
539                 log_mpidump("rsa d=", cert->d.rsa.rsa_d );
540                 log_mpidump("rsa p=", cert->d.rsa.rsa_p );
541                 log_mpidump("rsa q=", cert->d.rsa.rsa_q );
542                 log_mpidump("rsa u=", cert->d.rsa.rsa_u ); */
543             }
544         }
545     }
546     else if( list_mode )
547         printf("\tunknown algorithm %d\n", algorithm );
548
549
550   leave:
551     if( pkttype == PKT_PUBKEY_CERT )
552         iobuf_pop_filter( inp, md_filter, &pkt->pkt.pubkey_cert->mfx );
553     skip_rest(inp, pktlen);
554     return 0;
555 }
556
557
558 static int
559 parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
560 {
561     byte *p;
562
563     packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id  + pktlen - 1);
564     packet->pkt.user_id->len = pktlen;
565     p = packet->pkt.user_id->name;
566     for( ; pktlen; pktlen--, p++ )
567         *p = iobuf_get_noeof(inp);
568
569     if( list_mode ) {
570         int n = packet->pkt.user_id->len;
571         printf(":user id packet: \"");
572         for(p=packet->pkt.user_id->name; n; p++, n-- ) {
573             if( *p >= ' ' && *p <= 'z' )
574                 putchar(*p);
575             else
576                 printf("\\x%02x", *p );
577         }
578         printf("\"\n");
579     }
580     return 0;
581 }
582
583 static void
584 parse_comment( IOBUF inp, int pkttype, unsigned long pktlen )
585 {
586     if( list_mode ) {
587         printf(":comment packet: \"" );
588         for( ; pktlen; pktlen-- ) {
589             int c;
590             c = iobuf_get_noeof(inp);
591             if( c >= ' ' && c <= 'z' )
592                 putchar(c);
593             else
594                 printf("\\x%02x", c );
595         }
596         printf("\"\n");
597     }
598     skip_rest(inp, pktlen);
599 }
600
601
602 static void
603 parse_trust( IOBUF inp, int pkttype, unsigned long pktlen )
604 {
605     int c;
606
607     c = iobuf_get_noeof(inp);
608     if( list_mode )
609         printf(":trust packet: flag=%02x\n", c );
610   #if 0 /* fixme: depending on the context we have different interpretations*/
611     if( prev_packet_is_a_key_packet ) {
612         int ot = c & 7;   /* ownertrust bits (for the key owner) */
613
614             !ot ? "undefined" :
615         ot == 1 ? "unknown"   : /* we don't know the owner of this key */
616         ot == 2 ? "no"        : /* usually we do not trust this key owner */
617                                 /* to sign other keys */
618         ot == 5 ? "usually"   : /* usually we trust this key owner to sign */
619         ot == 6 ? "always"    : /* always trust this key owner to sign */
620         ot == 7 ? "ultimate"  : /* also present in the secret keyring */
621               ""                /* reserved value */
622         if( c & (1<<5) )
623             "key is disabled"
624         if( c & (1<<7) )
625             "buckstop"
626     else if( prev_packet_is_user_is_packet ) {
627             int kl = c & 3; /* keylegit bits */
628         0 = "unknown, undefined, or uninitialized trust"
629         1 = "we do not trust this key's ownership"
630         2 = "we have marginal confidence of this key's ownership"
631         3 = "we completely trust this key's ownership."
632          /* This one (3) requires either:
633           * - 1 ultimately trusted signature (SIGTRUST=7)
634           * - COMPLETES_NEEDED completely trusted signatures (SIGTRUST=6)
635           * - MARGINALS_NEEDED marginally trusted signatures (SIGTRUST=5)
636           */
637         if( c & 0x80 )
638             "warnonly"
639     else if( prev_packet_is_a_signature ) {
640          Bits 0-2 - SIGTRUST bits - Trust bits for this signature.  Value is
641                     copied directly from OWNERTRUST bits of signer:
642               000 - undefined, or uninitialized trust.
643               001 - unknown
644               010 - We do not trust this signature.
645               011 - reserved
646               100 - reserved
647               101 - We reasonably trust this signature.
648               110 - We completely trust this signature.
649               111 - ultimately trusted signature (from the owner of the ring)
650           Bit 6 - CHECKED bit - This means that the key checking pass (pgp -kc,
651                   also invoked automatically whenever keys are added to the
652                   keyring) has tested this signature and found it good.  If
653                   this bit is not set, the maintenance pass considers this
654                   signature untrustworthy.
655           Bit 7 - CONTIG bit - Means this signature leads up a contiguous trusted
656                   certification path all the way back to the ultimately-
657                   trusted keyring owner, where the buck stops.  This bit is derived
658                   from other trust packets.  It is currently not used for anything
659                   in PGP.
660     }
661   #endif
662 }
663
664
665 static int
666 parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
667 {
668     int mode, namelen;
669     PKT_plaintext *pt;
670     byte *p;
671     int c, i;
672
673     if( pktlen && pktlen < 6 ) {
674         log_error("packet(%d) too short (%lu)\n", pkttype, (ulong)pktlen);
675         goto leave;
676     }
677     mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
678     namelen = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
679     pt = pkt->pkt.plaintext = m_alloc(sizeof *pkt->pkt.plaintext + namelen -1);
680     pt->mode = mode;
681     pt->namelen = namelen;
682     if( pktlen ) {
683         for( i=0; pktlen > 4 && i < namelen; pktlen--, i++ )
684             pt->name[i] = iobuf_get_noeof(inp);
685     }
686     else {
687         for( i=0; i < namelen; i++ )
688             if( (c=iobuf_get(inp)) == -1 )
689                 break;
690             else
691                 pt->name[i] = c;
692     }
693     pt->timestamp = read_32(inp); if( pktlen) pktlen -= 4;
694     pt->len = pktlen;
695     pt->buf = inp;
696     pktlen = 0;
697
698     if( list_mode ) {
699         printf(":literal data packet:\n"
700                "\tmode %c, created %lu, name=\"",
701                     mode >= ' ' && mode <'z'? mode : '?',
702                     pt->timestamp );
703         for(p=pt->name,i=0; i < namelen; p++, i++ ) {
704             if( *p >= ' ' && *p <= 'z' )
705                 putchar(*p);
706             else
707                 printf("\\x%02x", *p );
708         }
709         printf("\",\n\traw data: %lu bytes\n", pt->len );
710     }
711
712   leave:
713     return 0;
714 }
715
716
717 static int
718 parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
719 {
720     PKT_compressed *zd;
721     int algorithm;
722
723     /* pktlen is here 0, but data follows
724      * (this should be the last object in a file or
725      *  the compress algorithm should know the length)
726      */
727     zd = pkt->pkt.compressed =  m_alloc(sizeof *pkt->pkt.compressed );
728     zd->len = 0; /* not yet used */
729     zd->algorithm = iobuf_get_noeof(inp);
730     zd->buf = inp;
731     if( list_mode )
732         printf(":compressed packet: algo=%d\n", zd->algorithm);
733     return 0;
734 }
735
736
737 static int
738 parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
739 {
740     PKT_encr_data *ed;
741
742     ed = pkt->pkt.encr_data =  m_alloc(sizeof *pkt->pkt.encr_data );
743     ed->len = pktlen;
744     ed->buf = NULL;
745     if( pktlen && pktlen < 10 ) {
746         log_error("packet(%d) too short\n", pkttype);
747         skip_rest(inp, pktlen);
748         goto leave;
749     }
750     if( list_mode )
751         if( pktlen )
752             printf(":encrypted data packet:\n\tlength: %lu\n", pktlen-10);
753         else
754             printf(":encrypted data packet:\n\tlength: unknown\n");
755
756     ed->buf = inp;
757     pktlen = 0;
758
759   leave:
760     return 0;
761 }
762
763