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