1 /* parse-packet.c - read packets
2 * Copyright (C) 1998, 1999 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
30 #include "dummy-cipher.h"
37 static int mpi_print_mode = 0;
38 static int list_mode = 0;
40 static int parse( IOBUF inp, PACKET *pkt, int reqtype,
41 ulong *retpos, int *skip, IOBUF out, int do_skip
42 #ifdef DEBUG_PARSE_PACKET
43 ,const char *dbg_w, const char *dbg_f, int dbg_l
46 static int copy_packet( IOBUF inp, IOBUF out, int pkttype,
47 unsigned long pktlen );
48 static void skip_packet( IOBUF inp, int pkttype, unsigned long pktlen );
49 static void skip_rest( IOBUF inp, unsigned long pktlen );
50 static void *read_rest( IOBUF inp, size_t pktlen );
51 static int parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen,
53 static int parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen,
55 static int parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
57 static int parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
58 PKT_onepass_sig *ops );
59 static int parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
60 byte *hdr, int hdrlen, PACKET *packet );
61 static int parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen,
63 static int parse_comment( IOBUF inp, int pkttype, unsigned long pktlen,
65 static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen,
67 static int parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
68 PACKET *packet, int new_ctb);
69 static int parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
70 PACKET *packet, int new_ctb );
71 static int parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
72 PACKET *packet, int new_ctb);
78 a = iobuf_get_noeof(inp) << 8;
79 a |= iobuf_get_noeof(inp);
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);
96 set_packet_list_mode( int mode )
100 mpi_print_mode = (opt.debug & DBG_MPI_VALUE);
105 unknown_pubkey_warning( int algo )
107 static byte unknown_pubkey_algos[256];
110 if( !unknown_pubkey_algos[algo] ) {
112 log_info(_("can't handle public key algorithm %d\n"), algo );
113 unknown_pubkey_algos[algo] = 1;
118 * Parse a Packet and return it in packet
119 * Returns: 0 := valid packet in pkt
120 * -1 := no more packets
122 * Note: The function may return an error and a partly valid packet;
123 * caller must free this packet.
125 #ifdef DEBUG_PARSE_PACKET
127 dbg_parse_packet( IOBUF inp, PACKET *pkt, const char *dbg_f, int dbg_l )
132 rc = parse( inp, pkt, 0, NULL, &skip, NULL, 0, "parse", dbg_f, dbg_l );
138 parse_packet( IOBUF inp, PACKET *pkt )
143 rc = parse( inp, pkt, 0, NULL, &skip, NULL, 0 );
150 * Like parse packet, but only return packets of the given type.
152 #ifdef DEBUG_PARSE_PACKET
154 dbg_search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos,
155 const char *dbg_f, int dbg_l )
160 rc = parse( inp, pkt, pkttype, retpos, &skip, NULL, 0, "search", dbg_f, dbg_l );
166 search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos )
171 rc = parse( inp, pkt, pkttype, retpos, &skip, NULL, 0 );
178 * Copy all packets from INP to OUT, thereby removing unused spaces.
180 #ifdef DEBUG_PARSE_PACKET
182 dbg_copy_all_packets( IOBUF inp, IOBUF out,
183 const char *dbg_f, int dbg_l )
189 } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0, "copy", dbg_f, dbg_l )));
194 copy_all_packets( IOBUF inp, IOBUF out )
200 } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0 )));
206 * Copy some packets from INP to OUT, thereby removing unused spaces.
207 * Stop at offset STOPoff (i.e. don't copy packets at this or later offsets)
209 #ifdef DEBUG_PARSE_PACKET
211 dbg_copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff,
212 const char *dbg_f, int dbg_l )
217 if( iobuf_tell(inp) >= stopoff )
220 } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0,
221 "some", dbg_f, dbg_l )) );
226 copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff )
231 if( iobuf_tell(inp) >= stopoff )
234 } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0 )) );
240 * Skip over N packets
242 #ifdef DEBUG_PARSE_PACKET
244 dbg_skip_some_packets( IOBUF inp, unsigned n,
245 const char *dbg_f, int dbg_l )
250 for( ;n && !rc; n--) {
252 rc = parse( inp, &pkt, 0, NULL, &skip, NULL, 1, "skip", dbg_f, dbg_l );
258 skip_some_packets( IOBUF inp, unsigned n )
263 for( ;n && !rc; n--) {
265 rc = parse( inp, &pkt, 0, NULL, &skip, NULL, 1 );
273 * Parse packet. Set the variable skip points to to 1 if the packet
274 * should be skipped; this is the case if either there is a
275 * requested packet type and the parsed packet doesn't match or the
276 * packet-type is 0, indicating deleted stuff.
277 * if OUT is not NULL, a special copymode is used.
280 parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos,
281 int *skip, IOBUF out, int do_skip
282 #ifdef DEBUG_PARSE_PACKET
283 ,const char *dbg_w, const char *dbg_f, int dbg_l
287 int rc=0, c, ctb, pkttype, lenbytes;
288 unsigned long pktlen;
294 assert( !pkt->pkt.generic );
296 *retpos = iobuf_tell(inp);
298 if( (ctb = iobuf_get(inp)) == -1 ) {
304 if( !(ctb & 0x80) ) {
305 log_error("%s: invalid packet (ctb=%02x) near %lu\n",
306 iobuf_where(inp), ctb, iobuf_tell(inp) );
307 rc = G10ERR_INVALID_PACKET;
311 new_ctb = !!(ctb & 0x40);
313 pkttype = ctb & 0x3f;
314 if( (c = iobuf_get(inp)) == -1 ) {
315 log_error("%s: 1st length byte missing\n", iobuf_where(inp) );
316 rc = G10ERR_INVALID_PACKET;
323 pktlen = (c - 192) * 256;
324 if( (c = iobuf_get(inp)) == -1 ) {
325 log_error("%s: 2nd length byte missing\n", iobuf_where(inp) );
326 rc = G10ERR_INVALID_PACKET;
332 else if( c == 255 ) {
333 pktlen = (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 24;
334 pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 16;
335 pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 8;
336 if( (c = iobuf_get(inp)) == -1 ) {
337 log_error("%s: 4 byte length invalid\n", iobuf_where(inp) );
338 rc = G10ERR_INVALID_PACKET;
341 pktlen |= (hdr[hdrlen++] = c );
343 else { /* partial body length */
344 iobuf_set_partial_block_mode(inp, c & 0xff);
345 pktlen = 0;/* to indicate partial length */
349 pkttype = (ctb>>2)&0xf;
350 lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3));
352 pktlen = 0; /* don't know the value */
353 if( pkttype != PKT_COMPRESSED )
354 iobuf_set_block_mode(inp, 1);
357 for( ; lenbytes; lenbytes-- ) {
359 pktlen |= hdr[hdrlen++] = iobuf_get_noeof(inp);
364 if( out && pkttype ) {
365 if( iobuf_write( out, hdr, hdrlen ) == -1 )
366 rc = G10ERR_WRITE_FILE;
368 rc = copy_packet(inp, out, pkttype, pktlen );
372 if( do_skip || !pkttype || (reqtype && pkttype != reqtype) ) {
373 skip_rest(inp, pktlen);
380 #ifdef DEBUG_PARSE_PACKET
381 log_debug("parse_packet(iob=%d): type=%d length=%lu%s (%s.%s.%d)\n",
382 iobuf_id(inp), pkttype, pktlen, new_ctb?" (new_ctb)":"",
383 dbg_w, dbg_f, dbg_l );
385 log_debug("parse_packet(iob=%d): type=%d length=%lu%s\n",
386 iobuf_id(inp), pkttype, pktlen, new_ctb?" (new_ctb)":"" );
389 pkt->pkttype = pkttype;
390 rc = G10ERR_UNKNOWN_PACKET; /* default error */
393 case PKT_PUBLIC_SUBKEY:
394 pkt->pkt.public_key = gcry_xcalloc( 1,sizeof *pkt->pkt.public_key );
395 rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt );
398 case PKT_SECRET_SUBKEY:
399 pkt->pkt.secret_key = gcry_xcalloc( 1,sizeof *pkt->pkt.secret_key );
400 rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt );
403 rc = parse_symkeyenc( inp, pkttype, pktlen, pkt );
406 rc = parse_pubkeyenc(inp, pkttype, pktlen, pkt );
409 pkt->pkt.signature = gcry_xcalloc( 1,sizeof *pkt->pkt.signature );
410 rc = parse_signature(inp, pkttype, pktlen, pkt->pkt.signature );
412 case PKT_ONEPASS_SIG:
413 pkt->pkt.onepass_sig = gcry_xcalloc( 1,sizeof *pkt->pkt.onepass_sig );
414 rc = parse_onepass_sig(inp, pkttype, pktlen, pkt->pkt.onepass_sig );
417 rc = parse_user_id(inp, pkttype, pktlen, pkt );
419 case PKT_OLD_COMMENT:
421 rc = parse_comment(inp, pkttype, pktlen, pkt);
424 parse_trust(inp, pkttype, pktlen, pkt);
428 rc = parse_plaintext(inp, pkttype, pktlen, pkt, new_ctb );
431 rc = parse_compressed(inp, pkttype, pktlen, pkt, new_ctb );
434 case PKT_ENCRYPTED_MDC:
435 rc = parse_encrypted(inp, pkttype, pktlen, pkt, new_ctb );
438 skip_packet(inp, pkttype, pktlen);
443 if( !rc && iobuf_error(inp) )
444 rc = G10ERR_INV_KEYRING;
449 dump_hex_line( int c, int *i )
451 if( *i && !(*i%8) ) {
453 printf("\n%4d:", *i );
466 copy_packet( IOBUF inp, IOBUF out, int pkttype, unsigned long pktlen )
471 if( iobuf_in_block_mode(inp) ) {
472 while( (n = iobuf_read( inp, buf, 100 )) != -1 )
473 if( iobuf_write(out, buf, n ) )
474 return G10ERR_WRITE_FILE; /* write error */
476 else if( !pktlen && pkttype == PKT_COMPRESSED ) {
477 log_debug("copy_packet: compressed!\n");
478 /* compressed packet, copy till EOF */
479 while( (n = iobuf_read( inp, buf, 100 )) != -1 )
480 if( iobuf_write(out, buf, n ) )
481 return G10ERR_WRITE_FILE; /* write error */
484 for( ; pktlen; pktlen -= n ) {
485 n = pktlen > 100 ? 100 : pktlen;
486 n = iobuf_read( inp, buf, n );
488 return G10ERR_READ_FILE;
489 if( iobuf_write(out, buf, n ) )
490 return G10ERR_WRITE_FILE; /* write error */
498 skip_packet( IOBUF inp, int pkttype, unsigned long pktlen )
501 if( pkttype == PKT_MARKER )
502 fputs(":marker packet:\n", stdout );
504 printf(":unknown packet: type %2d, length %lu\n", pkttype, pktlen);
507 if( pkttype != PKT_MARKER )
508 fputs("dump:", stdout );
509 if( iobuf_in_block_mode(inp) ) {
510 while( (c=iobuf_get(inp)) != -1 )
511 dump_hex_line(c, &i);
514 for( ; pktlen; pktlen-- )
515 dump_hex_line(iobuf_get(inp), &i);
521 skip_rest(inp,pktlen);
525 skip_rest( IOBUF inp, unsigned long pktlen )
527 if( iobuf_in_block_mode(inp) ) {
528 while( iobuf_get(inp) != -1 )
532 for( ; pktlen; pktlen-- )
533 if( iobuf_get(inp) == -1 )
540 read_rest( IOBUF inp, size_t pktlen )
545 if( iobuf_in_block_mode(inp) ) {
546 log_error("read_rest: can't store stream data\n");
550 p = gcry_xmalloc( pktlen );
551 for(i=0; pktlen; pktlen--, i++ )
552 p[i] = iobuf_get(inp);
560 parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
563 int i, version, s2kmode, cipher_algo, hash_algo, seskeylen, minlen;
566 log_error("packet(%d) too short\n", pkttype);
569 version = iobuf_get_noeof(inp); pktlen--;
571 log_error("packet(%d) with unknown version %d\n", pkttype, version);
574 if( pktlen > 200 ) { /* (we encode the seskeylen in a byte) */
575 log_error("packet(%d) too large\n", pkttype);
578 cipher_algo = iobuf_get_noeof(inp); pktlen--;
579 s2kmode = iobuf_get_noeof(inp); pktlen--;
580 hash_algo = iobuf_get_noeof(inp); pktlen--;
582 case 0: /* simple s2k */
585 case 1: /* salted s2k */
588 case 3: /* iterated+salted s2k */
592 log_error("unknown S2K %d\n", s2kmode );
595 if( minlen > pktlen ) {
596 log_error("packet with S2K %d too short\n", s2kmode );
599 seskeylen = pktlen - minlen;
600 k = packet->pkt.symkey_enc = gcry_xcalloc( 1, sizeof *packet->pkt.symkey_enc
602 k->version = version;
603 k->cipher_algo = cipher_algo;
604 k->s2k.mode = s2kmode;
605 k->s2k.hash_algo = hash_algo;
606 if( s2kmode == 1 || s2kmode == 3 ) {
607 for(i=0; i < 8 && pktlen; i++, pktlen-- )
608 k->s2k.salt[i] = iobuf_get_noeof(inp);
611 k->s2k.count = iobuf_get(inp); pktlen--;
613 k->seskeylen = seskeylen;
614 for(i=0; i < seskeylen && pktlen; i++, pktlen-- )
615 k->seskey[i] = iobuf_get_noeof(inp);
619 printf(":symkey enc packet: version %d, cipher %d, s2k %d, hash %d\n",
620 version, cipher_algo, s2kmode, hash_algo);
621 if( s2kmode == 1 || s2kmode == 3 ) {
623 for(i=0; i < 8; i++ )
624 printf("%02x", k->s2k.salt[i]);
626 printf(", count %lu\n", (ulong)k->s2k.count );
632 skip_rest(inp, pktlen);
637 parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
643 k = packet->pkt.pubkey_enc = gcry_xcalloc( 1,sizeof *packet->pkt.pubkey_enc);
645 log_error("packet(%d) too short\n", pkttype);
648 k->version = iobuf_get_noeof(inp); pktlen--;
649 if( k->version != 2 && k->version != 3 ) {
650 log_error("packet(%d) with unknown version %d\n", pkttype, k->version);
653 k->keyid[0] = read_32(inp); pktlen -= 4;
654 k->keyid[1] = read_32(inp); pktlen -= 4;
655 k->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
656 k->throw_keyid = 0; /* only used as flag for build_packet */
658 printf(":pubkey enc packet: version %d, algo %d, keyid %08lX%08lX\n",
659 k->version, k->pubkey_algo, (ulong)k->keyid[0], (ulong)k->keyid[1]);
661 ndata = pubkey_get_nenc(k->pubkey_algo);
664 printf("\tunsupported algorithm %d\n", k->pubkey_algo );
665 unknown_pubkey_warning( k->pubkey_algo );
666 k->data[0] = NULL; /* no need to store the encrypted data */
669 for( i=0; i < ndata; i++ ) {
671 k->data[i] = mpi_read(inp, &n, 0); pktlen -=n;
674 mpi_print(stdout, k->data[i], mpi_print_mode );
681 skip_rest(inp, pktlen);
687 dump_sig_subpkt( int hashed, int type, int critical,
688 const byte *buffer, size_t buflen, size_t length )
693 printf("\t%s%ssubpkt %d len %u (", /*)*/
694 critical ? "critical ":"",
695 hashed ? "hashed ":"", type, (unsigned)length );
698 if( length > buflen ) {
699 printf("too short: buffer is only %u)\n", (unsigned)buflen );
703 case SIGSUBPKT_SIG_CREATED:
705 printf("sig created %s", strtimestamp( buffer_to_u32(buffer) ) );
707 case SIGSUBPKT_SIG_EXPIRE:
709 printf("sig expires after %s",
710 strtimevalue( buffer_to_u32(buffer) ) );
712 case SIGSUBPKT_EXPORTABLE:
714 printf("%sexportable", *buffer? "":"not ");
716 case SIGSUBPKT_TRUST:
717 p = "trust signature";
719 case SIGSUBPKT_REGEXP:
720 p = "regular expression";
722 case SIGSUBPKT_REVOCABLE:
725 case SIGSUBPKT_KEY_EXPIRE:
727 printf("key expires after %s",
728 strtimevalue( buffer_to_u32(buffer) ) );
731 p = "additional recipient request";
733 case SIGSUBPKT_PREF_SYM:
734 fputs("pref-sym-algos:", stdout );
735 for( i=0; i < length; i++ )
736 printf(" %d", buffer[i] );
738 case SIGSUBPKT_REV_KEY:
739 fputs("revocation key: ", stdout );
743 printf("c=%02x a=%d f=", buffer[0], buffer[1] );
744 for( i=2; i < length; i++ )
745 printf("%02X", buffer[i] );
748 case SIGSUBPKT_ISSUER:
750 printf("issuer key ID %08lX%08lX",
751 (ulong)buffer_to_u32(buffer),
752 (ulong)buffer_to_u32(buffer+4) );
754 case SIGSUBPKT_NOTATION:
756 fputs("notation: ", stdout );
759 else if( !(*buffer & 0x80) )
760 p = "[not human readable]";
762 const byte *s = buffer;
765 n1 = (s[4] << 8) | s[5];
766 n2 = (s[6] << 8) | s[7];
768 if( 8+n1+n2 != length )
771 print_string( stdout, s, n1, ')' );
773 print_string( stdout, s+n1, n2, ')' );
778 case SIGSUBPKT_PREF_HASH:
779 fputs("pref-hash-algos:", stdout );
780 for( i=0; i < length; i++ )
781 printf(" %d", buffer[i] );
783 case SIGSUBPKT_PREF_COMPR:
784 fputs("pref-zip-algos:", stdout );
785 for( i=0; i < length; i++ )
786 printf(" %d", buffer[i] );
788 case SIGSUBPKT_KS_FLAGS:
789 p = "key server preferences";
791 case SIGSUBPKT_PREF_KS:
792 p = "preferred key server";
794 case SIGSUBPKT_PRIMARY_UID:
795 p = "primary user ID";
797 case SIGSUBPKT_POLICY:
798 fputs("policy: ", stdout );
799 print_string( stdout, buffer, length, ')' );
801 case SIGSUBPKT_KEY_FLAGS:
804 case SIGSUBPKT_SIGNERS_UID:
805 p = "signer's user ID";
807 case SIGSUBPKT_PRIV_ADD_SIG:
808 p = "signs additional user ID";
810 default: p = "?"; break;
813 printf("%s)\n", p? p: "");
817 * Returns: >= 0 offset into buffer
819 * -2 unsupported type
820 * -3 subpacket too short
823 parse_one_sig_subpkt( const byte *buffer, size_t n, int type )
826 case SIGSUBPKT_SIG_CREATED:
827 case SIGSUBPKT_SIG_EXPIRE:
828 case SIGSUBPKT_KEY_EXPIRE:
832 case SIGSUBPKT_EXPORTABLE:
836 case SIGSUBPKT_ISSUER:/* issuer key ID */
840 case SIGSUBPKT_NOTATION:
841 if( n < 8 ) /* minimum length needed */
844 case SIGSUBPKT_PREF_SYM:
845 case SIGSUBPKT_PREF_HASH:
846 case SIGSUBPKT_PREF_COMPR:
847 case SIGSUBPKT_POLICY:
849 case SIGSUBPKT_PRIV_ADD_SIG:
850 /* because we use private data, we check the GNUPG marker */
853 if( buffer[0] != 'G' || buffer[1] != 'P' || buffer[2] != 'G' )
863 can_handle_critical( const byte *buffer, size_t n, int type )
866 case SIGSUBPKT_NOTATION:
867 if( n >= 8 && (*buffer & 0x80) )
868 return 1; /* human readable is handled */
871 case SIGSUBPKT_SIG_CREATED:
872 case SIGSUBPKT_SIG_EXPIRE:
873 case SIGSUBPKT_KEY_EXPIRE:
874 case SIGSUBPKT_EXPORTABLE:
875 case SIGSUBPKT_ISSUER:/* issuer key ID */
876 case SIGSUBPKT_PREF_SYM:
877 case SIGSUBPKT_PREF_HASH:
878 case SIGSUBPKT_PREF_COMPR:
881 case SIGSUBPKT_POLICY: /* Is enough to show the policy? */
889 enum_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype,
890 size_t *ret_n, int *start )
898 int reqseq = start? *start: 0;
900 if( !buffer || reqseq == -1 )
902 buflen = (*buffer << 8) | buffer[1];
905 n = *buffer++; buflen--;
909 n = (buffer[0] << 24) | (buffer[1] << 16)
910 | (buffer[2] << 8) | buffer[3];
915 else if( n >= 192 ) {
918 n = (( n - 192 ) << 8) + *buffer + 192;
931 if( !(++seq > reqseq) )
933 else if( reqtype == SIGSUBPKT_TEST_CRITICAL ) {
937 if( !can_handle_critical(buffer+1, n-1, type ) ) {
938 log_info(_("subpacket of type %d has critical bit set\n"),
942 return NULL; /* this is an error */
946 else if( reqtype < 0 ) /* list packets */
947 dump_sig_subpkt( reqtype == SIGSUBPKT_LIST_HASHED,
948 type, critical, buffer, buflen, n );
949 else if( type == reqtype ) { /* found */
956 offset = parse_one_sig_subpkt(buffer, n, type );
959 log_error("subpacket of type %d too short\n", type);
964 BUG(); /* not yet needed */
970 return buffer+offset;
972 buffer += n; buflen -=n;
974 if( reqtype == SIGSUBPKT_TEST_CRITICAL )
975 return buffer; /* as value true to indicate that there is no */
976 /* critical bit we don't understand */
979 return NULL; /* end of packets; not found */
982 log_error("buffer shorter than subpacket\n");
990 parse_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype, size_t *ret_n )
992 return enum_sig_subpkt( buffer, reqtype, ret_n, NULL );
996 parse_sig_subpkt2( PKT_signature *sig, sigsubpkttype_t reqtype, size_t *ret_n )
1000 p = parse_sig_subpkt( sig->hashed_data, reqtype, ret_n );
1002 p = parse_sig_subpkt( sig->unhashed_data, reqtype, ret_n );
1009 parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
1010 PKT_signature *sig )
1019 log_error("packet(%d) too short\n", pkttype);
1022 sig->version = iobuf_get_noeof(inp); pktlen--;
1023 if( sig->version == 4 )
1025 else if( sig->version != 2 && sig->version != 3 ) {
1026 log_error("packet(%d) with unknown version %d\n", pkttype, sig->version);
1031 md5_len = iobuf_get_noeof(inp); pktlen--;
1033 sig->sig_class = iobuf_get_noeof(inp); pktlen--;
1035 sig->timestamp = read_32(inp); pktlen -= 4;
1036 sig->keyid[0] = read_32(inp); pktlen -= 4;
1037 sig->keyid[1] = read_32(inp); pktlen -= 4;
1039 sig->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
1040 sig->digest_algo = iobuf_get_noeof(inp); pktlen--;
1041 if( is_v4 ) { /* read subpackets */
1042 n = read_16(inp); pktlen -= 2; /* length of hashed data */
1044 log_error("signature packet: hashed data too long\n");
1045 rc = G10ERR_INVALID_PACKET;
1049 sig->hashed_data = gcry_xmalloc( n + 2 );
1050 sig->hashed_data[0] = n >> 8;
1051 sig->hashed_data[1] = n;
1052 if( iobuf_read(inp, sig->hashed_data+2, n ) != n ) {
1053 log_error("premature eof while reading hashed signature data\n");
1059 n = read_16(inp); pktlen -= 2; /* length of unhashed data */
1061 log_error("signature packet: unhashed data too long\n");
1062 rc = G10ERR_INVALID_PACKET;
1066 sig->unhashed_data = gcry_xmalloc( n + 2 );
1067 sig->unhashed_data[0] = n >> 8;
1068 sig->unhashed_data[1] = n;
1069 if( iobuf_read(inp, sig->unhashed_data+2, n ) != n ) {
1070 log_error("premature eof while reading unhashed signature data\n");
1078 if( pktlen < 5 ) { /* sanity check */
1079 log_error("packet(%d) too short\n", pkttype);
1080 rc = G10ERR_INVALID_PACKET;
1084 sig->digest_start[0] = iobuf_get_noeof(inp); pktlen--;
1085 sig->digest_start[1] = iobuf_get_noeof(inp); pktlen--;
1087 if( is_v4 && sig->pubkey_algo ) { /*extract required information */
1090 /* set sig->flags.unknown_critical if there is a
1091 * critical bit set for packets which we do not understand */
1092 if( !parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_TEST_CRITICAL, NULL)
1093 || !parse_sig_subpkt( sig->unhashed_data, SIGSUBPKT_TEST_CRITICAL,
1096 sig->flags.unknown_critical = 1;
1099 p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_SIG_CREATED, NULL );
1101 log_error("signature packet without timestamp\n");
1103 sig->timestamp = buffer_to_u32(p);
1104 p = parse_sig_subpkt2( sig, SIGSUBPKT_ISSUER, NULL );
1106 log_error("signature packet without keyid\n");
1108 sig->keyid[0] = buffer_to_u32(p);
1109 sig->keyid[1] = buffer_to_u32(p+4);
1114 printf(":signature packet: algo %d, keyid %08lX%08lX\n"
1115 "\tversion %d, created %lu, md5len %d, sigclass %02x\n"
1116 "\tdigest algo %d, begin of digest %02x %02x\n",
1118 (ulong)sig->keyid[0], (ulong)sig->keyid[1],
1119 sig->version, (ulong)sig->timestamp, md5_len, sig->sig_class,
1121 sig->digest_start[0], sig->digest_start[1] );
1123 parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_LIST_HASHED, NULL );
1124 parse_sig_subpkt( sig->unhashed_data,SIGSUBPKT_LIST_UNHASHED, NULL);
1128 ndata = pubkey_get_nsig(sig->pubkey_algo);
1131 printf("\tunknown algorithm %d\n", sig->pubkey_algo );
1132 unknown_pubkey_warning( sig->pubkey_algo );
1133 /* we store the plain material in data[0], so that we are able
1134 * to write it back with build_packet() */
1135 sig->data[0] = gcry_mpi_set_opaque(NULL,
1136 read_rest(inp, pktlen), pktlen*8 );
1140 for( i=0; i < ndata; i++ ) {
1142 sig->data[i] = mpi_read(inp, &n, 0 );
1146 mpi_print(stdout, sig->data[i], mpi_print_mode );
1153 skip_rest(inp, pktlen);
1159 parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
1160 PKT_onepass_sig *ops )
1165 log_error("packet(%d) too short\n", pkttype);
1168 version = iobuf_get_noeof(inp); pktlen--;
1169 if( version != 3 ) {
1170 log_error("onepass_sig with unknown version %d\n", version);
1173 ops->sig_class = iobuf_get_noeof(inp); pktlen--;
1174 ops->digest_algo = iobuf_get_noeof(inp); pktlen--;
1175 ops->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
1176 ops->keyid[0] = read_32(inp); pktlen -= 4;
1177 ops->keyid[1] = read_32(inp); pktlen -= 4;
1178 ops->last = iobuf_get_noeof(inp); pktlen--;
1180 printf(":onepass_sig packet: keyid %08lX%08lX\n"
1181 "\tversion %d, sigclass %02x, digest %d, pubkey %d, last=%d\n",
1182 (ulong)ops->keyid[0], (ulong)ops->keyid[1],
1183 version, ops->sig_class,
1184 ops->digest_algo, ops->pubkey_algo, ops->last );
1188 skip_rest(inp, pktlen);
1196 parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
1197 byte *hdr, int hdrlen, PACKET *pkt )
1199 int i, version, algorithm;
1201 unsigned long timestamp, expiredate;
1206 version = iobuf_get_noeof(inp); pktlen--;
1207 if( pkttype == PKT_PUBLIC_SUBKEY && version == '#' ) {
1208 /* early versions of G10 use old PGP comments packets;
1209 * luckily all those comments are started by a hash */
1211 printf(":rfc1991 comment packet: \"" );
1212 for( ; pktlen; pktlen-- ) {
1214 c = iobuf_get_noeof(inp);
1215 if( c >= ' ' && c <= 'z' )
1218 printf("\\x%02x", c );
1222 skip_rest(inp, pktlen);
1225 else if( version == 4 )
1227 else if( version != 2 && version != 3 ) {
1228 log_error("packet(%d) with unknown version %d\n", pkttype, version);
1233 log_error("packet(%d) too short\n", pkttype);
1237 timestamp = read_32(inp); pktlen -= 4;
1239 expiredate = 0; /* have to get it from the selfsignature */
1241 unsigned short ndays;
1242 ndays = read_16(inp); pktlen -= 2;
1244 expiredate = timestamp + ndays * 86400L;
1248 algorithm = iobuf_get_noeof(inp); pktlen--;
1250 printf(":%s key packet:\n"
1251 "\tversion %d, algo %d, created %lu, expires %lu\n",
1252 pkttype == PKT_PUBLIC_KEY? "public" :
1253 pkttype == PKT_SECRET_KEY? "secret" :
1254 pkttype == PKT_PUBLIC_SUBKEY? "public sub" :
1255 pkttype == PKT_SECRET_SUBKEY? "secret sub" : "??",
1256 version, algorithm, timestamp, expiredate );
1258 if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) {
1259 PKT_secret_key *sk = pkt->pkt.secret_key;
1261 sk->timestamp = timestamp;
1262 sk->expiredate = expiredate;
1263 sk->hdrbytes = hdrlen;
1264 sk->version = version;
1265 sk->is_primary = pkttype == PKT_SECRET_KEY;
1266 sk->pubkey_algo = algorithm;
1267 sk->pubkey_usage = 0; /* not yet used */
1270 PKT_public_key *pk = pkt->pkt.public_key;
1272 pk->timestamp = timestamp;
1273 pk->expiredate = expiredate;
1274 pk->hdrbytes = hdrlen;
1275 pk->version = version;
1276 pk->pubkey_algo = algorithm;
1277 pk->pubkey_usage = 0; /* not yet used */
1281 nskey = pubkey_get_nskey( algorithm );
1282 npkey = pubkey_get_npkey( algorithm );
1285 printf("\tunknown algorithm %d\n", algorithm );
1286 unknown_pubkey_warning( algorithm );
1290 if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) {
1291 PKT_secret_key *sk = pkt->pkt.secret_key;
1295 sk->skey[0] = gcry_mpi_set_opaque( NULL,
1296 read_rest(inp, pktlen), pktlen*8 );
1301 for(i=0; i < npkey; i++ ) {
1302 n = pktlen; sk->skey[i] = mpi_read(inp, &n, 0 ); pktlen -=n;
1304 printf( "\tskey[%d]: ", i);
1305 mpi_print(stdout, sk->skey[i], mpi_print_mode );
1309 sk->protect.algo = iobuf_get_noeof(inp); pktlen--;
1310 if( sk->protect.algo ) {
1311 sk->is_protected = 1;
1312 sk->protect.s2k.count = 0;
1313 if( sk->protect.algo == 255 ) {
1315 rc = G10ERR_INVALID_PACKET;
1318 sk->protect.algo = iobuf_get_noeof(inp); pktlen--;
1319 sk->protect.s2k.mode = iobuf_get_noeof(inp); pktlen--;
1320 sk->protect.s2k.hash_algo = iobuf_get_noeof(inp); pktlen--;
1321 switch( sk->protect.s2k.mode ) {
1324 for(i=0; i < 8 && pktlen; i++, pktlen-- )
1325 temp[i] = iobuf_get_noeof(inp);
1326 memcpy(sk->protect.s2k.salt, temp, 8 );
1329 switch( sk->protect.s2k.mode ) {
1330 case 0: if( list_mode ) printf( "\tsimple S2K" );
1332 case 1: if( list_mode ) printf( "\tsalted S2K" );
1334 case 3: if( list_mode ) printf( "\titer+salt S2K" );
1338 printf( "\tunknown S2K %d\n",
1339 sk->protect.s2k.mode );
1340 rc = G10ERR_INVALID_PACKET;
1345 printf(", algo: %d, hash: %d",
1347 sk->protect.s2k.hash_algo );
1348 if( sk->protect.s2k.mode == 1
1349 || sk->protect.s2k.mode == 3 ) {
1351 for(i=0; i < 8; i++ )
1352 printf("%02x", sk->protect.s2k.salt[i]);
1357 if( sk->protect.s2k.mode == 3 ) {
1359 rc = G10ERR_INVALID_PACKET;
1362 sk->protect.s2k.count = iobuf_get(inp);
1365 printf("\tprotect count: %lu\n",
1366 (ulong)sk->protect.s2k.count);
1369 else { /* old version; no S2K, so we set mode to 0, hash MD5 */
1370 sk->protect.s2k.mode = 0;
1371 sk->protect.s2k.hash_algo = GCRY_MD_MD5;
1373 printf( "\tprotect algo: %d (hash algo: %d)\n",
1374 sk->protect.algo, sk->protect.s2k.hash_algo );
1376 /* It is really ugly that we don't know the size
1377 * of the IV here in cases we are not aware of the algorithm.
1379 * sk->protect.ivlen = cipher_get_blocksize(sk->protect.algo);
1380 * won't work. The only solution I see is to hardwire it here.
1381 * NOTE: if you change the ivlen above 16, don't forget to
1384 switch( sk->protect.algo ) {
1385 case 7: case 8: case 9: /* reserved for AES */
1386 case 10: /* Twofish */
1387 sk->protect.ivlen = 16;
1390 sk->protect.ivlen = 8;
1392 if( pktlen < sk->protect.ivlen ) {
1393 rc = G10ERR_INVALID_PACKET;
1396 for(i=0; i < sk->protect.ivlen && pktlen; i++, pktlen-- )
1397 temp[i] = iobuf_get_noeof(inp);
1399 printf( "\tprotect IV: ");
1400 for(i=0; i < sk->protect.ivlen; i++ )
1401 printf(" %02x", temp[i] );
1404 memcpy(sk->protect.iv, temp, sk->protect.ivlen );
1407 sk->is_protected = 0;
1408 /* It does not make sense to read it into secure memory.
1409 * If the user is so careless, not to protect his secret key,
1410 * we can assume, that he operates an open system :=(.
1411 * So we put the key into secure memory when we unprotect it. */
1412 if( is_v4 && sk->is_protected ) {
1413 /* ugly; the length is encrypted too, so we read all
1414 * stuff up to the end of the packet into the first
1415 * skey element (which is the one indexed by npkey) */
1416 sk->skey[npkey] = gcry_mpi_set_opaque(NULL,
1417 read_rest(inp, pktlen), pktlen*8 );
1420 printf("\tencrypted stuff follows\n");
1423 else { /* v3 method: the mpi length is not encrypted */
1424 for(i=npkey; i < nskey; i++ ) {
1426 sk->skey[i] = mpi_read_opaque(inp, &n );
1429 printf( "\tskey[%d]: ", i);
1430 if( sk->is_protected )
1431 printf( "[encrypted]\n");
1433 mpi_print(stdout, sk->skey[i], mpi_print_mode );
1439 sk->csum = read_16(inp); pktlen -= 2;
1441 printf("\tchecksum: %04hx\n", sk->csum);
1446 PKT_public_key *pk = pkt->pkt.public_key;
1449 pk->pkey[0] = gcry_mpi_set_opaque( NULL,
1450 read_rest(inp, pktlen), pktlen*8 );
1455 for(i=0; i < npkey; i++ ) {
1456 n = pktlen; pk->pkey[i] = mpi_read(inp, &n, 0 ); pktlen -=n;
1458 printf( "\tpkey[%d]: ", i);
1459 mpi_print(stdout, pk->pkey[i], mpi_print_mode );
1466 skip_rest(inp, pktlen);
1472 parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
1476 packet->pkt.user_id = gcry_xmalloc(sizeof *packet->pkt.user_id + pktlen);
1477 packet->pkt.user_id->len = pktlen;
1478 p = packet->pkt.user_id->name;
1479 for( ; pktlen; pktlen--, p++ )
1480 *p = iobuf_get_noeof(inp);
1484 int n = packet->pkt.user_id->len;
1485 printf(":user ID packet: \"");
1486 /* fixme: Hey why don't we replace this wioth print_string?? */
1487 for(p=packet->pkt.user_id->name; n; p++, n-- ) {
1488 if( *p >= ' ' && *p <= 'z' )
1491 printf("\\x%02x", *p );
1501 parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
1505 packet->pkt.comment = gcry_xmalloc(sizeof *packet->pkt.comment + pktlen - 1);
1506 packet->pkt.comment->len = pktlen;
1507 p = packet->pkt.comment->data;
1508 for( ; pktlen; pktlen--, p++ )
1509 *p = iobuf_get_noeof(inp);
1512 int n = packet->pkt.comment->len;
1513 printf(":%scomment packet: \"", pkttype == PKT_OLD_COMMENT?
1514 "OpenPGP draft " : "" );
1515 for(p=packet->pkt.comment->data; n; p++, n-- ) {
1516 if( *p >= ' ' && *p <= 'z' )
1519 printf("\\x%02x", *p );
1528 parse_trust( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
1532 c = iobuf_get_noeof(inp);
1533 pkt->pkt.ring_trust = gcry_xmalloc( sizeof *pkt->pkt.ring_trust );
1534 pkt->pkt.ring_trust->trustval = c;
1536 printf(":trust packet: flag=%02x\n", c );
1541 parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
1542 PACKET *pkt, int new_ctb )
1549 if( pktlen && pktlen < 6 ) {
1550 log_error("packet(%d) too short (%lu)\n", pkttype, (ulong)pktlen);
1553 mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
1554 namelen = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
1555 pt = pkt->pkt.plaintext = gcry_xmalloc(sizeof *pkt->pkt.plaintext + namelen -1);
1556 pt->new_ctb = new_ctb;
1558 pt->namelen = namelen;
1560 for( i=0; pktlen > 4 && i < namelen; pktlen--, i++ )
1561 pt->name[i] = iobuf_get_noeof(inp);
1564 for( i=0; i < namelen; i++ )
1565 if( (c=iobuf_get(inp)) == -1 )
1570 pt->timestamp = read_32(inp); if( pktlen) pktlen -= 4;
1576 printf(":literal data packet:\n"
1577 "\tmode %c, created %lu, name=\"",
1578 mode >= ' ' && mode <'z'? mode : '?',
1579 (ulong)pt->timestamp );
1580 for(p=pt->name,i=0; i < namelen; p++, i++ ) {
1581 if( *p >= ' ' && *p <= 'z' )
1584 printf("\\x%02x", *p );
1586 printf("\",\n\traw data: %lu bytes\n", (ulong)pt->len );
1595 parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
1596 PACKET *pkt, int new_ctb )
1600 /* pktlen is here 0, but data follows
1601 * (this should be the last object in a file or
1602 * the compress algorithm should know the length)
1604 zd = pkt->pkt.compressed = gcry_xmalloc(sizeof *pkt->pkt.compressed );
1605 zd->len = 0; /* not yet used */
1606 zd->algorithm = iobuf_get_noeof(inp);
1607 zd->new_ctb = new_ctb;
1610 printf(":compressed packet: algo=%d\n", zd->algorithm);
1616 parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
1617 PACKET *pkt, int new_ctb )
1621 ed = pkt->pkt.encrypted = gcry_xmalloc(sizeof *pkt->pkt.encrypted );
1624 ed->new_ctb = new_ctb;
1626 if( pkttype == PKT_ENCRYPTED_MDC ) {
1627 /* test: this is the new encrypted_mdc packet */
1628 /* fixme: add some pktlen sanity checks */
1629 int version, method;
1631 version = iobuf_get_noeof(inp); pktlen--;
1632 if( version != 1 ) {
1633 log_error("encrypted_mdc packet with unknown version %d\n",
1637 method = iobuf_get_noeof(inp); pktlen--;
1638 if( method != GCRY_MD_SHA1 ) {
1639 log_error("encrypted_mdc does not use SHA1 method\n" );
1642 ed->mdc_method = method;
1644 if( pktlen && pktlen < 10 ) { /* actually this is blocksize+2 */
1645 log_error("packet(%d) too short\n", pkttype);
1646 skip_rest(inp, pktlen);
1651 printf(":encrypted data packet:\n\tlength: %lu\n", pktlen);
1653 printf(":encrypted data packet:\n\tlength: unknown\n");
1654 if( ed->mdc_method )
1655 printf("\tmdc_method: %d\n", ed->mdc_method );