summaryrefslogtreecommitdiffstats
path: root/g10/parse-packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/parse-packet.c')
-rw-r--r--g10/parse-packet.c2260
1 files changed, 0 insertions, 2260 deletions
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
deleted file mode 100644
index bce3ce308..000000000
--- a/g10/parse-packet.c
+++ /dev/null
@@ -1,2260 +0,0 @@
-/* parse-packet.c - read packets
- * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#include "packet.h"
-#include "iobuf.h"
-#include "mpi.h"
-#include "util.h"
-#include "cipher.h"
-#include "memory.h"
-#include "filter.h"
-#include "photoid.h"
-#include "options.h"
-#include "main.h"
-#include "i18n.h"
-
-static int mpi_print_mode = 0;
-static int list_mode = 0;
-
-static int parse( IOBUF inp, PACKET *pkt, int onlykeypkts,
- off_t *retpos, int *skip, IOBUF out, int do_skip
- #ifdef DEBUG_PARSE_PACKET
- ,const char *dbg_w, const char *dbg_f, int dbg_l
- #endif
- );
-static int copy_packet( IOBUF inp, IOBUF out, int pkttype,
- unsigned long pktlen );
-static void skip_packet( IOBUF inp, int pkttype, unsigned long pktlen );
-static void skip_rest( IOBUF inp, unsigned long pktlen );
-static void *read_rest( IOBUF inp, size_t pktlen );
-static int parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen,
- PACKET *packet );
-static int parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen,
- PACKET *packet );
-static int parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
- PKT_signature *sig );
-static int parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
- PKT_onepass_sig *ops );
-static int parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
- byte *hdr, int hdrlen, PACKET *packet );
-static int parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen,
- PACKET *packet );
-static int parse_attribute( IOBUF inp, int pkttype, unsigned long pktlen,
- PACKET *packet );
-static int parse_comment( IOBUF inp, int pkttype, unsigned long pktlen,
- PACKET *packet );
-static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen,
- PACKET *packet );
-static int parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
- PACKET *packet, int new_ctb);
-static int parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
- PACKET *packet, int new_ctb );
-static int parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
- PACKET *packet, int new_ctb);
-static int parse_mdc( IOBUF inp, int pkttype, unsigned long pktlen,
- PACKET *packet, int new_ctb);
-static int parse_gpg_control( IOBUF inp, int pkttype, unsigned long pktlen,
- PACKET *packet );
-
-static unsigned short
-read_16(IOBUF inp)
-{
- unsigned short a;
- a = iobuf_get_noeof(inp) << 8;
- a |= iobuf_get_noeof(inp);
- return a;
-}
-
-static unsigned long
-read_32(IOBUF inp)
-{
- unsigned long a;
- a = iobuf_get_noeof(inp) << 24;
- a |= iobuf_get_noeof(inp) << 16;
- a |= iobuf_get_noeof(inp) << 8;
- a |= iobuf_get_noeof(inp);
- return a;
-}
-
-
-int
-set_packet_list_mode( int mode )
-{
- int old = list_mode;
- list_mode = mode;
- mpi_print_mode = DBG_MPI;
- return old;
-}
-
-static void
-unknown_pubkey_warning( int algo )
-{
- static byte unknown_pubkey_algos[256];
-
- algo &= 0xff;
- if( !unknown_pubkey_algos[algo] ) {
- if( opt.verbose )
- log_info(_("can't handle public key algorithm %d\n"), algo );
- unknown_pubkey_algos[algo] = 1;
- }
-}
-
-/****************
- * Parse a Packet and return it in packet
- * Returns: 0 := valid packet in pkt
- * -1 := no more packets
- * >0 := error
- * Note: The function may return an error and a partly valid packet;
- * caller must free this packet.
- */
-#ifdef DEBUG_PARSE_PACKET
-int
-dbg_parse_packet( IOBUF inp, PACKET *pkt, const char *dbg_f, int dbg_l )
-{
- int skip, rc;
-
- do {
- rc = parse( inp, pkt, 0, NULL, &skip, NULL, 0, "parse", dbg_f, dbg_l );
- } while( skip );
- return rc;
-}
-#else
-int
-parse_packet( IOBUF inp, PACKET *pkt )
-{
- int skip, rc;
-
- do {
- rc = parse( inp, pkt, 0, NULL, &skip, NULL, 0 );
- } while( skip );
- return rc;
-}
-#endif
-
-/****************
- * Like parse packet, but only return secret or public (sub)key packets.
- */
-#ifdef DEBUG_PARSE_PACKET
-int
-dbg_search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid,
- const char *dbg_f, int dbg_l )
-{
- int skip, rc;
-
- do {
- rc = parse( inp, pkt, with_uid?2:1, retpos, &skip, NULL, 0, "search", dbg_f, dbg_l );
- } while( skip );
- return rc;
-}
-#else
-int
-search_packet( IOBUF inp, PACKET *pkt, off_t *retpos, int with_uid )
-{
- int skip, rc;
-
- do {
- rc = parse( inp, pkt, with_uid?2:1, retpos, &skip, NULL, 0 );
- } while( skip );
- return rc;
-}
-#endif
-
-/****************
- * Copy all packets from INP to OUT, thereby removing unused spaces.
- */
-#ifdef DEBUG_PARSE_PACKET
-int
-dbg_copy_all_packets( IOBUF inp, IOBUF out,
- const char *dbg_f, int dbg_l )
-{
- PACKET pkt;
- int skip, rc=0;
- do {
- init_packet(&pkt);
- } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0, "copy", dbg_f, dbg_l )));
- return rc;
-}
-#else
-int
-copy_all_packets( IOBUF inp, IOBUF out )
-{
- PACKET pkt;
- int skip, rc=0;
- do {
- init_packet(&pkt);
- } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0 )));
- return rc;
-}
-#endif
-
-/****************
- * Copy some packets from INP to OUT, thereby removing unused spaces.
- * Stop at offset STOPoff (i.e. don't copy packets at this or later offsets)
- */
-#ifdef DEBUG_PARSE_PACKET
-int
-dbg_copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff,
- const char *dbg_f, int dbg_l )
-{
- PACKET pkt;
- int skip, rc=0;
- do {
- if( iobuf_tell(inp) >= stopoff )
- return 0;
- init_packet(&pkt);
- } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0,
- "some", dbg_f, dbg_l )) );
- return rc;
-}
-#else
-int
-copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff )
-{
- PACKET pkt;
- int skip, rc=0;
- do {
- if( iobuf_tell(inp) >= stopoff )
- return 0;
- init_packet(&pkt);
- } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0 )) );
- return rc;
-}
-#endif
-
-/****************
- * Skip over N packets
- */
-#ifdef DEBUG_PARSE_PACKET
-int
-dbg_skip_some_packets( IOBUF inp, unsigned n,
- const char *dbg_f, int dbg_l )
-{
- int skip, rc=0;
- PACKET pkt;
-
- for( ;n && !rc; n--) {
- init_packet(&pkt);
- rc = parse( inp, &pkt, 0, NULL, &skip, NULL, 1, "skip", dbg_f, dbg_l );
- }
- return rc;
-}
-#else
-int
-skip_some_packets( IOBUF inp, unsigned n )
-{
- int skip, rc=0;
- PACKET pkt;
-
- for( ;n && !rc; n--) {
- init_packet(&pkt);
- rc = parse( inp, &pkt, 0, NULL, &skip, NULL, 1 );
- }
- return rc;
-}
-#endif
-
-
-/****************
- * Parse packet. Set the variable skip points to 1 if the packet
- * should be skipped; this is the case if either ONLYKEYPKTS is set
- * and the parsed packet isn't one or the
- * packet-type is 0, indicating deleted stuff.
- * if OUT is not NULL, a special copymode is used.
- */
-static int
-parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
- int *skip, IOBUF out, int do_skip
-#ifdef DEBUG_PARSE_PACKET
- ,const char *dbg_w, const char *dbg_f, int dbg_l
-#endif
- )
-{
- int rc=0, c, ctb, pkttype, lenbytes;
- unsigned long pktlen;
- byte hdr[8];
- int hdrlen;
- int new_ctb = 0;
- int with_uid = (onlykeypkts == 2);
-
- *skip = 0;
- assert( !pkt->pkt.generic );
- if( retpos )
- *retpos = iobuf_tell(inp);
-
- if( (ctb = iobuf_get(inp)) == -1 ) {
- rc = -1;
- goto leave;
- }
- hdrlen=0;
- hdr[hdrlen++] = ctb;
- if( !(ctb & 0x80) ) {
- log_error("%s: invalid packet (ctb=%02x)\n", iobuf_where(inp), ctb );
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
- pktlen = 0;
- new_ctb = !!(ctb & 0x40);
- if( new_ctb ) {
- pkttype = ctb & 0x3f;
- if( (c = iobuf_get(inp)) == -1 ) {
- log_error("%s: 1st length byte missing\n", iobuf_where(inp) );
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
- if (pkttype == PKT_COMPRESSED) {
- iobuf_set_partial_block_mode(inp, c & 0xff);
- pktlen = 0;/* to indicate partial length */
- }
- else {
- hdr[hdrlen++] = c;
- if( c < 192 )
- pktlen = c;
- else if( c < 224 ) {
- pktlen = (c - 192) * 256;
- if( (c = iobuf_get(inp)) == -1 ) {
- log_error("%s: 2nd length byte missing\n",
- iobuf_where(inp) );
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
- hdr[hdrlen++] = c;
- pktlen += c + 192;
- }
- else if( c == 255 ) {
- pktlen = (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 24;
- pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 16;
- pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 8;
- if( (c = iobuf_get(inp)) == -1 ) {
- log_error("%s: 4 byte length invalid\n",
- iobuf_where(inp) );
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
- pktlen |= (hdr[hdrlen++] = c );
- }
- else { /* partial body length */
- iobuf_set_partial_block_mode(inp, c & 0xff);
- pktlen = 0;/* to indicate partial length */
- }
- }
- }
- else {
- pkttype = (ctb>>2)&0xf;
- lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3));
- if( !lenbytes ) {
- pktlen = 0; /* don't know the value */
- if( pkttype != PKT_COMPRESSED )
- iobuf_set_block_mode(inp, 1);
- }
- else {
- for( ; lenbytes; lenbytes-- ) {
- pktlen <<= 8;
- pktlen |= hdr[hdrlen++] = iobuf_get_noeof(inp);
- }
- }
- }
-
- if (pktlen == 0xffffffff) {
- /* with a some probability this is caused by a problem in the
- * the uncompressing layer - in some error cases it just loops
- * and spits out 0xff bytes. */
- log_error ("%s: garbled packet detected\n", iobuf_where(inp) );
- g10_exit (2);
- }
-
- if( out && pkttype ) {
- if( iobuf_write( out, hdr, hdrlen ) == -1 )
- rc = G10ERR_WRITE_FILE;
- else
- rc = copy_packet(inp, out, pkttype, pktlen );
- goto leave;
- }
-
- if (with_uid && pkttype == PKT_USER_ID)
- ;
- else if( do_skip
- || !pkttype
- || (onlykeypkts && pkttype != PKT_PUBLIC_SUBKEY
- && pkttype != PKT_PUBLIC_KEY
- && pkttype != PKT_SECRET_SUBKEY
- && pkttype != PKT_SECRET_KEY ) ) {
- skip_rest(inp, pktlen);
- *skip = 1;
- rc = 0;
- goto leave;
- }
-
- if( DBG_PACKET ) {
-#ifdef DEBUG_PARSE_PACKET
- log_debug("parse_packet(iob=%d): type=%d length=%lu%s (%s.%s.%d)\n",
- iobuf_id(inp), pkttype, pktlen, new_ctb?" (new_ctb)":"",
- dbg_w, dbg_f, dbg_l );
-#else
- log_debug("parse_packet(iob=%d): type=%d length=%lu%s\n",
- iobuf_id(inp), pkttype, pktlen, new_ctb?" (new_ctb)":"" );
-#endif
- }
- pkt->pkttype = pkttype;
- rc = G10ERR_UNKNOWN_PACKET; /* default error */
- switch( pkttype ) {
- case PKT_PUBLIC_KEY:
- case PKT_PUBLIC_SUBKEY:
- pkt->pkt.public_key = m_alloc_clear(sizeof *pkt->pkt.public_key );
- rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt );
- break;
- case PKT_SECRET_KEY:
- case PKT_SECRET_SUBKEY:
- pkt->pkt.secret_key = m_alloc_clear(sizeof *pkt->pkt.secret_key );
- rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt );
- break;
- case PKT_SYMKEY_ENC:
- rc = parse_symkeyenc( inp, pkttype, pktlen, pkt );
- break;
- case PKT_PUBKEY_ENC:
- rc = parse_pubkeyenc(inp, pkttype, pktlen, pkt );
- break;
- case PKT_SIGNATURE:
- pkt->pkt.signature = m_alloc_clear(sizeof *pkt->pkt.signature );
- rc = parse_signature(inp, pkttype, pktlen, pkt->pkt.signature );
- break;
- case PKT_ONEPASS_SIG:
- pkt->pkt.onepass_sig = m_alloc_clear(sizeof *pkt->pkt.onepass_sig );
- rc = parse_onepass_sig(inp, pkttype, pktlen, pkt->pkt.onepass_sig );
- break;
- case PKT_USER_ID:
- rc = parse_user_id(inp, pkttype, pktlen, pkt );
- break;
- case PKT_ATTRIBUTE:
- pkt->pkttype = pkttype = PKT_USER_ID; /* we store it in the userID */
- rc = parse_attribute(inp, pkttype, pktlen, pkt);
- break;
- case PKT_OLD_COMMENT:
- case PKT_COMMENT:
- rc = parse_comment(inp, pkttype, pktlen, pkt);
- break;
- case PKT_RING_TRUST:
- parse_trust(inp, pkttype, pktlen, pkt);
- rc = 0;
- break;
- case PKT_PLAINTEXT:
- rc = parse_plaintext(inp, pkttype, pktlen, pkt, new_ctb );
- break;
- case PKT_COMPRESSED:
- rc = parse_compressed(inp, pkttype, pktlen, pkt, new_ctb );
- break;
- case PKT_ENCRYPTED:
- case PKT_ENCRYPTED_MDC:
- rc = parse_encrypted(inp, pkttype, pktlen, pkt, new_ctb );
- break;
- case PKT_MDC:
- rc = parse_mdc(inp, pkttype, pktlen, pkt, new_ctb );
- break;
- case PKT_GPG_CONTROL:
- rc = parse_gpg_control(inp, pkttype, pktlen, pkt );
- break;
- default:
- skip_packet(inp, pkttype, pktlen);
- break;
- }
-
- leave:
- if( !rc && iobuf_error(inp) )
- rc = G10ERR_INV_KEYRING;
- return rc;
-}
-
-static void
-dump_hex_line( int c, int *i )
-{
- if( *i && !(*i%8) ) {
- if( *i && !(*i%24) )
- printf("\n%4d:", *i );
- else
- putchar(' ');
- }
- if( c == -1 )
- printf(" EOF" );
- else
- printf(" %02x", c );
- ++*i;
-}
-
-
-static int
-copy_packet( IOBUF inp, IOBUF out, int pkttype, unsigned long pktlen )
-{
- int n;
- char buf[100];
-
- if( iobuf_in_block_mode(inp) ) {
- while( (n = iobuf_read( inp, buf, 100 )) != -1 )
- if( iobuf_write(out, buf, n ) )
- return G10ERR_WRITE_FILE; /* write error */
- }
- else if( !pktlen && pkttype == PKT_COMPRESSED ) {
- log_debug("copy_packet: compressed!\n");
- /* compressed packet, copy till EOF */
- while( (n = iobuf_read( inp, buf, 100 )) != -1 )
- if( iobuf_write(out, buf, n ) )
- return G10ERR_WRITE_FILE; /* write error */
- }
- else {
- for( ; pktlen; pktlen -= n ) {
- n = pktlen > 100 ? 100 : pktlen;
- n = iobuf_read( inp, buf, n );
- if( n == -1 )
- return G10ERR_READ_FILE;
- if( iobuf_write(out, buf, n ) )
- return G10ERR_WRITE_FILE; /* write error */
- }
- }
- return 0;
-}
-
-
-static void
-skip_packet( IOBUF inp, int pkttype, unsigned long pktlen )
-{
- if( list_mode ) {
- if( pkttype == PKT_MARKER )
- fputs(":marker packet:\n", stdout );
- else
- printf(":unknown packet: type %2d, length %lu\n", pkttype, pktlen);
- if( pkttype ) {
- int c, i=0 ;
- if( pkttype != PKT_MARKER )
- fputs("dump:", stdout );
- if( iobuf_in_block_mode(inp) ) {
- while( (c=iobuf_get(inp)) != -1 )
- dump_hex_line(c, &i);
- }
- else {
- for( ; pktlen; pktlen-- )
- dump_hex_line(iobuf_get(inp), &i);
- }
- putchar('\n');
- return;
- }
- }
- skip_rest(inp,pktlen);
-}
-
-static void
-skip_rest( IOBUF inp, unsigned long pktlen )
-{
- if( iobuf_in_block_mode(inp) ) {
- while( iobuf_get(inp) != -1 )
- ;
- }
- else {
- for( ; pktlen; pktlen-- )
- if( iobuf_get(inp) == -1 )
- break;
- }
-}
-
-
-static void *
-read_rest( IOBUF inp, size_t pktlen )
-{
- byte *p;
- int i;
-
- if( iobuf_in_block_mode(inp) ) {
- log_error("read_rest: can't store stream data\n");
- p = NULL;
- }
- else {
- p = m_alloc( pktlen );
- for(i=0; pktlen; pktlen--, i++ )
- p[i] = iobuf_get(inp);
- }
- return p;
-}
-
-
-
-static int
-parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
-{
- PKT_symkey_enc *k;
- int rc = 0;
- int i, version, s2kmode, cipher_algo, hash_algo, seskeylen, minlen;
-
- if( pktlen < 4 ) {
- log_error("packet(%d) too short\n", pkttype);
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
- version = iobuf_get_noeof(inp); pktlen--;
- if( version != 4 ) {
- log_error("packet(%d) with unknown version %d\n", pkttype, version);
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
- if( pktlen > 200 ) { /* (we encode the seskeylen in a byte) */
- log_error("packet(%d) too large\n", pkttype);
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
- cipher_algo = iobuf_get_noeof(inp); pktlen--;
- s2kmode = iobuf_get_noeof(inp); pktlen--;
- hash_algo = iobuf_get_noeof(inp); pktlen--;
- switch( s2kmode ) {
- case 0: /* simple s2k */
- minlen = 0;
- break;
- case 1: /* salted s2k */
- minlen = 8;
- break;
- case 3: /* iterated+salted s2k */
- minlen = 9;
- break;
- default:
- log_error("unknown S2K %d\n", s2kmode );
- goto leave;
- }
- if( minlen > pktlen ) {
- log_error("packet with S2K %d too short\n", s2kmode );
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
- seskeylen = pktlen - minlen;
- k = packet->pkt.symkey_enc = m_alloc_clear( sizeof *packet->pkt.symkey_enc
- + seskeylen - 1 );
- k->version = version;
- k->cipher_algo = cipher_algo;
- k->s2k.mode = s2kmode;
- k->s2k.hash_algo = hash_algo;
- if( s2kmode == 1 || s2kmode == 3 ) {
- for(i=0; i < 8 && pktlen; i++, pktlen-- )
- k->s2k.salt[i] = iobuf_get_noeof(inp);
- }
- if( s2kmode == 3 ) {
- k->s2k.count = iobuf_get(inp); pktlen--;
- }
- k->seskeylen = seskeylen;
- for(i=0; i < seskeylen && pktlen; i++, pktlen-- )
- k->seskey[i] = iobuf_get_noeof(inp);
- assert( !pktlen );
-
- if( list_mode ) {
- printf(":symkey enc packet: version %d, cipher %d, s2k %d, hash %d\n",
- version, cipher_algo, s2kmode, hash_algo);
- if( s2kmode == 1 || s2kmode == 3 ) {
- printf("\tsalt ");
- for(i=0; i < 8; i++ )
- printf("%02x", k->s2k.salt[i]);
- if( s2kmode == 3 )
- printf(", count %lu\n", (ulong)k->s2k.count );
- printf("\n");
- }
- }
-
- leave:
- skip_rest(inp, pktlen);
- return rc;
-}
-
-static int
-parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
-{
- unsigned int n;
- int rc = 0;
- int i, ndata;
- PKT_pubkey_enc *k;
-
- k = packet->pkt.pubkey_enc = m_alloc_clear(sizeof *packet->pkt.pubkey_enc);
- if( pktlen < 12 ) {
- log_error("packet(%d) too short\n", pkttype);
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
- k->version = iobuf_get_noeof(inp); pktlen--;
- if( k->version != 2 && k->version != 3 ) {
- log_error("packet(%d) with unknown version %d\n", pkttype, k->version);
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
- k->keyid[0] = read_32(inp); pktlen -= 4;
- k->keyid[1] = read_32(inp); pktlen -= 4;
- k->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
- k->throw_keyid = 0; /* only used as flag for build_packet */
- if( list_mode )
- printf(":pubkey enc packet: version %d, algo %d, keyid %08lX%08lX\n",
- k->version, k->pubkey_algo, (ulong)k->keyid[0], (ulong)k->keyid[1]);
-
- ndata = pubkey_get_nenc(k->pubkey_algo);
- if( !ndata ) {
- if( list_mode )
- printf("\tunsupported algorithm %d\n", k->pubkey_algo );
- unknown_pubkey_warning( k->pubkey_algo );
- k->data[0] = NULL; /* no need to store the encrypted data */
- }
- else {
- for( i=0; i < ndata; i++ ) {
- n = pktlen;
- k->data[i] = mpi_read(inp, &n, 0); pktlen -=n;
- if( list_mode ) {
- printf("\tdata: ");
- mpi_print(stdout, k->data[i], mpi_print_mode );
- putchar('\n');
- }
- if (!k->data[i])
- rc = G10ERR_INVALID_PACKET;
- }
- }
-
- leave:
- skip_rest(inp, pktlen);
- return rc;
-}
-
-
-static void
-dump_sig_subpkt( int hashed, int type, int critical,
- const byte *buffer, size_t buflen, size_t length )
-{
- const char *p=NULL;
- int i;
-
- /* The CERT has warning out with explains how to use GNUPG to
- * detect the ARRs - we print our old message here when it is a faked
- * ARR and add an additional notice */
- if ( type == SIGSUBPKT_ARR && !hashed ) {
- printf("\tsubpkt %d len %u (additional recipient request)\n"
- "WARNING: PGP versions > 5.0 and < 6.5.8 will automagically "
- "encrypt to this key and thereby reveal the plaintext to "
- "the owner of this ARR key. Detailed info follows:\n",
- type, (unsigned)length );
- }
-
-
- printf("\t%s%ssubpkt %d len %u (", /*)*/
- critical ? "critical ":"",
- hashed ? "hashed ":"", type, (unsigned)length );
- buffer++;
- length--;
- if( length > buflen ) {
- printf("too short: buffer is only %u)\n", (unsigned)buflen );
- return;
- }
- switch( type ) {
- case SIGSUBPKT_SIG_CREATED:
- if( length >= 4 )
- printf("sig created %s", strtimestamp( buffer_to_u32(buffer) ) );
- break;
- case SIGSUBPKT_SIG_EXPIRE:
- if( length >= 4 )
- printf("sig expires after %s",
- strtimevalue( buffer_to_u32(buffer) ) );
- break;
- case SIGSUBPKT_EXPORTABLE:
- if( length )
- printf("%sexportable", *buffer? "":"not ");
- break;
- case SIGSUBPKT_TRUST:
- if(length!=2)
- p="[invalid trust signature]";
- else
- printf("trust signature of level %d, amount %d",buffer[0],buffer[1]);
- break;
- case SIGSUBPKT_REGEXP:
- if(!length)
- p="[invalid regexp]";
- else
- printf("regular expression: \"%s\"",buffer);
- break;
- case SIGSUBPKT_REVOCABLE:
- if( length )
- printf("%srevocable", *buffer? "":"not ");
- break;
- case SIGSUBPKT_KEY_EXPIRE:
- if( length >= 4 )
- printf("key expires after %s",
- strtimevalue( buffer_to_u32(buffer) ) );
- break;
- case SIGSUBPKT_PREF_SYM:
- fputs("pref-sym-algos:", stdout );
- for( i=0; i < length; i++ )
- printf(" %d", buffer[i] );
- break;
- case SIGSUBPKT_REV_KEY:
- fputs("revocation key: ", stdout );
- if( length < 22 )
- p = "[too short]";
- else {
- printf("c=%02x a=%d f=", buffer[0], buffer[1] );
- for( i=2; i < length; i++ )
- printf("%02X", buffer[i] );
- }
- break;
- case SIGSUBPKT_ISSUER:
- if( length >= 8 )
- printf("issuer key ID %08lX%08lX",
- (ulong)buffer_to_u32(buffer),
- (ulong)buffer_to_u32(buffer+4) );
- break;
- case SIGSUBPKT_NOTATION:
- {
- fputs("notation: ", stdout );
- if( length < 8 )
- p = "[too short]";
- else if( !(*buffer & 0x80) )
- p = "[not human readable]";
- else {
- const byte *s = buffer;
- size_t n1, n2;
-
- n1 = (s[4] << 8) | s[5];
- n2 = (s[6] << 8) | s[7];
- s += 8;
- if( 8+n1+n2 != length )
- p = "[error]";
- else {
- print_string( stdout, s, n1, ')' );
- putc( '=', stdout );
- print_string( stdout, s+n1, n2, ')' );
- }
- }
- }
- break;
- case SIGSUBPKT_PREF_HASH:
- fputs("pref-hash-algos:", stdout );
- for( i=0; i < length; i++ )
- printf(" %d", buffer[i] );
- break;
- case SIGSUBPKT_PREF_COMPR:
- fputs("pref-zip-algos:", stdout );
- for( i=0; i < length; i++ )
- printf(" %d", buffer[i] );
- break;
- case SIGSUBPKT_KS_FLAGS:
- fputs("key server preferences:",stdout);
- for(i=0;i<length;i++)
- printf(" %02X", buffer[i]);
- break;
- case SIGSUBPKT_PREF_KS:
- p = "preferred key server";
- break;
- case SIGSUBPKT_PRIMARY_UID:
- p = "primary user ID";
- break;
- case SIGSUBPKT_POLICY:
- fputs("policy: ", stdout );
- print_string( stdout, buffer, length, ')' );
- break;
- case SIGSUBPKT_KEY_FLAGS:
- fputs ( "key flags:", stdout );
- for( i=0; i < length; i++ )
- printf(" %02X", buffer[i] );
- break;
- case SIGSUBPKT_SIGNERS_UID:
- p = "signer's user ID";
- break;
- case SIGSUBPKT_REVOC_REASON:
- if( length ) {
- printf("revocation reason 0x%02x (", *buffer );
- print_string( stdout, buffer+1, length-1, ')' );
- p = ")";
- }
- break;
- case SIGSUBPKT_ARR:
- fputs("Big Brother's key (ignored): ", stdout );
- if( length < 22 )
- p = "[too short]";
- else {
- printf("c=%02x a=%d f=", buffer[0], buffer[1] );
- for( i=2; i < length; i++ )
- printf("%02X", buffer[i] );
- }
- break;
- case SIGSUBPKT_FEATURES:
- fputs ( "features:", stdout );
- for( i=0; i < length; i++ )
- printf(" %02x", buffer[i] );
- break;
- case SIGSUBPKT_PRIV_VERIFY_CACHE:
- p = "obsolete verification cache";
- break;
- default: p = "?"; break;
- }
-
- printf("%s)\n", p? p: "");
-}
-
-/****************
- * Returns: >= 0 offset into buffer
- * -1 unknown type
- * -2 unsupported type
- * -3 subpacket too short
- */
-int
-parse_one_sig_subpkt( const byte *buffer, size_t n, int type )
-{
- switch( type ) {
- case SIGSUBPKT_REV_KEY:
- if(n < 22)
- break;
- return 0;
- case SIGSUBPKT_SIG_CREATED:
- case SIGSUBPKT_SIG_EXPIRE:
- case SIGSUBPKT_KEY_EXPIRE:
- if( n < 4 )
- break;
- return 0;
- case SIGSUBPKT_KEY_FLAGS:
- case SIGSUBPKT_KS_FLAGS:
- case SIGSUBPKT_PREF_SYM:
- case SIGSUBPKT_PREF_HASH:
- case SIGSUBPKT_PREF_COMPR:
- case SIGSUBPKT_POLICY:
- case SIGSUBPKT_FEATURES:
- return 0;
- case SIGSUBPKT_EXPORTABLE:
- case SIGSUBPKT_REVOCABLE:
- if( !n )
- break;
- return 0;
- case SIGSUBPKT_ISSUER: /* issuer key ID */
- if( n < 8 )
- break;
- return 0;
- case SIGSUBPKT_NOTATION:
- if( n < 8 ) /* minimum length needed */
- break;
- return 0;
- case SIGSUBPKT_REVOC_REASON:
- if( !n )
- break;
- return 0;
- case SIGSUBPKT_PRIMARY_UID:
- if ( n != 1 )
- break;
- return 0;
- case SIGSUBPKT_PRIV_VERIFY_CACHE:
- /* We used this in gpg 1.0.5 and 1.0.6 to cache signature
- * verification results - it is no longer used.
- * "GPG" 0x00 <mode> <stat>
- * where mode == 1: valid data, stat == 0: invalid signature
- * stat == 1: valid signature
- * (because we use private data, we check our marker) */
- if( n < 6 )
- break;
- if( buffer[0] != 'G' || buffer[1] != 'P'
- || buffer[2] != 'G' || buffer[3] )
- return -2;
- return 4;
- default: return -1;
- }
- return -3;
-}
-
-
-static int
-can_handle_critical( const byte *buffer, size_t n, int type )
-{
- switch( type ) {
- case SIGSUBPKT_NOTATION:
- if( n >= 8 && (*buffer & 0x80) )
- return 1; /* human readable is handled */
- return 0;
-
- case SIGSUBPKT_SIG_CREATED:
- case SIGSUBPKT_SIG_EXPIRE:
- case SIGSUBPKT_KEY_EXPIRE:
- case SIGSUBPKT_EXPORTABLE:
- case SIGSUBPKT_REVOCABLE:
- case SIGSUBPKT_REV_KEY:
- case SIGSUBPKT_ISSUER:/* issuer key ID */
- case SIGSUBPKT_PREF_SYM:
- case SIGSUBPKT_PREF_HASH:
- case SIGSUBPKT_PREF_COMPR:
- case SIGSUBPKT_KEY_FLAGS:
- case SIGSUBPKT_PRIMARY_UID:
- case SIGSUBPKT_FEATURES:
- case SIGSUBPKT_POLICY: /* Is it enough to show the policy? */
- return 1;
-
- default:
- return 0;
- }
-}
-
-
-const byte *
-enum_sig_subpkt( const subpktarea_t *pktbuf, sigsubpkttype_t reqtype,
- size_t *ret_n, int *start, int *critical )
-{
- const byte *buffer;
- int buflen;
- int type;
- int critical_dummy;
- int offset;
- size_t n;
- int seq = 0;
- int reqseq = start? *start: 0;
-
- if(!critical)
- critical=&critical_dummy;
-
- if( !pktbuf || reqseq == -1 ) {
- /* return some value different from NULL to indicate that
- * there is no critical bit we do not understand. The caller
- * will never use the value. Yes I know, it is an ugly hack */
- return reqtype == SIGSUBPKT_TEST_CRITICAL? (const byte*)&pktbuf : NULL;
- }
- buffer = pktbuf->data;
- buflen = pktbuf->len;
- while( buflen ) {
- n = *buffer++; buflen--;
- if( n == 255 ) { /* 4 byte length header */
- if( buflen < 4 )
- goto too_short;
- n = (buffer[0] << 24) | (buffer[1] << 16)
- | (buffer[2] << 8) | buffer[3];
- buffer += 4;
- buflen -= 4;
- }
- else if( n >= 192 ) { /* 2 byte special encoded length header */
- if( buflen < 2 )
- goto too_short;
- n = (( n - 192 ) << 8) + *buffer + 192;
- buffer++;
- buflen--;
- }
- if( buflen < n )
- goto too_short;
- type = *buffer;
- if( type & 0x80 ) {
- type &= 0x7f;
- *critical = 1;
- }
- else
- *critical = 0;
- if( !(++seq > reqseq) )
- ;
- else if( reqtype == SIGSUBPKT_TEST_CRITICAL ) {
- if( *critical ) {
- if( n-1 > buflen+1 )
- goto too_short;
- if( !can_handle_critical(buffer+1, n-1, type ) ) {
- log_info(_("subpacket of type %d has critical bit set\n"),
- type);
- if( start )
- *start = seq;
- return NULL; /* this is an error */
- }
- }
- }
- else if( reqtype < 0 ) /* list packets */
- dump_sig_subpkt( reqtype == SIGSUBPKT_LIST_HASHED,
- type, *critical, buffer, buflen, n );
- else if( type == reqtype ) { /* found */
- buffer++;
- n--;
- if( n > buflen )
- goto too_short;
- if( ret_n )
- *ret_n = n;
- offset = parse_one_sig_subpkt(buffer, n, type );
- switch( offset ) {
- case -3:
- log_error("subpacket of type %d too short\n", type);
- return NULL;
- case -2:
- return NULL;
- case -1:
- BUG(); /* not yet needed */
- default:
- break;
- }
- if( start )
- *start = seq;
- return buffer+offset;
- }
- buffer += n; buflen -=n;
- }
- if( reqtype == SIGSUBPKT_TEST_CRITICAL )
- return buffer; /* as value true to indicate that there is no */
- /* critical bit we don't understand */
- if( start )
- *start = -1;
- return NULL; /* end of packets; not found */
-
- too_short:
- log_error("buffer shorter than subpacket\n");
- if( start )
- *start = -1;
- return NULL;
-}
-
-
-const byte *
-parse_sig_subpkt (const subpktarea_t *buffer, sigsubpkttype_t reqtype,
- size_t *ret_n)
-{
- return enum_sig_subpkt( buffer, reqtype, ret_n, NULL, NULL );
-}
-
-const byte *
-parse_sig_subpkt2 (PKT_signature *sig, sigsubpkttype_t reqtype,
- size_t *ret_n )
-{
- const byte *p;
-
- p = parse_sig_subpkt (sig->hashed, reqtype, ret_n );
- if( !p )
- p = parse_sig_subpkt (sig->unhashed, reqtype, ret_n );
- return p;
-}
-
-/* Find all revocation keys. Look in hashed area only. */
-void parse_revkeys(PKT_signature *sig)
-{
- struct revocation_key *revkey;
- int seq=0;
- size_t len;
-
- if(sig->sig_class!=0x1F)
- return;
-
- while((revkey=
- (struct revocation_key *)enum_sig_subpkt(sig->hashed,
- SIGSUBPKT_REV_KEY,
- &len,&seq,NULL)))
- {
- if(len==sizeof(struct revocation_key) &&
- (revkey->class&0x80)) /* 0x80 bit must be set */
- {
- sig->revkey=m_realloc(sig->revkey,
- sizeof(struct revocation_key *)*(sig->numrevkeys+1));
- sig->revkey[sig->numrevkeys]=revkey;
- sig->numrevkeys++;
- }
- }
-}
-
-static int
-parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
- PKT_signature *sig )
-{
- int md5_len=0;
- unsigned n;
- int is_v4=0;
- int rc=0;
- int i, ndata;
-
- if( pktlen < 16 ) {
- log_error("packet(%d) too short\n", pkttype);
- goto leave;
- }
- sig->version = iobuf_get_noeof(inp); pktlen--;
- if( sig->version == 4 )
- is_v4=1;
- else if( sig->version != 2 && sig->version != 3 ) {
- log_error("packet(%d) with unknown version %d\n", pkttype, sig->version);
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
-
- if( !is_v4 ) {
- md5_len = iobuf_get_noeof(inp); pktlen--;
- }
- sig->sig_class = iobuf_get_noeof(inp); pktlen--;
- if( !is_v4 ) {
- sig->timestamp = read_32(inp); pktlen -= 4;
- sig->keyid[0] = read_32(inp); pktlen -= 4;
- sig->keyid[1] = read_32(inp); pktlen -= 4;
- }
- sig->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
- sig->digest_algo = iobuf_get_noeof(inp); pktlen--;
- sig->flags.exportable=1;
- sig->flags.revocable=1;
- if( is_v4 ) { /* read subpackets */
- n = read_16(inp); pktlen -= 2; /* length of hashed data */
- if( n > 10000 ) {
- log_error("signature packet: hashed data too long\n");
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
- if( n ) {
- sig->hashed = m_alloc (sizeof (*sig->hashed) + n - 1 );
- sig->hashed->size = n;
- sig->hashed->len = n;
- if( iobuf_read (inp, sig->hashed->data, n ) != n ) {
- log_error ("premature eof while reading "
- "hashed signature data\n");
- rc = -1;
- goto leave;
- }
- pktlen -= n;
- }
- n = read_16(inp); pktlen -= 2; /* length of unhashed data */
- if( n > 10000 ) {
- log_error("signature packet: unhashed data too long\n");
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
- if( n ) {
- /* we add 8 extra bytes so that we have space for the signature
- * status cache. Well we are wasting this if there is a cache
- * packet already, but in the other case it avoids an realloc */
- sig->unhashed = m_alloc (sizeof(*sig->unhashed) + n + 8 - 1 );
- sig->unhashed->size = n + 8;
- sig->unhashed->len = n;
- if( iobuf_read(inp, sig->unhashed->data, n ) != n ) {
- log_error("premature eof while reading "
- "unhashed signature data\n");
- rc = -1;
- goto leave;
- }
- pktlen -= n;
- }
- }
-
- if( pktlen < 5 ) { /* sanity check */
- log_error("packet(%d) too short\n", pkttype);
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
-
- sig->digest_start[0] = iobuf_get_noeof(inp); pktlen--;
- sig->digest_start[1] = iobuf_get_noeof(inp); pktlen--;
-
- if( is_v4 && sig->pubkey_algo ) { /*extract required information */
- const byte *p;
-
- /* set sig->flags.unknown_critical if there is a
- * critical bit set for packets which we do not understand */
- if( !parse_sig_subpkt (sig->hashed, SIGSUBPKT_TEST_CRITICAL, NULL)
- || !parse_sig_subpkt (sig->unhashed, SIGSUBPKT_TEST_CRITICAL,
- NULL) )
- {
- sig->flags.unknown_critical = 1;
- }
-
- p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIG_CREATED, NULL );
- if( !p )
- log_error("signature packet without timestamp\n");
- else
- sig->timestamp = buffer_to_u32(p);
- p = parse_sig_subpkt2( sig, SIGSUBPKT_ISSUER, NULL );
- if( !p )
- log_error("signature packet without keyid\n");
- else {
- sig->keyid[0] = buffer_to_u32(p);
- sig->keyid[1] = buffer_to_u32(p+4);
- }
-
- p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_SIG_EXPIRE,NULL);
- if(p)
- sig->expiredate=sig->timestamp+buffer_to_u32(p);
- if(sig->expiredate && sig->expiredate<=make_timestamp())
- sig->flags.expired=1;
-
- p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_POLICY,NULL);
- if(p)
- sig->flags.policy_url=1;
-
- p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_NOTATION,NULL);
- if(p)
- sig->flags.notation=1;
-
- p=parse_sig_subpkt(sig->hashed,SIGSUBPKT_REVOCABLE,NULL);
- if(p && *p==0)
- sig->flags.revocable=0;
-
- /* We accept the exportable subpacket from either the hashed
- or unhashed areas as older versions of gpg put it in the
- unhashed area. In theory, anyway, we should never see this
- packet off of a local keyring. */
-
- p=parse_sig_subpkt2(sig,SIGSUBPKT_EXPORTABLE,NULL);
- if(p && *p==0)
- sig->flags.exportable=0;
-
- /* Find all revocation keys. */
- if(sig->sig_class==0x1F)
- parse_revkeys(sig);
- }
-
- if( list_mode ) {
- printf(":signature packet: algo %d, keyid %08lX%08lX\n"
- "\tversion %d, created %lu, md5len %d, sigclass %02x\n"
- "\tdigest algo %d, begin of digest %02x %02x\n",
- sig->pubkey_algo,
- (ulong)sig->keyid[0], (ulong)sig->keyid[1],
- sig->version, (ulong)sig->timestamp, md5_len, sig->sig_class,
- sig->digest_algo,
- sig->digest_start[0], sig->digest_start[1] );
- if( is_v4 ) {
- parse_sig_subpkt (sig->hashed, SIGSUBPKT_LIST_HASHED, NULL );
- parse_sig_subpkt (sig->unhashed, SIGSUBPKT_LIST_UNHASHED, NULL);
- }
- }
-
- ndata = pubkey_get_nsig(sig->pubkey_algo);
- if( !ndata ) {
- if( list_mode )
- printf("\tunknown algorithm %d\n", sig->pubkey_algo );
- unknown_pubkey_warning( sig->pubkey_algo );
- /* we store the plain material in data[0], so that we are able
- * to write it back with build_packet() */
- sig->data[0] = mpi_set_opaque(NULL, read_rest(inp, pktlen), pktlen );
- pktlen = 0;
- }
- else {
- for( i=0; i < ndata; i++ ) {
- n = pktlen;
- sig->data[i] = mpi_read(inp, &n, 0 );
- pktlen -=n;
- if( list_mode ) {
- printf("\tdata: ");
- mpi_print(stdout, sig->data[i], mpi_print_mode );
- putchar('\n');
- }
- if (!sig->data[i])
- rc = G10ERR_INVALID_PACKET;
- }
- }
-
- leave:
- skip_rest(inp, pktlen);
- return rc;
-}
-
-
-static int
-parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
- PKT_onepass_sig *ops )
-{
- int version;
- int rc = 0;
-
- if( pktlen < 13 ) {
- log_error("packet(%d) too short\n", pkttype);
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
- version = iobuf_get_noeof(inp); pktlen--;
- if( version != 3 ) {
- log_error("onepass_sig with unknown version %d\n", version);
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
- ops->sig_class = iobuf_get_noeof(inp); pktlen--;
- ops->digest_algo = iobuf_get_noeof(inp); pktlen--;
- ops->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
- ops->keyid[0] = read_32(inp); pktlen -= 4;
- ops->keyid[1] = read_32(inp); pktlen -= 4;
- ops->last = iobuf_get_noeof(inp); pktlen--;
- if( list_mode )
- printf(":onepass_sig packet: keyid %08lX%08lX\n"
- "\tversion %d, sigclass %02x, digest %d, pubkey %d, last=%d\n",
- (ulong)ops->keyid[0], (ulong)ops->keyid[1],
- version, ops->sig_class,
- ops->digest_algo, ops->pubkey_algo, ops->last );
-
-
- leave:
- skip_rest(inp, pktlen);
- return rc;
-}
-
-
-static MPI
-read_protected_v3_mpi (IOBUF inp, unsigned long *length)
-{
- int c;
- unsigned int nbits, nbytes;
- unsigned char *buf, *p;
- MPI val;
-
- if (*length < 2)
- {
- log_error ("mpi too small\n");
- return NULL;
- }
-
- if ((c=iobuf_get (inp)) == -1)
- return NULL;
- --*length;
- nbits = c << 8;
- if ((c=iobuf_get(inp)) == -1)
- return NULL;
- --*length;
- nbits |= c;
-
- if (nbits > 16384)
- {
- log_error ("mpi too large (%u bits)\n", nbits);
- return NULL;
- }
- nbytes = (nbits+7) / 8;
- buf = p = m_alloc (2 + nbytes);
- *p++ = nbits >> 8;
- *p++ = nbits;
- for (; nbytes && length; nbytes--, --*length)
- *p++ = iobuf_get (inp);
- if (nbytes)
- {
- log_error ("packet shorter tham mpi\n");
- m_free (buf);
- return NULL;
- }
-
- /* convert buffer into an opaque MPI */
- val = mpi_set_opaque (NULL, buf, p-buf);
- return val;
-}
-
-
-static int
-parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
- byte *hdr, int hdrlen, PACKET *pkt )
-{
- int i, version, algorithm;
- unsigned n;
- unsigned long timestamp, expiredate, max_expiredate;
- int npkey, nskey;
- int is_v4=0;
- int rc=0;
-
- version = iobuf_get_noeof(inp); pktlen--;
- if( pkttype == PKT_PUBLIC_SUBKEY && version == '#' ) {
- /* early versions of G10 use old PGP comments packets;
- * luckily all those comments are started by a hash */
- if( list_mode ) {
- printf(":rfc1991 comment packet: \"" );
- for( ; pktlen; pktlen-- ) {
- int c;
- c = iobuf_get_noeof(inp);
- if( c >= ' ' && c <= 'z' )
- putchar(c);
- else
- printf("\\x%02x", c );
- }
- printf("\"\n");
- }
- skip_rest(inp, pktlen);
- return 0;
- }
- else if( version == 4 )
- is_v4=1;
- else if( version != 2 && version != 3 ) {
- log_error("packet(%d) with unknown version %d\n", pkttype, version);
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
-
- if( pktlen < 11 ) {
- log_error("packet(%d) too short\n", pkttype);
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
-
- timestamp = read_32(inp); pktlen -= 4;
- if( is_v4 ) {
- expiredate = 0; /* have to get it from the selfsignature */
- max_expiredate = 0;
- }
- else {
- unsigned short ndays;
- ndays = read_16(inp); pktlen -= 2;
- if( ndays )
- expiredate = timestamp + ndays * 86400L;
- else
- expiredate = 0;
-
- max_expiredate=expiredate;
- }
- algorithm = iobuf_get_noeof(inp); pktlen--;
- if( list_mode )
- printf(":%s key packet:\n"
- "\tversion %d, algo %d, created %lu, expires %lu\n",
- pkttype == PKT_PUBLIC_KEY? "public" :
- pkttype == PKT_SECRET_KEY? "secret" :
- pkttype == PKT_PUBLIC_SUBKEY? "public sub" :
- pkttype == PKT_SECRET_SUBKEY? "secret sub" : "??",
- version, algorithm, timestamp, expiredate );
-
- if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) {
- PKT_secret_key *sk = pkt->pkt.secret_key;
-
- sk->timestamp = timestamp;
- sk->expiredate = expiredate;
- sk->max_expiredate = max_expiredate;
- sk->hdrbytes = hdrlen;
- sk->version = version;
- sk->is_primary = pkttype == PKT_SECRET_KEY;
- sk->pubkey_algo = algorithm;
- sk->req_usage = 0;
- sk->pubkey_usage = 0; /* not yet used */
- }
- else {
- PKT_public_key *pk = pkt->pkt.public_key;
-
- pk->timestamp = timestamp;
- pk->expiredate = expiredate;
- pk->max_expiredate = max_expiredate;
- pk->hdrbytes = hdrlen;
- pk->version = version;
- pk->is_primary = pkttype == PKT_PUBLIC_KEY;
- pk->pubkey_algo = algorithm;
- pk->req_usage = 0;
- pk->pubkey_usage = 0; /* not yet used */
- pk->is_revoked = 0;
- pk->keyid[0] = 0;
- pk->keyid[1] = 0;
- }
- nskey = pubkey_get_nskey( algorithm );
- npkey = pubkey_get_npkey( algorithm );
- if( !npkey ) {
- if( list_mode )
- printf("\tunknown algorithm %d\n", algorithm );
- unknown_pubkey_warning( algorithm );
- }
-
-
- if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) {
- PKT_secret_key *sk = pkt->pkt.secret_key;
- byte temp[16];
-
- if( !npkey ) {
- sk->skey[0] = mpi_set_opaque( NULL,
- read_rest(inp, pktlen), pktlen );
- pktlen = 0;
- goto leave;
- }
-
- for(i=0; i < npkey; i++ ) {
- n = pktlen; sk->skey[i] = mpi_read(inp, &n, 0 ); pktlen -=n;
- if( list_mode ) {
- printf( "\tskey[%d]: ", i);
- mpi_print(stdout, sk->skey[i], mpi_print_mode );
- putchar('\n');
- }
- if (!sk->skey[i])
- rc = G10ERR_INVALID_PACKET;
- }
- if (rc) /* one of the MPIs were bad */
- goto leave;
- sk->protect.algo = iobuf_get_noeof(inp); pktlen--;
- sk->protect.sha1chk = 0;
- if( sk->protect.algo ) {
- sk->is_protected = 1;
- sk->protect.s2k.count = 0;
- if( sk->protect.algo == 254 || sk->protect.algo == 255 ) {
- if( pktlen < 3 ) {
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
- sk->protect.sha1chk = (sk->protect.algo == 254);
- sk->protect.algo = iobuf_get_noeof(inp); pktlen--;
- /* Note that a sk->protect.algo > 110 is illegal, but
- I'm not erroring on it here as otherwise there
- would be no way to delete such a key. */
- sk->protect.s2k.mode = iobuf_get_noeof(inp); pktlen--;
- sk->protect.s2k.hash_algo = iobuf_get_noeof(inp); pktlen--;
- /* check for the special GNU extension */
- if( is_v4 && sk->protect.s2k.mode == 101 ) {
- for(i=0; i < 4 && pktlen; i++, pktlen-- )
- temp[i] = iobuf_get_noeof(inp);
- if( i < 4 || memcmp( temp, "GNU", 3 ) ) {
- if( list_mode )
- printf( "\tunknown S2K %d\n",
- sk->protect.s2k.mode );
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
- /* here we know that it is a gnu extension
- * What follows is the GNU protection mode:
- * All values have special meanings
- * and they are mapped in the mode with a base of 1000.
- */
- sk->protect.s2k.mode = 1000 + temp[3];
- }
- switch( sk->protect.s2k.mode ) {
- case 1:
- case 3:
- for(i=0; i < 8 && pktlen; i++, pktlen-- )
- temp[i] = iobuf_get_noeof(inp);
- memcpy(sk->protect.s2k.salt, temp, 8 );
- break;
- }
- switch( sk->protect.s2k.mode ) {
- case 0: if( list_mode ) printf( "\tsimple S2K" );
- break;
- case 1: if( list_mode ) printf( "\tsalted S2K" );
- break;
- case 3: if( list_mode ) printf( "\titer+salt S2K" );
- break;
- case 1001: if( list_mode ) printf( "\tgnu-dummy S2K" );
- break;
- default:
- if( list_mode )
- printf( "\tunknown %sS2K %d\n",
- sk->protect.s2k.mode < 1000? "":"GNU ",
- sk->protect.s2k.mode );
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
-
- if( list_mode ) {
- printf(", algo: %d,%s hash: %d",
- sk->protect.algo,
- sk->protect.sha1chk?" SHA1 protection,"
- :" simple checksum,",
- sk->protect.s2k.hash_algo );
- if( sk->protect.s2k.mode == 1
- || sk->protect.s2k.mode == 3 ) {
- printf(", salt: ");
- for(i=0; i < 8; i++ )
- printf("%02x", sk->protect.s2k.salt[i]);
- }
- putchar('\n');
- }
-
- if( sk->protect.s2k.mode == 3 ) {
- if( pktlen < 1 ) {
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
- sk->protect.s2k.count = iobuf_get(inp);
- pktlen--;
- if( list_mode )
- printf("\tprotect count: %lu\n",
- (ulong)sk->protect.s2k.count);
- }
- }
- /* Note that a sk->protect.algo > 110 is illegal, but I'm
- not erroring on it here as otherwise there would be no
- way to delete such a key. */
- else { /* old version; no S2K, so we set mode to 0, hash MD5 */
- sk->protect.s2k.mode = 0;
- sk->protect.s2k.hash_algo = DIGEST_ALGO_MD5;
- if( list_mode )
- printf( "\tprotect algo: %d (hash algo: %d)\n",
- sk->protect.algo, sk->protect.s2k.hash_algo );
- }
- /* It is really ugly that we don't know the size
- * of the IV here in cases we are not aware of the algorithm.
- * so a
- * sk->protect.ivlen = cipher_get_blocksize(sk->protect.algo);
- * won't work. The only solution I see is to hardwire it here.
- * NOTE: if you change the ivlen above 16, don't forget to
- * enlarge temp.
- */
- switch( sk->protect.algo ) {
- case 7: case 8: case 9: /* reserved for AES */
- case 10: /* Twofish */
- sk->protect.ivlen = 16;
- break;
- default:
- sk->protect.ivlen = 8;
- }
- if( sk->protect.s2k.mode == 1001 )
- sk->protect.ivlen = 0;
-
- if( pktlen < sk->protect.ivlen ) {
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
- for(i=0; i < sk->protect.ivlen && pktlen; i++, pktlen-- )
- temp[i] = iobuf_get_noeof(inp);
- if( list_mode ) {
- printf( "\tprotect IV: ");
- for(i=0; i < sk->protect.ivlen; i++ )
- printf(" %02x", temp[i] );
- putchar('\n');
- }
- memcpy(sk->protect.iv, temp, sk->protect.ivlen );
- }
- else
- sk->is_protected = 0;
- /* It does not make sense to read it into secure memory.
- * If the user is so careless, not to protect his secret key,
- * we can assume, that he operates an open system :=(.
- * So we put the key into secure memory when we unprotect it. */
- if( sk->protect.s2k.mode == 1001 ) {
- /* better set some dummy stuff here */
- sk->skey[npkey] = mpi_set_opaque(NULL, m_strdup("dummydata"), 10);
- pktlen = 0;
- }
- else if( is_v4 && sk->is_protected ) {
- /* ugly; the length is encrypted too, so we read all
- * stuff up to the end of the packet into the first
- * skey element */
- sk->skey[npkey] = mpi_set_opaque(NULL,
- read_rest(inp, pktlen), pktlen );
- pktlen = 0;
- if( list_mode ) {
- printf("\tencrypted stuff follows\n");
- }
- }
- else { /* v3 method: the mpi length is not encrypted */
- for(i=npkey; i < nskey; i++ ) {
- if ( sk->is_protected ) {
- sk->skey[i] = read_protected_v3_mpi (inp, &pktlen);
- if( list_mode )
- printf( "\tskey[%d]: [encrypted]\n", i);
- }
- else {
- n = pktlen;
- sk->skey[i] = mpi_read(inp, &n, 0 );
- pktlen -=n;
- if( list_mode ) {
- printf( "\tskey[%d]: ", i);
- mpi_print(stdout, sk->skey[i], mpi_print_mode );
- putchar('\n');
- }
- }
-
- if (!sk->skey[i])
- rc = G10ERR_INVALID_PACKET;
- }
- if (rc)
- goto leave;
-
- sk->csum = read_16(inp); pktlen -= 2;
- if( list_mode ) {
- printf("\tchecksum: %04hx\n", sk->csum);
- }
- }
- }
- else {
- PKT_public_key *pk = pkt->pkt.public_key;
-
- if( !npkey ) {
- pk->pkey[0] = mpi_set_opaque( NULL,
- read_rest(inp, pktlen), pktlen );
- pktlen = 0;
- goto leave;
- }
-
- for(i=0; i < npkey; i++ ) {
- n = pktlen; pk->pkey[i] = mpi_read(inp, &n, 0 ); pktlen -=n;
- if( list_mode ) {
- printf( "\tpkey[%d]: ", i);
- mpi_print(stdout, pk->pkey[i], mpi_print_mode );
- putchar('\n');
- }
- if (!pk->pkey[i])
- rc = G10ERR_INVALID_PACKET;
- }
- if (rc)
- goto leave;
- }
-
- leave:
- skip_rest(inp, pktlen);
- return rc;
-}
-
-/* Attribute subpackets have the same format as v4 signature
- subpackets. This is not part of OpenPGP, but is done in several
- versions of PGP nevertheless. */
-int
-parse_attribute_subpkts(PKT_user_id *uid)
-{
- size_t n;
- int count=0;
- struct user_attribute *attribs=NULL;
- const byte *buffer=uid->attrib_data;
- int buflen=uid->attrib_len;
- byte type;
-
- m_free(uid->attribs);
-
- while(buflen)
- {
- n = *buffer++; buflen--;
- if( n == 255 ) { /* 4 byte length header */
- if( buflen < 4 )
- goto too_short;
- n = (buffer[0] << 24) | (buffer[1] << 16)
- | (buffer[2] << 8) | buffer[3];
- buffer += 4;
- buflen -= 4;
- }
- else if( n >= 192 ) { /* 2 byte special encoded length header */
- if( buflen < 2 )
- goto too_short;
- n = (( n - 192 ) << 8) + *buffer + 192;
- buffer++;
- buflen--;
- }
- if( buflen < n )
- goto too_short;
-
- attribs=m_realloc(attribs,(count+1)*sizeof(struct user_attribute));
- memset(&attribs[count],0,sizeof(struct user_attribute));
-
- type=*buffer;
- buffer++;
- buflen--;
- n--;
-
- attribs[count].type=type;
- attribs[count].data=buffer;
- attribs[count].len=n;
- buffer+=n;
- buflen-=n;
- count++;
- }
-
- uid->attribs=attribs;
- uid->numattribs=count;
- return count;
-
- too_short:
- log_error("buffer shorter than attribute subpacket\n");
- uid->attribs=attribs;
- uid->numattribs=count;
- return count;
-}
-
-static void setup_user_id(PACKET *packet)
-{
- packet->pkt.user_id->ref = 1;
- packet->pkt.user_id->attribs = NULL;
- packet->pkt.user_id->attrib_data = NULL;
- packet->pkt.user_id->attrib_len = 0;
- packet->pkt.user_id->is_primary = 0;
- packet->pkt.user_id->is_revoked = 0;
- packet->pkt.user_id->is_expired = 0;
- packet->pkt.user_id->expiredate = 0;
- packet->pkt.user_id->created = 0;
- packet->pkt.user_id->help_key_usage = 0;
- packet->pkt.user_id->help_key_expire = 0;
- packet->pkt.user_id->prefs = NULL;
-}
-
-static int
-parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
-{
- byte *p;
-
- packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id + pktlen);
- packet->pkt.user_id->len = pktlen;
-
- setup_user_id(packet);
-
- p = packet->pkt.user_id->name;
- for( ; pktlen; pktlen--, p++ )
- *p = iobuf_get_noeof(inp);
- *p = 0;
-
- if( list_mode ) {
- int n = packet->pkt.user_id->len;
- printf(":user ID packet: \"");
- /* fixme: Hey why don't we replace this with print_string?? */
- for(p=packet->pkt.user_id->name; n; p++, n-- ) {
- if( *p >= ' ' && *p <= 'z' )
- putchar(*p);
- else
- printf("\\x%02x", *p );
- }
- printf("\"\n");
- }
- return 0;
-}
-
-
-void
-make_attribute_uidname(PKT_user_id *uid, size_t max_namelen)
-{
- assert ( max_namelen > 70 );
- if(uid->numattribs<=0)
- sprintf(uid->name,"[bad attribute packet of size %lu]",uid->attrib_len);
- else if(uid->numattribs>1)
- sprintf(uid->name,"[%d attributes of size %lu]",
- uid->numattribs,uid->attrib_len);
- else
- {
- /* Only one attribute, so list it as the "user id" */
-
- if(uid->attribs->type==ATTRIB_IMAGE)
- {
- u32 len;
- byte type;
-
- if(parse_image_header(uid->attribs,&type,&len))
- sprintf(uid->name,"[%.20s image of size %lu]",
- image_type_to_string(type,1),(ulong)len);
- else
- sprintf(uid->name,"[invalid image]");
- }
- else
- sprintf(uid->name,"[unknown attribute of size %lu]",
- (ulong)uid->attribs->len);
- }
-
- uid->len = strlen(uid->name);
-}
-
-static int
-parse_attribute( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
-{
- byte *p;
-
-#define EXTRA_UID_NAME_SPACE 71
- packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id
- + EXTRA_UID_NAME_SPACE);
-
- setup_user_id(packet);
-
- packet->pkt.user_id->attrib_data = m_alloc(pktlen);
- packet->pkt.user_id->attrib_len = pktlen;
- p = packet->pkt.user_id->attrib_data;
- for( ; pktlen; pktlen--, p++ )
- *p = iobuf_get_noeof(inp);
-
- /* Now parse out the individual attribute subpackets. This is
- somewhat pointless since there is only one currently defined
- attribute type (jpeg), but it is correct by the spec. */
- parse_attribute_subpkts(packet->pkt.user_id);
-
- make_attribute_uidname(packet->pkt.user_id, EXTRA_UID_NAME_SPACE);
-
- if( list_mode ) {
- printf(":attribute packet: %s\n", packet->pkt.user_id->name );
- }
- return 0;
-}
-
-
-static int
-parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
-{
- byte *p;
-
- packet->pkt.comment = m_alloc(sizeof *packet->pkt.comment + pktlen - 1);
- packet->pkt.comment->len = pktlen;
- p = packet->pkt.comment->data;
- for( ; pktlen; pktlen--, p++ )
- *p = iobuf_get_noeof(inp);
-
- if( list_mode ) {
- int n = packet->pkt.comment->len;
- printf(":%scomment packet: \"", pkttype == PKT_OLD_COMMENT?
- "OpenPGP draft " : "" );
- for(p=packet->pkt.comment->data; n; p++, n-- ) {
- if( *p >= ' ' && *p <= 'z' )
- putchar(*p);
- else
- printf("\\x%02x", *p );
- }
- printf("\"\n");
- }
- return 0;
-}
-
-
-static void
-parse_trust( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
-{
- int c;
-
- if (pktlen)
- {
- c = iobuf_get_noeof(inp);
- pktlen--;
- pkt->pkt.ring_trust = m_alloc( sizeof *pkt->pkt.ring_trust );
- pkt->pkt.ring_trust->trustval = c;
- pkt->pkt.ring_trust->sigcache = 0;
- if (!c && pktlen==1)
- {
- c = iobuf_get_noeof (inp);
- pktlen--;
- /* we require that bit 7 of the sigcache is 0 (easier eof handling)*/
- if ( !(c & 0x80) )
- pkt->pkt.ring_trust->sigcache = c;
- }
- if( list_mode )
- printf(":trust packet: flag=%02x sigcache=%02x\n",
- pkt->pkt.ring_trust->trustval,
- pkt->pkt.ring_trust->sigcache);
- }
- else
- {
- if( list_mode )
- printf(":trust packet: empty\n");
- }
- skip_rest (inp, pktlen);
-}
-
-
-static int
-parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
- PACKET *pkt, int new_ctb )
-{
- int rc = 0;
- int mode, namelen, partial=0;
- PKT_plaintext *pt;
- byte *p;
- int c, i;
-
- if( pktlen && pktlen < 6 ) {
- log_error("packet(%d) too short (%lu)\n", pkttype, (ulong)pktlen);
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
- /* A packet length of zero indicates partial body length. A zero
- data length isn't a zero length packet due to the header (mode,
- name, etc), so this is accurate. */
- if(pktlen==0)
- partial=1;
- mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
- namelen = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
- pt = pkt->pkt.plaintext = m_alloc(sizeof *pkt->pkt.plaintext + namelen -1);
- pt->new_ctb = new_ctb;
- pt->mode = mode;
- pt->namelen = namelen;
- pt->is_partial = partial;
- if( pktlen ) {
- for( i=0; pktlen > 4 && i < namelen; pktlen--, i++ )
- pt->name[i] = iobuf_get_noeof(inp);
- }
- else {
- for( i=0; i < namelen; i++ )
- if( (c=iobuf_get(inp)) == -1 )
- break;
- else
- pt->name[i] = c;
- }
- pt->timestamp = read_32(inp); if( pktlen) pktlen -= 4;
- pt->len = pktlen;
- pt->buf = inp;
- pktlen = 0;
-
- if( list_mode ) {
- printf(":literal data packet:\n"
- "\tmode %c, created %lu, name=\"",
- mode >= ' ' && mode <'z'? mode : '?',
- (ulong)pt->timestamp );
- for(p=pt->name,i=0; i < namelen; p++, i++ ) {
- if( *p >= ' ' && *p <= 'z' )
- putchar(*p);
- else
- printf("\\x%02x", *p );
- }
- printf("\",\n\traw data: %lu bytes\n", (ulong)pt->len );
- }
-
- leave:
- return rc;
-}
-
-
-static int
-parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
- PACKET *pkt, int new_ctb )
-{
- PKT_compressed *zd;
-
- /* pktlen is here 0, but data follows
- * (this should be the last object in a file or
- * the compress algorithm should know the length)
- */
- zd = pkt->pkt.compressed = m_alloc(sizeof *pkt->pkt.compressed );
- zd->algorithm = iobuf_get_noeof(inp);
- zd->len = 0; /* not used */
- zd->new_ctb = new_ctb;
- zd->buf = inp;
- if( list_mode )
- printf(":compressed packet: algo=%d\n", zd->algorithm);
- return 0;
-}
-
-
-static int
-parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
- PACKET *pkt, int new_ctb )
-{
- int rc = 0;
- PKT_encrypted *ed;
- unsigned long orig_pktlen = pktlen;
-
- ed = pkt->pkt.encrypted = m_alloc(sizeof *pkt->pkt.encrypted );
- ed->len = pktlen;
- /* we don't know the extralen which is (cipher_blocksize+2)
- because the algorithm ist not specified in this packet.
- However, it is only important to know this for some sanity
- checks on the packet length - it doesn't matter that we can't
- do it */
- ed->extralen = 0;
- ed->buf = NULL;
- ed->new_ctb = new_ctb;
- ed->mdc_method = 0;
- if( pkttype == PKT_ENCRYPTED_MDC ) {
- /* fixme: add some pktlen sanity checks */
- int version;
-
- version = iobuf_get_noeof(inp);
- if (orig_pktlen)
- pktlen--;
- if( version != 1 ) {
- log_error("encrypted_mdc packet with unknown version %d\n",
- version);
- /*skip_rest(inp, pktlen); should we really do this? */
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
- ed->mdc_method = DIGEST_ALGO_SHA1;
- }
- if( orig_pktlen && pktlen < 10 ) { /* actually this is blocksize+2 */
- log_error("packet(%d) too short\n", pkttype);
- rc = G10ERR_INVALID_PACKET;
- skip_rest(inp, pktlen);
- goto leave;
- }
- if( list_mode ) {
- if( orig_pktlen )
- printf(":encrypted data packet:\n\tlength: %lu\n", orig_pktlen);
- else
- printf(":encrypted data packet:\n\tlength: unknown\n");
- if( ed->mdc_method )
- printf("\tmdc_method: %d\n", ed->mdc_method );
- }
-
- ed->buf = inp;
- pktlen = 0;
-
- leave:
- return rc;
-}
-
-
-static int
-parse_mdc( IOBUF inp, int pkttype, unsigned long pktlen,
- PACKET *pkt, int new_ctb )
-{
- int rc = 0;
- PKT_mdc *mdc;
- byte *p;
-
- mdc = pkt->pkt.mdc= m_alloc(sizeof *pkt->pkt.mdc );
- if( list_mode )
- printf(":mdc packet: length=%lu\n", pktlen);
- if( !new_ctb || pktlen != 20 ) {
- log_error("mdc_packet with invalid encoding\n");
- rc = G10ERR_INVALID_PACKET;
- goto leave;
- }
- p = mdc->hash;
- for( ; pktlen; pktlen--, p++ )
- *p = iobuf_get_noeof(inp);
-
- leave:
- return rc;
-}
-
-
-/*
- * This packet is internally generated by PGG (by armor.c) to
- * transfer some information to the lower layer. To make sure that
- * this packet is really a GPG faked one and not one comming from outside,
- * we first check that tehre is a unique tag in it.
- * The format of such a control packet is:
- * n byte session marker
- * 1 byte control type CTRLPKT_xxxxx
- * m byte control data
- */
-
-static int
-parse_gpg_control( IOBUF inp,
- int pkttype, unsigned long pktlen, PACKET *packet )
-{
- byte *p;
- const byte *sesmark;
- size_t sesmarklen;
- int i;
-
- if ( list_mode )
- printf(":packet 63: length %lu ", pktlen);
-
- sesmark = get_session_marker ( &sesmarklen );
- if ( pktlen < sesmarklen+1 ) /* 1 is for the control bytes */
- goto skipit;
- for( i=0; i < sesmarklen; i++, pktlen-- ) {
- if ( sesmark[i] != iobuf_get_noeof(inp) )
- goto skipit;
- }
- if ( list_mode )
- puts ("- gpg control packet");
-
- packet->pkt.gpg_control = m_alloc(sizeof *packet->pkt.gpg_control
- + pktlen - 1);
- packet->pkt.gpg_control->control = iobuf_get_noeof(inp); pktlen--;
- packet->pkt.gpg_control->datalen = pktlen;
- p = packet->pkt.gpg_control->data;
- for( ; pktlen; pktlen--, p++ )
- *p = iobuf_get_noeof(inp);
-
- return 0;
-
- skipit:
- if ( list_mode ) {
- int c;
-
- i=0;
- printf("- private (rest length %lu)\n", pktlen);
- if( iobuf_in_block_mode(inp) ) {
- while( (c=iobuf_get(inp)) != -1 )
- dump_hex_line(c, &i);
- }
- else {
- for( ; pktlen; pktlen-- )
- dump_hex_line(iobuf_get(inp), &i);
- }
- putchar('\n');
- }
- skip_rest(inp,pktlen);
- return G10ERR_INVALID_PACKET;
-}
-
-/* create a gpg control packet to be used internally as a placeholder */
-PACKET *
-create_gpg_control( ctrlpkttype_t type, const byte *data, size_t datalen )
-{
- PACKET *packet;
- byte *p;
-
- packet = m_alloc( sizeof *packet );
- init_packet(packet);
- packet->pkttype = PKT_GPG_CONTROL;
- packet->pkt.gpg_control = m_alloc(sizeof *packet->pkt.gpg_control
- + datalen - 1);
- packet->pkt.gpg_control->control = type;
- packet->pkt.gpg_control->datalen = datalen;
- p = packet->pkt.gpg_control->data;
- for( ; datalen; datalen--, p++ )
- *p = *data++;
-
- return packet;
-}