added option file handling
[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 int  parse( IOBUF inp, PACKET *pkt, int reqtype,
40                                            ulong *retpos, int *skip );
41 static void skip_packet( IOBUF inp, int pkttype, unsigned long pktlen );
42 static void skip_rest( IOBUF inp, unsigned long pktlen );
43 static int  parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen,
44                                                              PACKET *packet );
45 static int  parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
46                                                          PKT_signature *sig );
47 static int  parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
48                                                         PKT_onepass_sig *ops );
49 static int  parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
50                                       byte *hdr, int hdrlen, PACKET *packet );
51 static int  parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen,
52                                                            PACKET *packet );
53 static void parse_comment( IOBUF inp, int pkttype, unsigned long pktlen );
54 static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen );
55 static int  parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
56                                                                 PACKET *pkt );
57 static int  parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
58                                                            PACKET *packet );
59 static int  parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
60                                                            PACKET *packet );
61
62 static u16
63 checksum( byte *p )
64 {
65     u16 n, a;
66
67     n = *p++ << 8;
68     n |= *p++;
69     for(a=0; n; n-- )
70         a += *p++;
71     return a;
72 }
73
74 static unsigned short
75 read_16(IOBUF inp)
76 {
77     unsigned short a;
78     a = iobuf_get_noeof(inp) << 8;
79     a |= iobuf_get_noeof(inp);
80     return a;
81 }
82
83 static unsigned long
84 read_32(IOBUF inp)
85 {
86     unsigned long a;
87     a =  iobuf_get_noeof(inp) << 24;
88     a |= iobuf_get_noeof(inp) << 16;
89     a |= iobuf_get_noeof(inp) << 8;
90     a |= iobuf_get_noeof(inp);
91     return a;
92 }
93
94 int
95 set_packet_list_mode( int mode )
96 {
97     int old = list_mode;
98     list_mode = mode;
99     mpi_print_mode = DBG_MPI;
100     return old;
101 }
102
103 /****************
104  * Parse a Packet and return it in packet
105  * Returns: 0 := valid packet in pkt
106  *         -1 := no more packets
107  *         >0 := error
108  * Note: The function may return an error and a partly valid packet;
109  * caller must free this packet.
110  */
111 int
112 parse_packet( IOBUF inp, PACKET *pkt )
113 {
114     int skip, rc;
115
116     do {
117         rc = parse( inp, pkt, 0, NULL, &skip );
118     } while( skip );
119     return rc;
120 }
121
122 /****************
123  * Like parse packet, but do only return packet of the given type.
124  */
125 int
126 search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos )
127 {
128     int skip, rc;
129
130     do {
131         rc = parse( inp, pkt, pkttype, retpos, &skip );
132     } while( skip );
133     return rc;
134 }
135
136
137 /****************
138  * Parse packet. Set the variable skip points to to 1 if the packet
139  * should be skipped; this is the case if either there is a
140  * requested packet type and the parsed packet doesn't match or the
141  * packet-type is 0, indicating deleted stuff.
142  */
143 static int
144 parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos, int *skip )
145 {
146     int rc, ctb, pkttype, lenbytes;
147     unsigned long pktlen;
148     byte hdr[5];
149     int hdrlen;
150
151     *skip = 0;
152     assert( !pkt->pkt.generic );
153     if( retpos )
154         *retpos = iobuf_tell(inp);
155     if( (ctb = iobuf_get(inp)) == -1 )
156         return -1;
157     hdrlen=0;
158     hdr[hdrlen++] = ctb;
159     if( !(ctb & 0x80) ) {
160         log_error("invalid packet at '%s'\n", iobuf_where(inp) );
161         return G10ERR_INVALID_PACKET;
162     }
163     /* we handle the pgp 3 extensions here, so that we can skip such packets*/
164     pkttype =  ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf);
165     lenbytes = (ctb & 0x40) || ((ctb&3)==3)? 0 : (1<<(ctb & 3));
166     pktlen = 0;
167     if( !lenbytes ) {
168         pktlen = 0; /* don't know the value */
169         if( pkttype != PKT_COMPRESSED )
170             iobuf_set_block_mode(inp, 1);
171     }
172     else {
173         for( ; lenbytes; lenbytes-- ) {
174             pktlen <<= 8;
175             pktlen |= hdr[hdrlen++] = iobuf_get_noeof(inp);
176         }
177     }
178
179     if( !pkttype || (reqtype && pkttype != reqtype) ) {
180         skip_packet(inp, pkttype, pktlen);
181         *skip = 1;
182         return 0;
183     }
184
185     if( DBG_PACKET )
186         log_debug("parse_packet(iob=%d): type=%d length=%lu\n",
187                                             iobuf_id(inp), pkttype, pktlen );
188     pkt->pkttype = pkttype;
189     rc = G10ERR_UNKNOWN_PACKET; /* default to no error */
190     switch( pkttype ) {
191       case PKT_PUBLIC_CERT:
192         pkt->pkt.public_cert = m_alloc_clear(sizeof *pkt->pkt.public_cert );
193         rc = parse_certificate(inp, pkttype, pktlen, hdr, hdrlen, pkt );
194         break;
195       case PKT_SECRET_CERT:
196       case PKT_SECKEY_SUBCERT:
197         pkt->pkt.secret_cert = m_alloc_clear(sizeof *pkt->pkt.secret_cert );
198         rc = parse_certificate(inp, pkttype, pktlen, hdr, hdrlen, pkt );
199         break;
200       case PKT_PUBKEY_ENC:
201         rc = parse_publickey(inp, pkttype, pktlen, pkt );
202         break;
203       case PKT_SIGNATURE:
204         pkt->pkt.signature = m_alloc_clear(sizeof *pkt->pkt.signature );
205         rc = parse_signature(inp, pkttype, pktlen, pkt->pkt.signature );
206         break;
207       case PKT_ONEPASS_SIG:
208         pkt->pkt.onepass_sig = m_alloc_clear(sizeof *pkt->pkt.onepass_sig );
209         rc = parse_onepass_sig(inp, pkttype, pktlen, pkt->pkt.onepass_sig );
210         break;
211       case PKT_USER_ID:
212         rc = parse_user_id(inp, pkttype, pktlen, pkt );
213         break;
214       case PKT_COMMENT:
215         parse_comment(inp, pkttype, pktlen);
216         break;
217       case PKT_RING_TRUST:
218         parse_trust(inp, pkttype, pktlen);
219         break;
220       case PKT_PLAINTEXT:
221         rc = parse_plaintext(inp, pkttype, pktlen, pkt );
222         break;
223       case PKT_COMPRESSED:
224         rc = parse_compressed(inp, pkttype, pktlen, pkt );
225         break;
226       case PKT_ENCRYPTED:
227         rc = parse_encrypted(inp, pkttype, pktlen, pkt );
228         break;
229       default:
230         skip_packet(inp, pkttype, pktlen);
231         break;
232     }
233
234     return rc;
235 }
236
237
238 static void
239 skip_packet( IOBUF inp, int pkttype, unsigned long pktlen )
240 {
241     if( list_mode )
242         printf(":unknown packet: type %2d, length %lu\n", pkttype, pktlen );
243     skip_rest(inp,pktlen);
244 }
245
246 static void
247 skip_rest( IOBUF inp, unsigned long pktlen )
248 {
249     if( iobuf_in_block_mode(inp) ) {
250         while( iobuf_get(inp) != -1 )
251                 ;
252     }
253     else {
254         for( ; pktlen; pktlen-- )
255             iobuf_get(inp);
256     }
257 }
258
259
260 static int
261 parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
262 {
263     int version;
264     unsigned n;
265     PKT_pubkey_enc *k;
266
267     k = packet->pkt.pubkey_enc = m_alloc(sizeof *packet->pkt.pubkey_enc );
268     if( pktlen < 12 ) {
269         log_error("packet(%d) too short\n", pkttype);
270         goto leave;
271     }
272     version = iobuf_get_noeof(inp); pktlen--;
273     if( version != 2 && version != 3 ) {
274         log_error("packet(%d) with unknown version %d\n", pkttype, version);
275         goto leave;
276     }
277     k->keyid[0] = read_32(inp); pktlen -= 4;
278     k->keyid[1] = read_32(inp); pktlen -= 4;
279     k->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
280     if( list_mode )
281         printf(":public key packet: keyid %08lX%08lX\n",
282                                         k->keyid[0], k->keyid[1]);
283     if( k->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
284         n = pktlen;
285         k->d.elg.a = mpi_read(inp, &n, 0); pktlen -=n;
286         k->d.elg.b = mpi_read(inp, &n, 0 ); pktlen -=n;
287         if( list_mode ) {
288             printf("\telg a: ");
289             mpi_print(stdout, k->d.elg.a, mpi_print_mode );
290             printf("\n\telg b: ");
291             mpi_print(stdout, k->d.elg.b, mpi_print_mode );
292             putchar('\n');
293         }
294     }
295     else if( k->pubkey_algo == PUBKEY_ALGO_RSA ) {
296         n = pktlen;
297         k->d.rsa.rsa_integer = mpi_read(inp, &n, 0 ); pktlen -=n;
298         if( list_mode ) {
299             printf("\trsa integer: ");
300             mpi_print(stdout, k->d.rsa.rsa_integer, mpi_print_mode );
301             putchar('\n');
302         }
303     }
304     else if( list_mode )
305         printf("\tunknown algorithm %d\n", k->pubkey_algo );
306
307
308   leave:
309     skip_rest(inp, pktlen);
310     return 0;
311 }
312
313
314 static int
315 parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
316                                           PKT_signature *sig )
317 {
318     int version, md5_len;
319     unsigned n;
320
321     if( pktlen < 16 ) {
322         log_error("packet(%d) too short\n", pkttype);
323         goto leave;
324     }
325     version = iobuf_get_noeof(inp); pktlen--;
326     if( version != 2 && version != 3 ) {
327         log_error("packet(%d) with unknown version %d\n", pkttype, version);
328         goto leave;
329     }
330     md5_len = iobuf_get_noeof(inp); pktlen--;
331     sig->sig_class = iobuf_get_noeof(inp); pktlen--;
332     sig->timestamp = read_32(inp); pktlen -= 4;
333     sig->keyid[0] = read_32(inp); pktlen -= 4;
334     sig->keyid[1] = read_32(inp); pktlen -= 4;
335     sig->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
336     if( list_mode )
337         printf(":signature packet: keyid %08lX%08lX\n"
338                "\tversion %d, created %lu, md5len %d, sigclass %02x\n",
339                 sig->keyid[0], sig->keyid[1],
340                 version, sig->timestamp, md5_len, sig->sig_class );
341     if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
342         if( pktlen < 5 ) {
343             log_error("packet(%d) too short\n", pkttype);
344             goto leave;
345         }
346         sig->d.elg.digest_algo = iobuf_get_noeof(inp); pktlen--;
347         sig->d.elg.digest_start[0] = iobuf_get_noeof(inp); pktlen--;
348         sig->d.elg.digest_start[1] = iobuf_get_noeof(inp); pktlen--;
349         n = pktlen;
350         sig->d.elg.a = mpi_read(inp, &n, 0 ); pktlen -=n;
351         sig->d.elg.b = mpi_read(inp, &n, 0 ); pktlen -=n;
352         if( list_mode ) {
353             printf("\tdigest algo %d, begin of digest %02x %02x\n",
354                     sig->d.elg.digest_algo,
355                     sig->d.elg.digest_start[0], sig->d.elg.digest_start[1] );
356             printf("\telg a: ");
357             mpi_print(stdout, sig->d.elg.a, mpi_print_mode );
358             printf("\n\telg b: ");
359             mpi_print(stdout, sig->d.elg.b, mpi_print_mode );
360             putchar('\n');
361         }
362     }
363     else if( sig->pubkey_algo == PUBKEY_ALGO_RSA ) {
364         if( pktlen < 5 ) {
365             log_error("packet(%d) too short\n", pkttype);
366             goto leave;
367         }
368         sig->d.rsa.digest_algo = iobuf_get_noeof(inp); pktlen--;
369         sig->d.rsa.digest_start[0] = iobuf_get_noeof(inp); pktlen--;
370         sig->d.rsa.digest_start[1] = iobuf_get_noeof(inp); pktlen--;
371         n = pktlen;
372         sig->d.rsa.rsa_integer = mpi_read(inp, &n, 0 ); pktlen -=n;
373         if( list_mode ) {
374             printf("\tdigest algo %d, begin of digest %02x %02x\n",
375                     sig->d.rsa.digest_algo,
376                     sig->d.rsa.digest_start[0], sig->d.rsa.digest_start[1] );
377             printf("\trsa integer: ");
378             mpi_print(stdout, sig->d.rsa.rsa_integer, mpi_print_mode );
379             putchar('\n');
380         }
381     }
382     else if( list_mode )
383         printf("\tunknown algorithm %d\n", sig->pubkey_algo );
384
385
386   leave:
387     skip_rest(inp, pktlen);
388     return 0;
389 }
390
391
392 static int
393 parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
394                                              PKT_onepass_sig *ops )
395 {
396     int version;
397     unsigned n;
398
399     if( pktlen < 13 ) {
400         log_error("packet(%d) too short\n", pkttype);
401         goto leave;
402     }
403     version = iobuf_get_noeof(inp); pktlen--;
404     if( version != 3 ) {
405         log_error("onepass_sig with unknown version %d\n", version);
406         goto leave;
407     }
408     ops->sig_class = iobuf_get_noeof(inp); pktlen--;
409     ops->digest_algo = iobuf_get_noeof(inp); pktlen--;
410     ops->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
411     ops->keyid[0] = read_32(inp); pktlen -= 4;
412     ops->keyid[1] = read_32(inp); pktlen -= 4;
413     ops->last = iobuf_get_noeof(inp); pktlen--;
414     if( list_mode )
415         printf(":onepass_sig packet: keyid %08lX%08lX\n"
416                "\tversion %d, sigclass %02x, digest %d, pubkey %d, last=%d\n",
417                 ops->keyid[0], ops->keyid[1],
418                 version, ops->sig_class,
419                 ops->digest_algo, ops->pubkey_algo, ops->last );
420
421
422   leave:
423     skip_rest(inp, pktlen);
424     return 0;
425 }
426
427
428
429
430 static int
431 parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
432                               byte *hdr, int hdrlen, PACKET *pkt )
433 {
434     int i, version, algorithm;
435     unsigned n;
436     unsigned long timestamp;
437     unsigned short valid_period;
438     int is_v4=0;
439
440     if( pkttype == PKT_PUBLIC_CERT ) {
441         pkt->pkt.public_cert->mfx.md5 = md5_open(0);
442         pkt->pkt.public_cert->mfx.rmd160 = rmd160_open(0);
443         pkt->pkt.public_cert->mfx.maxbuf_size = 1;
444         md5_write(pkt->pkt.public_cert->mfx.md5, hdr, hdrlen);
445         rmd160_write(pkt->pkt.public_cert->mfx.rmd160, hdr, hdrlen);
446         iobuf_push_filter( inp, md_filter, &pkt->pkt.public_cert->mfx );
447     }
448
449     if( pktlen < 12 ) {
450         log_error("packet(%d) too short\n", pkttype);
451         goto leave;
452     }
453     version = iobuf_get_noeof(inp); pktlen--;
454     if( version == 4 )
455         is_v4=1;
456     else if( version != 2 && version != 3 ) {
457         log_error("packet(%d) with unknown version %d\n", pkttype, version);
458         goto leave;
459     }
460
461     timestamp = read_32(inp); pktlen -= 4;
462     if( is_v4 )
463         valid_period = 0;
464     else
465         valid_period = read_16(inp); pktlen -= 2;
466     algorithm = iobuf_get_noeof(inp); pktlen--;
467     if( list_mode )
468         printf(":%s key certification packet:\n"
469                "\tversion %d, created %lu, valid for %hu days\n",
470                 pkttype == PKT_PUBLIC_CERT? "public": "secret",
471                 version, timestamp, valid_period );
472     if( pkttype == PKT_SECRET_CERT )  {
473         pkt->pkt.secret_cert->timestamp = timestamp;
474         pkt->pkt.secret_cert->valid_days = valid_period;
475         pkt->pkt.secret_cert->pubkey_algo = algorithm;
476     }
477     else {
478         pkt->pkt.public_cert->timestamp = timestamp;
479         pkt->pkt.public_cert->valid_days = valid_period;
480         pkt->pkt.public_cert->pubkey_algo = algorithm;
481     }
482
483     if( algorithm == PUBKEY_ALGO_ELGAMAL ) {
484         MPI elg_p, elg_g, elg_y;
485         n = pktlen; elg_p = mpi_read(inp, &n, 0 ); pktlen -=n;
486         n = pktlen; elg_g = mpi_read(inp, &n, 0 ); pktlen -=n;
487         n = pktlen; elg_y = mpi_read(inp, &n, 0 ); pktlen -=n;
488         if( list_mode ) {
489             printf(  "\telg p:  ");
490             mpi_print(stdout, elg_p, mpi_print_mode  );
491             printf("\n\telg g: ");
492             mpi_print(stdout, elg_g, mpi_print_mode  );
493             printf("\n\telg y: ");
494             mpi_print(stdout, elg_y, mpi_print_mode  );
495             putchar('\n');
496         }
497         if( pkttype == PKT_PUBLIC_CERT ) {
498             pkt->pkt.public_cert->d.elg.p = elg_p;
499             pkt->pkt.public_cert->d.elg.g = elg_g;
500             pkt->pkt.public_cert->d.elg.y = elg_y;
501         }
502         else {
503             PKT_secret_cert *cert = pkt->pkt.secret_cert;
504             byte temp[8];
505             byte *mpibuf;
506
507             pkt->pkt.secret_cert->d.elg.p = elg_p;
508             pkt->pkt.secret_cert->d.elg.g = elg_g;
509             pkt->pkt.secret_cert->d.elg.y = elg_y;
510             cert->d.elg.protect_algo = iobuf_get_noeof(inp); pktlen--;
511             if( list_mode )
512                 printf(  "\tprotect algo: %d\n", cert->d.elg.protect_algo);
513             if( cert->d.elg.protect_algo ) {
514                 cert->d.elg.is_protected = 1;
515                 for(i=0; i < 8 && pktlen; i++, pktlen-- )
516                     temp[i] = iobuf_get_noeof(inp);
517                 if( list_mode ) {
518                     printf(  "\tprotect IV: ");
519                     for(i=0; i < 8; i++ )
520                         printf(" %02x", temp[i] );
521                     putchar('\n');
522                 }
523                 if( cert->d.elg.protect_algo == CIPHER_ALGO_BLOWFISH )
524                     memcpy(cert->d.elg.protect.blowfish.iv, temp, 8 );
525             }
526             else
527                 cert->d.elg.is_protected = 0;
528
529             n = pktlen; cert->d.elg.x = mpi_read(inp, &n, 1 ); pktlen -=n;
530
531             cert->d.elg.csum = read_16(inp); pktlen -= 2;
532             if( list_mode ) {
533                 printf("\t[secret value x is not shown]\n"
534                        "\tchecksum: %04hx\n", cert->d.elg.csum);
535             }
536           /*log_mpidump("elg p=", cert->d.elg.p );
537             log_mpidump("elg g=", cert->d.elg.g );
538             log_mpidump("elg y=", cert->d.elg.y );
539             log_mpidump("elg x=", cert->d.elg.x ); */
540         }
541     }
542     else if( algorithm == PUBKEY_ALGO_RSA ) {
543         MPI rsa_pub_mod, rsa_pub_exp;
544
545         n = pktlen; rsa_pub_mod = mpi_read(inp, &n, 0); pktlen -=n;
546         n = pktlen; rsa_pub_exp = mpi_read(inp, &n, 0 ); pktlen -=n;
547         if( list_mode ) {
548             printf(  "\tpublic modulus  n:  ");
549             mpi_print(stdout, rsa_pub_mod, mpi_print_mode  );
550             printf("\n\tpublic exponent e: ");
551             mpi_print(stdout, rsa_pub_exp, mpi_print_mode  );
552             putchar('\n');
553         }
554         if( pkttype == PKT_PUBLIC_CERT ) {
555             pkt->pkt.public_cert->d.rsa.rsa_n = rsa_pub_mod;
556             pkt->pkt.public_cert->d.rsa.rsa_e = rsa_pub_exp;
557         }
558         else {
559             PKT_secret_cert *cert = pkt->pkt.secret_cert;
560             byte temp[8];
561             byte *mpibuf;
562
563             pkt->pkt.secret_cert->d.rsa.rsa_n = rsa_pub_mod;
564             pkt->pkt.secret_cert->d.rsa.rsa_e = rsa_pub_exp;
565             cert->d.rsa.protect_algo = iobuf_get_noeof(inp); pktlen--;
566             if( list_mode )
567                 printf(  "\tprotect algo: %d\n", cert->d.rsa.protect_algo);
568             if( cert->d.rsa.protect_algo ) {
569                 cert->d.rsa.is_protected = 1;
570                 for(i=0; i < 8 && pktlen; i++, pktlen-- )
571                     temp[i] = iobuf_get_noeof(inp);
572                 if( list_mode ) {
573                     printf(  "\tprotect IV: ");
574                     for(i=0; i < 8; i++ )
575                         printf(" %02x", temp[i] );
576                     putchar('\n');
577                 }
578                 if( cert->d.rsa.protect_algo == CIPHER_ALGO_BLOWFISH )
579                     memcpy(cert->d.rsa.protect.blowfish.iv, temp, 8 );
580             }
581             else
582                 cert->d.rsa.is_protected = 0;
583
584             n = pktlen; cert->d.rsa.rsa_d = mpi_read(inp, &n, 1 ); pktlen -=n;
585             n = pktlen; cert->d.rsa.rsa_p = mpi_read(inp, &n, 1 ); pktlen -=n;
586             n = pktlen; cert->d.rsa.rsa_q = mpi_read(inp, &n, 1 ); pktlen -=n;
587             n = pktlen; cert->d.rsa.rsa_u = mpi_read(inp, &n, 1 ); pktlen -=n;
588
589             cert->d.rsa.csum = read_16(inp); pktlen -= 2;
590             if( list_mode ) {
591                 printf("\t[secret values d,p,q,u are not shown]\n"
592                        "\tchecksum: %04hx\n", cert->d.rsa.csum);
593             }
594          /* log_mpidump("rsa n=", cert->d.rsa.rsa_n );
595             log_mpidump("rsa e=", cert->d.rsa.rsa_e );
596             log_mpidump("rsa d=", cert->d.rsa.rsa_d );
597             log_mpidump("rsa p=", cert->d.rsa.rsa_p );
598             log_mpidump("rsa q=", cert->d.rsa.rsa_q );
599             log_mpidump("rsa u=", cert->d.rsa.rsa_u ); */
600         }
601     }
602     else if( list_mode )
603         printf("\tunknown algorithm %d\n", algorithm );
604
605
606   leave:
607     if( pkttype == PKT_PUBLIC_CERT )
608         iobuf_pop_filter( inp, md_filter, &pkt->pkt.public_cert->mfx );
609     skip_rest(inp, pktlen);
610     return 0;
611 }
612
613
614 static int
615 parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
616 {
617     byte *p;
618
619     packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id  + pktlen - 1);
620     packet->pkt.user_id->len = pktlen;
621     p = packet->pkt.user_id->name;
622     for( ; pktlen; pktlen--, p++ )
623         *p = iobuf_get_noeof(inp);
624
625     if( list_mode ) {
626         int n = packet->pkt.user_id->len;
627         printf(":user id packet: \"");
628         for(p=packet->pkt.user_id->name; n; p++, n-- ) {
629             if( *p >= ' ' && *p <= 'z' )
630                 putchar(*p);
631             else
632                 printf("\\x%02x", *p );
633         }
634         printf("\"\n");
635     }
636     return 0;
637 }
638
639 static void
640 parse_comment( IOBUF inp, int pkttype, unsigned long pktlen )
641 {
642     if( list_mode ) {
643         printf(":comment packet: \"" );
644         for( ; pktlen; pktlen-- ) {
645             int c;
646             c = iobuf_get_noeof(inp);
647             if( c >= ' ' && c <= 'z' )
648                 putchar(c);
649             else
650                 printf("\\x%02x", c );
651         }
652         printf("\"\n");
653     }
654     skip_rest(inp, pktlen);
655 }
656
657
658 static void
659 parse_trust( IOBUF inp, int pkttype, unsigned long pktlen )
660 {
661     int c;
662
663     c = iobuf_get_noeof(inp);
664     if( list_mode )
665         printf(":trust packet: flag=%02x\n", c );
666   #if 0 /* fixme: depending on the context we have different interpretations*/
667     if( prev_packet_is_a_key_packet ) {
668         int ot = c & 7;   /* ownertrust bits (for the key owner) */
669
670             !ot ? "undefined" :
671         ot == 1 ? "unknown"   : /* we don't know the owner of this key */
672         ot == 2 ? "no"        : /* usually we do not trust this key owner */
673                                 /* to sign other keys */
674         ot == 5 ? "usually"   : /* usually we trust this key owner to sign */
675         ot == 6 ? "always"    : /* always trust this key owner to sign */
676         ot == 7 ? "ultimate"  : /* also present in the secret keyring */
677               ""                /* reserved value */
678         if( c & (1<<5) )
679             "key is disabled"
680         if( c & (1<<7) )
681             "buckstop"
682     else if( prev_packet_is_user_is_packet ) {
683             int kl = c & 3; /* keylegit bits */
684         0 = "unknown, undefined, or uninitialized trust"
685         1 = "we do not trust this key's ownership"
686         2 = "we have marginal confidence of this key's ownership"
687         3 = "we completely trust this key's ownership."
688         if( c & 0x80 )
689             "warnonly"
690     else if( prev_packet_is_a_signature ) {
691     }
692   #endif
693 }
694
695
696 static int
697 parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
698 {
699     int mode, namelen;
700     PKT_plaintext *pt;
701     byte *p;
702     int c, i;
703
704     if( pktlen && pktlen < 6 ) {
705         log_error("packet(%d) too short (%lu)\n", pkttype, (ulong)pktlen);
706         goto leave;
707     }
708     mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
709     namelen = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
710     pt = pkt->pkt.plaintext = m_alloc(sizeof *pkt->pkt.plaintext + namelen -1);
711     pt->mode = mode;
712     pt->namelen = namelen;
713     if( pktlen ) {
714         for( i=0; pktlen > 4 && i < namelen; pktlen--, i++ )
715             pt->name[i] = iobuf_get_noeof(inp);
716     }
717     else {
718         for( i=0; i < namelen; i++ )
719             if( (c=iobuf_get(inp)) == -1 )
720                 break;
721             else
722                 pt->name[i] = c;
723     }
724     pt->timestamp = read_32(inp); if( pktlen) pktlen -= 4;
725     pt->len = pktlen;
726     pt->buf = inp;
727     pktlen = 0;
728
729     if( list_mode ) {
730         printf(":literal data packet:\n"
731                "\tmode %c, created %lu, name=\"",
732                     mode >= ' ' && mode <'z'? mode : '?',
733                     pt->timestamp );
734         for(p=pt->name,i=0; i < namelen; p++, i++ ) {
735             if( *p >= ' ' && *p <= 'z' )
736                 putchar(*p);
737             else
738                 printf("\\x%02x", *p );
739         }
740         printf("\",\n\traw data: %lu bytes\n", pt->len );
741     }
742
743   leave:
744     return 0;
745 }
746
747
748 static int
749 parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
750 {
751     PKT_compressed *zd;
752     int algorithm;
753
754     /* pktlen is here 0, but data follows
755      * (this should be the last object in a file or
756      *  the compress algorithm should know the length)
757      */
758     zd = pkt->pkt.compressed =  m_alloc(sizeof *pkt->pkt.compressed );
759     zd->len = 0; /* not yet used */
760     zd->algorithm = iobuf_get_noeof(inp);
761     zd->buf = inp;
762     if( list_mode )
763         printf(":compressed packet: algo=%d\n", zd->algorithm);
764     return 0;
765 }
766
767
768 static int
769 parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
770 {
771     PKT_encrypted *ed;
772
773     ed = pkt->pkt.encrypted =  m_alloc(sizeof *pkt->pkt.encrypted );
774     ed->len = pktlen;
775     ed->buf = NULL;
776     if( pktlen && pktlen < 10 ) {
777         log_error("packet(%d) too short\n", pkttype);
778         skip_rest(inp, pktlen);
779         goto leave;
780     }
781     if( list_mode )
782         if( pktlen )
783             printf(":encrypted data packet:\n\tlength: %lu\n", pktlen-10);
784         else
785             printf(":encrypted data packet:\n\tlength: unknown\n");
786
787     ed->buf = inp;
788     pktlen = 0;
789
790   leave:
791     return 0;
792 }
793
794