1 /* parse-packet.c - read packets
2 * Copyright (C) 1998 Free Software Foundation, Inc.
4 * This file is part of GNUPG.
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.
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.
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
38 static int mpi_print_mode = 0;
39 static int list_mode = 0;
41 static int parse( IOBUF inp, PACKET *pkt, int reqtype,
42 ulong *retpos, int *skip, IOBUF out, int do_skip );
43 static int copy_packet( IOBUF inp, IOBUF out, int pkttype,
44 unsigned long pktlen );
45 static void skip_packet( IOBUF inp, int pkttype, unsigned long pktlen );
46 static void skip_rest( IOBUF inp, unsigned long pktlen );
47 static void *read_rest( IOBUF inp, ulong *r_pktlen );
48 static int parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen,
50 static int parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen,
52 static int parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
54 static int parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
55 PKT_onepass_sig *ops );
56 static int parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
57 byte *hdr, int hdrlen, PACKET *packet );
58 static int parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen,
60 static int parse_comment( IOBUF inp, int pkttype, unsigned long pktlen,
62 static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen );
63 static int parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
64 PACKET *packet, int new_ctb);
65 static int parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
66 PACKET *packet, int new_ctb );
67 static int parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
68 PACKET *packet, int new_ctb);
75 a = iobuf_get_noeof(inp) << 8;
76 a |= iobuf_get_noeof(inp);
84 a = iobuf_get_noeof(inp) << 24;
85 a |= iobuf_get_noeof(inp) << 16;
86 a |= iobuf_get_noeof(inp) << 8;
87 a |= iobuf_get_noeof(inp);
93 set_packet_list_mode( int mode )
97 mpi_print_mode = DBG_MPI;
102 unknown_pubkey_warning( int algo )
104 static byte unknown_pubkey_algos[256];
107 if( !unknown_pubkey_algos[algo] ) {
109 log_info(_("can't handle public key algorithm %d\n"), algo );
110 unknown_pubkey_algos[algo] = 1;
115 * Parse a Packet and return it in packet
116 * Returns: 0 := valid packet in pkt
117 * -1 := no more packets
119 * Note: The function may return an error and a partly valid packet;
120 * caller must free this packet.
123 parse_packet( IOBUF inp, PACKET *pkt )
128 rc = parse( inp, pkt, 0, NULL, &skip, NULL, 0 );
134 * Like parse packet, but only return packets of the given type.
137 search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos )
142 rc = parse( inp, pkt, pkttype, retpos, &skip, NULL, 0 );
148 * Copy all packets from INP to OUT, thereby removing unused spaces.
151 copy_all_packets( IOBUF inp, IOBUF out )
157 } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0 )));
162 * Copy some packets from INP to OUT, thereby removing unused spaces.
163 * Stop at offset STOPoff (i.e. don't copy packets at this or later offsets)
166 copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff )
171 if( iobuf_tell(inp) >= stopoff )
174 } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0 )) );
179 * Skip over N packets
182 skip_some_packets( IOBUF inp, unsigned n )
187 for( ;n && !rc; n--) {
189 rc = parse( inp, &pkt, 0, NULL, &skip, NULL, 1 );
197 * Parse packet. Set the variable skip points to to 1 if the packet
198 * should be skipped; this is the case if either there is a
199 * requested packet type and the parsed packet doesn't match or the
200 * packet-type is 0, indicating deleted stuff.
201 * if OUT is not NULL, a special copymode is used.
204 parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos,
205 int *skip, IOBUF out, int do_skip )
207 int rc=0, c, ctb, pkttype, lenbytes;
208 unsigned long pktlen;
214 assert( !pkt->pkt.generic );
216 *retpos = iobuf_tell(inp);
217 if( (ctb = iobuf_get(inp)) == -1 ) {
223 if( !(ctb & 0x80) ) {
224 log_error("%s: invalid packet (ctb=%02x)\n", iobuf_where(inp), ctb );
225 rc = G10ERR_INVALID_PACKET;
229 new_ctb = !!(ctb & 0x40);
231 pkttype = ctb & 0x3f;
232 if( (c = iobuf_get(inp)) == -1 ) {
233 log_error("%s: 1st length byte missing\n", iobuf_where(inp) );
234 rc = G10ERR_INVALID_PACKET;
241 pktlen = (c - 192) * 256;
242 if( (c = iobuf_get(inp)) == -1 ) {
243 log_error("%s: 2nd length byte missing\n", iobuf_where(inp) );
244 rc = G10ERR_INVALID_PACKET;
250 else if( c == 255 ) {
251 pktlen = (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 24;
252 pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 16;
253 pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 8;
254 if( (c = iobuf_get(inp)) == -1 ) {
255 log_error("%s: 4 byte length invalid\n", iobuf_where(inp) );
256 rc = G10ERR_INVALID_PACKET;
259 pktlen |= (hdr[hdrlen++] = c );
261 else { /* partial body length */
262 iobuf_set_partial_block_mode(inp, c & 0xff);
263 pktlen = 0;/* to indicate partial length */
267 pkttype = (ctb>>2)&0xf;
268 lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3));
270 pktlen = 0; /* don't know the value */
271 if( pkttype != PKT_COMPRESSED )
272 iobuf_set_block_mode(inp, 1);
275 for( ; lenbytes; lenbytes-- ) {
277 pktlen |= hdr[hdrlen++] = iobuf_get_noeof(inp);
282 if( out && pkttype ) {
283 if( iobuf_write( out, hdr, hdrlen ) == -1 )
284 rc = G10ERR_WRITE_FILE;
286 rc = copy_packet(inp, out, pkttype, pktlen );
290 if( do_skip || !pkttype || (reqtype && pkttype != reqtype) ) {
291 skip_packet(inp, pkttype, pktlen);
298 log_debug("parse_packet(iob=%d): type=%d length=%lu%s\n",
299 iobuf_id(inp), pkttype, pktlen, new_ctb?" (new_ctb)":"" );
300 pkt->pkttype = pkttype;
301 rc = G10ERR_UNKNOWN_PACKET; /* default error */
304 case PKT_PUBLIC_SUBKEY:
305 pkt->pkt.public_key = m_alloc_clear(sizeof *pkt->pkt.public_key );
306 rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt );
309 case PKT_SECRET_SUBKEY:
310 pkt->pkt.secret_key = m_alloc_clear(sizeof *pkt->pkt.secret_key );
311 rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt );
314 rc = parse_symkeyenc( inp, pkttype, pktlen, pkt );
317 rc = parse_pubkeyenc(inp, pkttype, pktlen, pkt );
320 pkt->pkt.signature = m_alloc_clear(sizeof *pkt->pkt.signature );
321 rc = parse_signature(inp, pkttype, pktlen, pkt->pkt.signature );
323 case PKT_ONEPASS_SIG:
324 pkt->pkt.onepass_sig = m_alloc_clear(sizeof *pkt->pkt.onepass_sig );
325 rc = parse_onepass_sig(inp, pkttype, pktlen, pkt->pkt.onepass_sig );
328 rc = parse_user_id(inp, pkttype, pktlen, pkt );
330 case PKT_OLD_COMMENT:
332 rc = parse_comment(inp, pkttype, pktlen, pkt);
335 parse_trust(inp, pkttype, pktlen);
336 rc = G10ERR_UNKNOWN_PACKET;
339 rc = parse_plaintext(inp, pkttype, pktlen, pkt, new_ctb );
342 rc = parse_compressed(inp, pkttype, pktlen, pkt, new_ctb );
345 rc = parse_encrypted(inp, pkttype, pktlen, pkt, new_ctb );
348 skip_packet(inp, pkttype, pktlen);
353 if( !rc && iobuf_error(inp) )
354 rc = G10ERR_INV_KEYRING;
359 dump_hex_line( int c, int *i )
361 if( *i && !(*i%8) ) {
363 printf("\n%4d:", *i );
376 copy_packet( IOBUF inp, IOBUF out, int pkttype, unsigned long pktlen )
381 if( iobuf_in_block_mode(inp) ) {
382 while( (n = iobuf_read( inp, buf, 100 )) != -1 )
383 if( iobuf_write(out, buf, n ) )
384 return G10ERR_WRITE_FILE; /* write error */
386 else if( !pktlen && pkttype == PKT_COMPRESSED ) {
387 /* compressed packet, copy till EOF */
388 while( (n = iobuf_read( inp, buf, 100 )) != -1 )
389 if( iobuf_write(out, buf, n ) )
390 return G10ERR_WRITE_FILE; /* write error */
393 for( ; pktlen; pktlen -= n ) {
394 n = pktlen > 100 ? 100 : pktlen;
395 n = iobuf_read( inp, buf, n );
397 return G10ERR_READ_FILE;
398 if( iobuf_write(out, buf, n ) )
399 return G10ERR_WRITE_FILE; /* write error */
407 skip_packet( IOBUF inp, int pkttype, unsigned long pktlen )
410 printf(":unknown packet: type %2d, length %lu\n", pkttype, pktlen );
414 if( iobuf_in_block_mode(inp) ) {
415 while( (c=iobuf_get(inp)) != -1 )
416 dump_hex_line(c, &i);
419 for( ; pktlen; pktlen-- )
420 dump_hex_line(iobuf_get(inp), &i);
426 skip_rest(inp,pktlen);
430 skip_rest( IOBUF inp, unsigned long pktlen )
432 if( iobuf_in_block_mode(inp) ) {
433 while( iobuf_get(inp) != -1 )
437 for( ; pktlen; pktlen-- )
438 if( iobuf_get(inp) == -1 )
444 read_rest( IOBUF inp, ulong *r_pktlen )
448 size_t pktlen = *r_pktlen;
450 if( iobuf_in_block_mode(inp) ) {
451 log_error("read_rest: can't store stream data\n");
455 p = m_alloc( pktlen + 2 );
457 p[1] = pktlen & 0xff;
458 for(i=2; pktlen; pktlen--, i++ )
459 p[i] = iobuf_get(inp);
466 read_rest2( IOBUF inp, size_t pktlen )
471 if( iobuf_in_block_mode(inp) ) {
472 log_error("read_rest: can't store stream data\n");
476 p = m_alloc( pktlen );
477 for(i=0; pktlen; pktlen--, i++ )
478 p[i] = iobuf_get(inp);
486 parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
489 int i, version, s2kmode, cipher_algo, hash_algo, seskeylen, minlen;
492 log_error("packet(%d) too short\n", pkttype);
495 version = iobuf_get_noeof(inp); pktlen--;
497 log_error("packet(%d) with unknown version %d\n", pkttype, version);
500 if( pktlen > 200 ) { /* (we encode the seskeylen in a byte) */
501 log_error("packet(%d) too large\n", pkttype);
504 cipher_algo = iobuf_get_noeof(inp); pktlen--;
505 s2kmode = iobuf_get_noeof(inp); pktlen--;
506 hash_algo = iobuf_get_noeof(inp); pktlen--;
508 case 0: /* simple s2k */
511 case 1: /* salted s2k */
514 case 3: /* iterated+salted s2k */
518 log_error("unknown S2K %d\n", s2kmode );
521 if( minlen > pktlen ) {
522 log_error("packet with S2K %d too short\n", s2kmode );
525 seskeylen = pktlen - minlen;
526 k = packet->pkt.symkey_enc = m_alloc_clear( sizeof *packet->pkt.symkey_enc
528 k->version = version;
529 k->cipher_algo = cipher_algo;
530 k->s2k.mode = s2kmode;
531 k->s2k.hash_algo = hash_algo;
532 if( s2kmode == 1 || s2kmode == 3 ) {
533 for(i=0; i < 8 && pktlen; i++, pktlen-- )
534 k->s2k.salt[i] = iobuf_get_noeof(inp);
537 k->s2k.count = iobuf_get(inp); pktlen--;
539 k->seskeylen = seskeylen;
540 for(i=0; i < seskeylen && pktlen; i++, pktlen-- )
541 k->seskey[i] = iobuf_get_noeof(inp);
545 printf(":symkey enc packet: version %d, cipher %d, s2k %d, hash %d\n",
546 version, cipher_algo, s2kmode, hash_algo);
547 if( s2kmode == 1 || s2kmode == 3 ) {
549 for(i=0; i < 8; i++ )
550 printf("%02x", k->s2k.salt[i]);
552 printf(", count %lu\n", (ulong)k->s2k.count );
558 skip_rest(inp, pktlen);
563 parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
569 k = packet->pkt.pubkey_enc = m_alloc(sizeof *packet->pkt.pubkey_enc );
571 log_error("packet(%d) too short\n", pkttype);
574 k->version = iobuf_get_noeof(inp); pktlen--;
575 if( k->version != 2 && k->version != 3 ) {
576 log_error("packet(%d) with unknown version %d\n", pkttype, k->version);
579 k->keyid[0] = read_32(inp); pktlen -= 4;
580 k->keyid[1] = read_32(inp); pktlen -= 4;
581 k->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
582 k->throw_keyid = 0; /* only used as flag for build_packet */
584 printf(":pubkey enc packet: version %d, algo %d, keyid %08lX%08lX\n",
585 k->version, k->pubkey_algo, (ulong)k->keyid[0], (ulong)k->keyid[1]);
587 ndata = pubkey_get_nenc(k->pubkey_algo);
590 printf("\tunsupported algorithm %d\n", k->pubkey_algo );
591 unknown_pubkey_warning( k->pubkey_algo );
592 k->data[0] = NULL; /* no need to store the encrypted data */
595 for( i=0; i < ndata; i++ ) {
597 k->data[i] = mpi_read(inp, &n, 0); pktlen -=n;
600 mpi_print(stdout, k->data[i], mpi_print_mode );
607 skip_rest(inp, pktlen);
613 dump_sig_subpkt( int hashed, int type, int critical,
614 const char * buffer, size_t buflen, size_t length )
618 printf("\t%s%ssubpkt %d len %u (", /*)*/
619 critical ? "critical ":"",
620 hashed ? "hashed ":"", type, (unsigned)length );
623 if( length > buflen ) {
624 printf("too short: buffer is only %u)\n", (unsigned)buflen );
628 case SIGSUBPKT_SIG_CREATED:
630 printf("sig created %s", strtimestamp( buffer_to_u32(buffer) ) );
632 case SIGSUBPKT_SIG_EXPIRE:
634 printf("sig expires %s", strtimestamp( buffer_to_u32(buffer) ) );
636 case SIGSUBPKT_EXPORTABLE:
638 printf("%sexportable", *buffer? "":"not ");
640 case SIGSUBPKT_TRUST:
641 p = "trust signature";
643 case SIGSUBPKT_REGEXP:
644 p = "regular expression";
646 case SIGSUBPKT_REVOCABLE:
649 case SIGSUBPKT_KEY_EXPIRE:
651 printf("key expires %s", strtimestamp( buffer_to_u32(buffer) ) );
654 p = "additional recipient request";
656 case SIGSUBPKT_PREF_SYM:
657 p = "preferred symmetric algorithms";
659 case SIGSUBPKT_REV_KEY:
660 p = "revocation key";
662 case SIGSUBPKT_ISSUER:
664 printf("issuer key ID %08lX%08lX",
665 (ulong)buffer_to_u32(buffer),
666 (ulong)buffer_to_u32(buffer+4) );
668 case SIGSUBPKT_NOTATION:
671 case SIGSUBPKT_PREF_HASH:
672 p = "preferred hash algorithms";
674 case SIGSUBPKT_PREF_COMPR:
675 p = "preferred compression algorithms";
677 case SIGSUBPKT_KS_FLAGS:
678 p = "key server preferences";
680 case SIGSUBPKT_PREF_KS:
681 p = "preferred key server";
683 case SIGSUBPKT_PRIMARY_UID:
684 p = "primary user id";
686 case SIGSUBPKT_POLICY:
689 case SIGSUBPKT_KEY_FLAGS:
692 case SIGSUBPKT_SIGNERS_UID:
693 p = "signer's user id";
695 case SIGSUBPKT_PRIV_ADD_SIG:
696 p = "signs additional user id";
698 default: p = "?"; break;
701 printf("%s)\n", p? p: "");
705 parse_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype, size_t *ret_n )
714 buflen = (*buffer << 8) | buffer[1];
718 return NULL; /* end of packets; not found */
719 n = *buffer++; buflen--;
723 n = (buffer[0] << 24) | (buffer[1] << 16)
724 | (buffer[2] << 8) | buffer[3];
729 else if( n >= 192 ) {
732 n = (( n - 192 ) << 8) + *buffer + 192;
744 if( reqtype < 0 ) /* list packets */
745 dump_sig_subpkt( reqtype == SIGSUBPKT_LIST_HASHED,
746 type, critical, buffer, buflen, n );
747 else if( type == reqtype )
749 buffer += n; buflen -=n;
758 case SIGSUBPKT_SIG_CREATED:
759 case SIGSUBPKT_SIG_EXPIRE:
760 case SIGSUBPKT_KEY_EXPIRE:
764 case SIGSUBPKT_EXPORTABLE:
768 case SIGSUBPKT_ISSUER:/* issuer key ID */
772 case SIGSUBPKT_PREF_SYM:
773 case SIGSUBPKT_PREF_HASH:
774 case SIGSUBPKT_PREF_COMPR:
776 case SIGSUBPKT_PRIV_ADD_SIG:
777 /* because we use private data, we check the GNUPG marker */
780 if( buffer[0] != 'G' || buffer[1] != 'P' || buffer[2] != 'G' )
783 default: BUG(); /* not yet needed */
785 log_error("subpacket of type %d too short\n", type);
789 log_error("buffer shorter than subpacket\n");
795 parse_sig_subpkt2( PKT_signature *sig, sigsubpkttype_t reqtype, size_t *ret_n )
799 p = parse_sig_subpkt( sig->hashed_data, reqtype, ret_n );
801 p = parse_sig_subpkt( sig->unhashed_data, reqtype, ret_n );
808 parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
818 log_error("packet(%d) too short\n", pkttype);
821 sig->version = iobuf_get_noeof(inp); pktlen--;
822 if( sig->version == 4 )
824 else if( sig->version != 2 && sig->version != 3 ) {
825 log_error("packet(%d) with unknown version %d\n", pkttype, sig->version);
830 md5_len = iobuf_get_noeof(inp); pktlen--;
832 sig->sig_class = iobuf_get_noeof(inp); pktlen--;
834 sig->timestamp = read_32(inp); pktlen -= 4;
835 sig->keyid[0] = read_32(inp); pktlen -= 4;
836 sig->keyid[1] = read_32(inp); pktlen -= 4;
838 sig->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
839 sig->digest_algo = iobuf_get_noeof(inp); pktlen--;
840 if( is_v4 ) { /* read subpackets */
841 n = read_16(inp); pktlen -= 2; /* length of hashed data */
843 log_error("signature packet: hashed data too long\n");
844 rc = G10ERR_INVALID_PACKET;
848 sig->hashed_data = m_alloc( n + 2 );
849 sig->hashed_data[0] = n << 8;
850 sig->hashed_data[1] = n;
851 if( iobuf_read(inp, sig->hashed_data+2, n ) != n ) {
852 log_error("premature eof while reading hashed signature data\n");
858 n = read_16(inp); pktlen -= 2; /* length of unhashed data */
860 log_error("signature packet: unhashed data too long\n");
861 rc = G10ERR_INVALID_PACKET;
865 sig->unhashed_data = m_alloc( n + 2 );
866 sig->unhashed_data[0] = n << 8;
867 sig->unhashed_data[1] = n;
868 if( iobuf_read(inp, sig->unhashed_data+2, n ) != n ) {
869 log_error("premature eof while reading unhashed signature data\n");
877 if( pktlen < 5 ) { /* sanity check */
878 log_error("packet(%d) too short\n", pkttype);
879 rc = G10ERR_INVALID_PACKET;
883 sig->digest_start[0] = iobuf_get_noeof(inp); pktlen--;
884 sig->digest_start[1] = iobuf_get_noeof(inp); pktlen--;
886 if( is_v4 ) { /*extract required information */
889 /* FIXME: set sig->flags.unknown_critical is there is a
890 * critical bit set for packets which are not understood
891 * It does only make sense for hashed data.
893 p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_SIG_CREATED, NULL );
895 log_error("signature packet without timestamp\n");
897 sig->timestamp = buffer_to_u32(p);
898 p = parse_sig_subpkt2( sig, SIGSUBPKT_ISSUER, NULL );
900 log_error("signature packet without keyid\n");
902 sig->keyid[0] = buffer_to_u32(p);
903 sig->keyid[1] = buffer_to_u32(p+4);
908 printf(":signature packet: algo %d, keyid %08lX%08lX\n"
909 "\tversion %d, created %lu, md5len %d, sigclass %02x\n"
910 "\tdigest algo %d, begin of digest %02x %02x\n",
912 (ulong)sig->keyid[0], (ulong)sig->keyid[1],
913 sig->version, (ulong)sig->timestamp, md5_len, sig->sig_class,
915 sig->digest_start[0], sig->digest_start[1] );
917 parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_LIST_HASHED, NULL );
918 parse_sig_subpkt( sig->unhashed_data,SIGSUBPKT_LIST_UNHASHED, NULL);
922 ndata = pubkey_get_nsig(sig->pubkey_algo);
925 printf("\tunknown algorithm %d\n", sig->pubkey_algo );
926 unknown_pubkey_warning( sig->pubkey_algo );
927 /* we store the plain material in data[0], so that we are able
928 * to write it back with build_packet() */
929 sig->data[0] = read_rest(inp, &pktlen );
932 for( i=0; i < ndata; i++ ) {
934 sig->data[i] = mpi_read(inp, &n, 0 );
938 mpi_print(stdout, sig->data[i], mpi_print_mode );
946 skip_rest(inp, pktlen);
952 parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
953 PKT_onepass_sig *ops )
958 log_error("packet(%d) too short\n", pkttype);
961 version = iobuf_get_noeof(inp); pktlen--;
963 log_error("onepass_sig with unknown version %d\n", version);
966 ops->sig_class = iobuf_get_noeof(inp); pktlen--;
967 ops->digest_algo = iobuf_get_noeof(inp); pktlen--;
968 ops->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
969 ops->keyid[0] = read_32(inp); pktlen -= 4;
970 ops->keyid[1] = read_32(inp); pktlen -= 4;
971 ops->last = iobuf_get_noeof(inp); pktlen--;
973 printf(":onepass_sig packet: keyid %08lX%08lX\n"
974 "\tversion %d, sigclass %02x, digest %d, pubkey %d, last=%d\n",
975 (ulong)ops->keyid[0], (ulong)ops->keyid[1],
976 version, ops->sig_class,
977 ops->digest_algo, ops->pubkey_algo, ops->last );
981 skip_rest(inp, pktlen);
989 parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
990 byte *hdr, int hdrlen, PACKET *pkt )
992 int i, version, algorithm;
994 unsigned long timestamp, expiredate;
999 version = iobuf_get_noeof(inp); pktlen--;
1000 if( pkttype == PKT_PUBLIC_SUBKEY && version == '#' ) {
1001 /* early versions of G10 use old PGP comments packets;
1002 * luckily all those comments are started by a hash */
1004 printf(":rfc1991 comment packet: \"" );
1005 for( ; pktlen; pktlen-- ) {
1007 c = iobuf_get_noeof(inp);
1008 if( c >= ' ' && c <= 'z' )
1011 printf("\\x%02x", c );
1015 skip_rest(inp, pktlen);
1018 else if( version == 4 )
1020 else if( version != 2 && version != 3 ) {
1021 log_error("packet(%d) with unknown version %d\n", pkttype, version);
1026 log_error("packet(%d) too short\n", pkttype);
1030 timestamp = read_32(inp); pktlen -= 4;
1032 expiredate = 0; /* have to get it from the selfsignature */
1034 unsigned short ndays;
1035 ndays = read_16(inp); pktlen -= 2;
1037 expiredate = timestamp + ndays * 86400L;
1041 algorithm = iobuf_get_noeof(inp); pktlen--;
1043 printf(":%s key packet:\n"
1044 "\tversion %d, algo %d, created %lu, expires %lu\n",
1045 pkttype == PKT_PUBLIC_KEY? "public" :
1046 pkttype == PKT_SECRET_KEY? "secret" :
1047 pkttype == PKT_PUBLIC_SUBKEY? "public sub" :
1048 pkttype == PKT_SECRET_SUBKEY? "secret sub" : "??",
1049 version, algorithm, timestamp, expiredate );
1051 if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) {
1052 PKT_secret_key *sk = pkt->pkt.secret_key;
1054 sk->timestamp = timestamp;
1055 sk->expiredate = expiredate;
1056 sk->hdrbytes = hdrlen;
1057 sk->version = version;
1058 sk->pubkey_algo = algorithm;
1059 sk->pubkey_usage = 0; /* not yet used */
1062 PKT_public_key *pk = pkt->pkt.public_key;
1064 pk->timestamp = timestamp;
1065 pk->expiredate = expiredate;
1066 pk->hdrbytes = hdrlen;
1067 pk->version = version;
1068 pk->pubkey_algo = algorithm;
1069 pk->pubkey_usage = 0; /* not yet used */
1073 nskey = pubkey_get_nskey( algorithm );
1074 npkey = pubkey_get_npkey( algorithm );
1077 printf("\tunknown algorithm %d\n", algorithm );
1078 unknown_pubkey_warning( algorithm );
1082 if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) {
1083 PKT_secret_key *sk = pkt->pkt.secret_key;
1087 sk->skey[0] = read_rest( inp, &pktlen );
1091 for(i=0; i < npkey; i++ ) {
1092 n = pktlen; sk->skey[i] = mpi_read(inp, &n, 0 ); pktlen -=n;
1094 printf( "\tskey[%d]: ", i);
1095 mpi_print(stdout, sk->skey[i], mpi_print_mode );
1099 sk->protect.algo = iobuf_get_noeof(inp); pktlen--;
1100 if( sk->protect.algo ) {
1101 sk->is_protected = 1;
1102 sk->protect.s2k.count = 0;
1103 if( sk->protect.algo == 255 ) {
1105 rc = G10ERR_INVALID_PACKET;
1108 sk->protect.algo = iobuf_get_noeof(inp); pktlen--;
1109 sk->protect.s2k.mode = iobuf_get_noeof(inp); pktlen--;
1110 sk->protect.s2k.hash_algo = iobuf_get_noeof(inp); pktlen--;
1111 switch( sk->protect.s2k.mode ) {
1114 for(i=0; i < 8 && pktlen; i++, pktlen-- )
1115 temp[i] = iobuf_get_noeof(inp);
1116 memcpy(sk->protect.s2k.salt, temp, 8 );
1119 switch( sk->protect.s2k.mode ) {
1120 case 0: if( list_mode ) printf( "\tsimple S2K" );
1122 case 1: if( list_mode ) printf( "\tsalted S2K" );
1124 case 3: if( list_mode ) printf( "\titer+salt S2K" );
1128 printf( "\tunknown S2K %d\n",
1129 sk->protect.s2k.mode );
1130 rc = G10ERR_INVALID_PACKET;
1135 printf(", algo: %d, hash: %d",
1137 sk->protect.s2k.hash_algo );
1138 if( sk->protect.s2k.mode == 1
1139 || sk->protect.s2k.mode == 3 ) {
1141 for(i=0; i < 8; i++ )
1142 printf("%02x", sk->protect.s2k.salt[i]);
1147 if( sk->protect.s2k.mode == 3 ) {
1149 rc = G10ERR_INVALID_PACKET;
1152 sk->protect.s2k.count = iobuf_get(inp);
1155 printf("\tprotect count: %lu\n",
1156 (ulong)sk->protect.s2k.count);
1159 else { /* old version; no S2K, so we set mode to 0, hash MD5 */
1160 sk->protect.s2k.mode = 0;
1161 /* We need a kludge to cope with old GNUPG versions */
1162 sk->protect.s2k.hash_algo =
1163 ( sk->protect.algo == CIPHER_ALGO_BLOWFISH160
1164 && algorithm == PUBKEY_ALGO_ELGAMAL_E ) ?
1165 DIGEST_ALGO_RMD160 : DIGEST_ALGO_MD5;
1167 printf( "\tprotect algo: %d (hash algo: %d)\n",
1168 sk->protect.algo, sk->protect.s2k.hash_algo );
1171 rc = G10ERR_INVALID_PACKET;
1174 /* fixme: Add support for other blocksizes */
1175 for(i=0; i < 8 && pktlen; i++, pktlen-- )
1176 temp[i] = iobuf_get_noeof(inp);
1178 printf( "\tprotect IV: ");
1179 for(i=0; i < 8; i++ )
1180 printf(" %02x", temp[i] );
1183 memcpy(sk->protect.iv, temp, 8 );
1186 sk->is_protected = 0;
1187 /* It does not make sense to read it into secure memory.
1188 * If the user is so careless, not to protect his secret key,
1189 * we can assume, that he operates an open system :=(.
1190 * So we put the key into secure memory when we unprotect it. */
1191 if( is_v4 && sk->is_protected ){
1192 /* ugly; the length is encrypted too, so we read all
1193 * stuff up to the end of the packet into the first
1195 sk->skey[npkey] = mpi_set_opaque(NULL,
1196 read_rest2(inp, pktlen), pktlen );
1199 printf("\tencrypted stuff follows\n");
1202 else { /* v3 method: the mpi length is not encrypted */
1203 for(i=npkey; i < nskey; i++ ) {
1204 n = pktlen; sk->skey[i] = mpi_read(inp, &n, 0 ); pktlen -=n;
1205 if( sk->is_protected )
1206 mpi_set_protect_flag(sk->skey[i]);
1208 printf( "\tskey[%d]: ", i);
1209 if( sk->is_protected )
1210 printf( "[encrypted]\n");
1212 mpi_print(stdout, sk->skey[i], mpi_print_mode );
1218 sk->csum = read_16(inp); pktlen -= 2;
1220 printf("\tchecksum: %04hx\n", sk->csum);
1225 PKT_public_key *pk = pkt->pkt.public_key;
1228 pk->pkey[0] = read_rest( inp, &pktlen );
1232 for(i=0; i < npkey; i++ ) {
1233 n = pktlen; pk->pkey[i] = mpi_read(inp, &n, 0 ); pktlen -=n;
1235 printf( "\tpkey[%d]: ", i);
1236 mpi_print(stdout, pk->pkey[i], mpi_print_mode );
1243 skip_rest(inp, pktlen);
1249 parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
1253 packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id + pktlen - 1);
1254 packet->pkt.user_id->len = pktlen;
1255 p = packet->pkt.user_id->name;
1256 for( ; pktlen; pktlen--, p++ )
1257 *p = iobuf_get_noeof(inp);
1260 int n = packet->pkt.user_id->len;
1261 printf(":user id packet: \"");
1262 for(p=packet->pkt.user_id->name; n; p++, n-- ) {
1263 if( *p >= ' ' && *p <= 'z' )
1266 printf("\\x%02x", *p );
1276 parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
1280 packet->pkt.comment = m_alloc(sizeof *packet->pkt.comment + pktlen - 1);
1281 packet->pkt.comment->len = pktlen;
1282 p = packet->pkt.comment->data;
1283 for( ; pktlen; pktlen--, p++ )
1284 *p = iobuf_get_noeof(inp);
1287 int n = packet->pkt.comment->len;
1288 printf(":%scomment packet: \"", pkttype == PKT_OLD_COMMENT?
1289 "OpenPGP draft " : "" );
1290 for(p=packet->pkt.comment->data; n; p++, n-- ) {
1291 if( *p >= ' ' && *p <= 'z' )
1294 printf("\\x%02x", *p );
1303 parse_trust( IOBUF inp, int pkttype, unsigned long pktlen )
1307 c = iobuf_get_noeof(inp);
1309 printf(":trust packet: flag=%02x\n", c );
1314 parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
1315 PACKET *pkt, int new_ctb )
1322 if( pktlen && pktlen < 6 ) {
1323 log_error("packet(%d) too short (%lu)\n", pkttype, (ulong)pktlen);
1326 mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
1327 namelen = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
1328 pt = pkt->pkt.plaintext = m_alloc(sizeof *pkt->pkt.plaintext + namelen -1);
1329 pt->new_ctb = new_ctb;
1331 pt->namelen = namelen;
1333 for( i=0; pktlen > 4 && i < namelen; pktlen--, i++ )
1334 pt->name[i] = iobuf_get_noeof(inp);
1337 for( i=0; i < namelen; i++ )
1338 if( (c=iobuf_get(inp)) == -1 )
1343 pt->timestamp = read_32(inp); if( pktlen) pktlen -= 4;
1349 printf(":literal data packet:\n"
1350 "\tmode %c, created %lu, name=\"",
1351 mode >= ' ' && mode <'z'? mode : '?',
1352 (ulong)pt->timestamp );
1353 for(p=pt->name,i=0; i < namelen; p++, i++ ) {
1354 if( *p >= ' ' && *p <= 'z' )
1357 printf("\\x%02x", *p );
1359 printf("\",\n\traw data: %lu bytes\n", (ulong)pt->len );
1368 parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
1369 PACKET *pkt, int new_ctb )
1373 /* pktlen is here 0, but data follows
1374 * (this should be the last object in a file or
1375 * the compress algorithm should know the length)
1377 zd = pkt->pkt.compressed = m_alloc(sizeof *pkt->pkt.compressed );
1378 zd->len = 0; /* not yet used */
1379 zd->algorithm = iobuf_get_noeof(inp);
1380 zd->new_ctb = new_ctb;
1383 printf(":compressed packet: algo=%d\n", zd->algorithm);
1389 parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
1390 PACKET *pkt, int new_ctb )
1394 ed = pkt->pkt.encrypted = m_alloc(sizeof *pkt->pkt.encrypted );
1397 ed->new_ctb = new_ctb;
1398 if( pktlen && pktlen < 10 ) {
1399 log_error("packet(%d) too short\n", pkttype);
1400 skip_rest(inp, pktlen);
1405 printf(":encrypted data packet:\n\tlength: %lu\n", pktlen-10);
1407 printf(":encrypted data packet:\n\tlength: unknown\n");