1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-06-09 23:39:51 +02:00

partly added creation of OP partial length headers

This commit is contained in:
Werner Koch 1998-07-02 19:31:46 +00:00
parent 77a6af76d0
commit 97090f1293
17 changed files with 432 additions and 157 deletions

3
TODO
View File

@ -1,4 +1,7 @@
* add writing of partial headers conforming to OpenPGP
util/iobuf.c:block_filter
* add options: --default-signature-user, --default-encryption-user * add options: --default-signature-user, --default-encryption-user
* make preferences work * make preferences work

View File

@ -1,3 +1,7 @@
Thu Jul 2 10:50:30 1998 Werner Koch (wk@isil.d.shuttle.de)
* cipher.c (cipher_open): algos >=100 use standard CFB
Thu Jun 25 11:18:25 1998 Werner Koch (wk@isil.d.shuttle.de) Thu Jun 25 11:18:25 1998 Werner Koch (wk@isil.d.shuttle.de)
* Makefile.am: Support for extensions * Makefile.am: Support for extensions

View File

@ -305,10 +305,10 @@ cipher_open( int algo, int mode, int secure )
if( algo == CIPHER_ALGO_DUMMY ) if( algo == CIPHER_ALGO_DUMMY )
hd->mode = CIPHER_MODE_DUMMY; hd->mode = CIPHER_MODE_DUMMY;
else if( mode == CIPHER_MODE_AUTO_CFB ) { else if( mode == CIPHER_MODE_AUTO_CFB ) {
if( algo != CIPHER_ALGO_BLOWFISH160 ) if( algo == CIPHER_ALGO_BLOWFISH160 || algo >= 100 )
hd->mode = CIPHER_MODE_PHILS_CFB;
else
hd->mode = CIPHER_MODE_CFB; hd->mode = CIPHER_MODE_CFB;
else
hd->mode = CIPHER_MODE_PHILS_CFB;
} }
else else
hd->mode = mode; hd->mode = mode;

View File

@ -1,3 +1,20 @@
Thu Jul 2 21:01:25 1998 Werner Koch (wk@isil.d.shuttle.de)
* parse-packet.c: Now is able sto store data of unknown
algorithms.
* free-packet.c: Support for this.
* build-packet.c: Can write data of packet with unknown algos.
Thu Jul 2 11:46:36 1998 Werner Koch (wk@isil.d.shuttle.de)
* parse-packet.c (parse): fixed 4 byte length header
Wed Jul 1 12:36:55 1998 Werner Koch (wk@isil.d.shuttle.de)
* packet.h (new_ctb): New field for some packets
* build-packet.c (build_packet): Support for new_ctb
* parse-packet.c (parse): Ditto.
Mon Jun 29 12:54:45 1998 Werner Koch (wk@isil.d.shuttle.de) Mon Jun 29 12:54:45 1998 Werner Koch (wk@isil.d.shuttle.de)
* packet.h: changed all "_cert" to "_key", "subcert" to "subkey". * packet.h: changed all "_cert" to "_key", "subcert" to "subkey".

View File

@ -87,8 +87,9 @@ static char *head_strings[] = {
"BEGIN PGP PUBLIC KEY BLOCK", "BEGIN PGP PUBLIC KEY BLOCK",
"BEGIN PGP SIGNATURE", "BEGIN PGP SIGNATURE",
"BEGIN PGP SIGNED MESSAGE", "BEGIN PGP SIGNED MESSAGE",
"BEGIN PGP ARMORED FILE", "BEGIN PGP ARMORED FILE", /* gnupg extension */
"BEGIN PGP SECRET KEY BLOCK", "BEGIN PGP PRIVATE KEY BLOCK",
"BEGIN PGP SECRET KEY BLOCK", /* only used by pgp2 */
NULL NULL
}; };
static char *tail_strings[] = { static char *tail_strings[] = {
@ -97,6 +98,7 @@ static char *tail_strings[] = {
"END PGP SIGNATURE", "END PGP SIGNATURE",
"END dummy", "END dummy",
"END PGP ARMORED FILE", "END PGP ARMORED FILE",
"END PGP PRIVATE KEY BLOCK",
"END PGP SECRET KEY BLOCK", "END PGP SECRET KEY BLOCK",
NULL NULL
}; };

View File

@ -64,14 +64,21 @@ static int write_version( IOBUF out, int ctb );
int int
build_packet( IOBUF out, PACKET *pkt ) build_packet( IOBUF out, PACKET *pkt )
{ {
int rc=0, ctb; int new_ctb=0, rc=0, ctb;
if( DBG_PACKET ) if( DBG_PACKET )
log_debug("build_packet() type=%d\n", pkt->pkttype ); log_debug("build_packet() type=%d\n", pkt->pkttype );
if( pkt->pkttype == PKT_OLD_COMMENT )
pkt->pkttype = PKT_COMMENT;
assert( pkt->pkt.generic ); assert( pkt->pkt.generic );
if( pkt->pkttype > 15 ) /* new format */
switch( pkt->pkttype ) {
case PKT_OLD_COMMENT: pkt->pkttype = PKT_COMMENT; break;
case PKT_PLAINTEXT: new_ctb = pkt->pkt.plaintext->new_ctb; break;
case PKT_ENCRYPTED: new_ctb = pkt->pkt.encrypted->new_ctb; break;
case PKT_COMPRESSED:new_ctb = pkt->pkt.compressed->new_ctb; break;
default: break;
}
if( new_ctb || pkt->pkttype > 15 ) /* new format */
ctb = 0xc0 | (pkt->pkttype & 0x3f); ctb = 0xc0 | (pkt->pkttype & 0x3f);
else else
ctb = 0x80 | ((pkt->pkttype & 15)<<2); ctb = 0x80 | ((pkt->pkttype & 15)<<2);
@ -152,6 +159,19 @@ calc_packet_length( PACKET *pkt )
return n; return n;
} }
static void
write_fake_data( IOBUF out, MPI a )
{
byte *s;
u16 len;
if( a ) {
s = (byte*)a;
len = (s[0] << 8) | s[1];
iobuf_write( out, s+2, len );
}
}
static int static int
do_comment( IOBUF out, int ctb, PKT_comment *rem ) do_comment( IOBUF out, int ctb, PKT_comment *rem )
@ -189,6 +209,8 @@ do_public_key( IOBUF out, int ctb, PKT_public_key *pk )
write_16(a, pk->valid_days ); write_16(a, pk->valid_days );
iobuf_put(a, pk->pubkey_algo ); iobuf_put(a, pk->pubkey_algo );
n = pubkey_get_npkey( pk->pubkey_algo ); n = pubkey_get_npkey( pk->pubkey_algo );
if( !n )
write_fake_data( a, pk->pkey[0] );
for(i=0; i < n; i++ ) for(i=0; i < n; i++ )
mpi_write(a, pk->pkey[i] ); mpi_write(a, pk->pkey[i] );
@ -259,6 +281,10 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
iobuf_put(a, sk->pubkey_algo ); iobuf_put(a, sk->pubkey_algo );
nskey = pubkey_get_nskey( sk->pubkey_algo ); nskey = pubkey_get_nskey( sk->pubkey_algo );
npkey = pubkey_get_npkey( sk->pubkey_algo ); npkey = pubkey_get_npkey( sk->pubkey_algo );
if( npkey ) {
write_fake_data( a, sk->skey[0] );
goto leave;
}
assert( npkey < nskey ); assert( npkey < nskey );
for(i=0; i < npkey; i++ ) for(i=0; i < npkey; i++ )
@ -287,6 +313,7 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
mpi_write(a, sk->skey[i] ); mpi_write(a, sk->skey[i] );
write_16(a, sk->csum ); write_16(a, sk->csum );
leave:
write_header2(out, ctb, iobuf_get_temp_length(a), sk->hdrbytes, 1 ); write_header2(out, ctb, iobuf_get_temp_length(a), sk->hdrbytes, 1 );
if( iobuf_write_temp( out, a ) ) if( iobuf_write_temp( out, a ) )
rc = G10ERR_WRITE_FILE; rc = G10ERR_WRITE_FILE;
@ -326,6 +353,9 @@ do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc )
return rc; return rc;
} }
static int static int
do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ) do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc )
{ {
@ -338,6 +368,8 @@ do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc )
write_32(a, enc->keyid[1] ); write_32(a, enc->keyid[1] );
iobuf_put(a,enc->pubkey_algo ); iobuf_put(a,enc->pubkey_algo );
n = pubkey_get_nenc( enc->pubkey_algo ); n = pubkey_get_nenc( enc->pubkey_algo );
if( !n )
write_fake_data( a, enc->data[0] );
for(i=0; i < n; i++ ) for(i=0; i < n; i++ )
mpi_write(a, enc->data[i] ); mpi_write(a, enc->data[i] );
@ -632,6 +664,8 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig )
iobuf_put(a, sig->digest_start[0] ); iobuf_put(a, sig->digest_start[0] );
iobuf_put(a, sig->digest_start[1] ); iobuf_put(a, sig->digest_start[1] );
n = pubkey_get_nsig( sig->pubkey_algo ); n = pubkey_get_nsig( sig->pubkey_algo );
if( !n )
write_fake_data( a, sig->data[0] );
for(i=0; i < n; i++ ) for(i=0; i < n; i++ )
mpi_write(a, sig->data[i] ); mpi_write(a, sig->data[i] );
@ -772,7 +806,7 @@ write_new_header( IOBUF out, int ctb, u32 len, int hdrlen )
if( iobuf_put(out, ctb ) ) if( iobuf_put(out, ctb ) )
return -1; return -1;
if( !len ) { if( !len ) {
log_bug("can't write partial headers yet\n"); iobuf_set_partial_block_mode(out, 512 );
} }
else { else {
if( len < 192 ) { if( len < 192 ) {

View File

@ -34,6 +34,34 @@
#include "options.h" #include "options.h"
#define MIN_PARTIAL_SIZE 512
static void
write_header( cipher_filter_context_t *cfx, IOBUF a )
{
PACKET pkt;
PKT_encrypted ed;
byte temp[10];
memset( &ed, 0, sizeof ed );
ed.len = cfx->datalen;
init_packet( &pkt );
pkt.pkttype = PKT_ENCRYPTED;
pkt.pkt.encrypted = &ed;
if( build_packet( a, &pkt ))
log_bug("build_packet(ENCR_DATA) failed\n");
randomize_buffer( temp, 8, 1 );
temp[8] = temp[6];
temp[9] = temp[7];
cfx->cipher_hd = cipher_open( cfx->dek->algo, CIPHER_MODE_AUTO_CFB, 1 );
cipher_setkey( cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen );
cipher_setiv( cfx->cipher_hd, NULL );
cipher_encrypt( cfx->cipher_hd, temp, temp, 10);
cipher_sync( cfx->cipher_hd );
iobuf_write(a, temp, 10);
cfx->header=1;
}
/**************** /****************
@ -53,35 +81,20 @@ cipher_filter( void *opaque, int control,
else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */ else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
assert(a); assert(a);
if( !cfx->header ) { if( !cfx->header ) {
PACKET pkt; write_header( cfx, a );
PKT_encrypted ed;
byte temp[10];
memset( &ed, 0, sizeof ed );
ed.len = cfx->datalen;
init_packet( &pkt );
pkt.pkttype = PKT_ENCRYPTED;
pkt.pkt.encrypted = &ed;
if( build_packet( a, &pkt ))
log_bug("build_packet(ENCR_DATA) failed\n");
randomize_buffer( temp, 8, 1 );
temp[8] = temp[6];
temp[9] = temp[7];
cfx->cipher_hd = cipher_open( cfx->dek->algo,
CIPHER_MODE_AUTO_CFB, 1 );
cipher_setkey( cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen );
cipher_setiv( cfx->cipher_hd, NULL );
cipher_encrypt( cfx->cipher_hd, temp, temp, 10);
cipher_sync( cfx->cipher_hd );
iobuf_write(a, temp, 10);
cfx->header=1;
} }
cipher_encrypt( cfx->cipher_hd, buf, buf, size); cipher_encrypt( cfx->cipher_hd, buf, buf, size);
if( iobuf_write( a, buf, size ) ) if( iobuf_write( a, buf, size ) )
rc = G10ERR_WRITE_FILE; rc = G10ERR_WRITE_FILE;
} }
else if( control == IOBUFCTRL_FREE ) { else if( control == IOBUFCTRL_FREE ) {
#if 0
if( cfx->new_partial && cfx->cfx->la_buffer ) {
}
#endif
cipher_close(cfx->cipher_hd); cipher_close(cfx->cipher_hd);
m_free(cfx->la_buffer); cfx->la_buffer = NULL;
} }
else if( control == IOBUFCTRL_DESC ) { else if( control == IOBUFCTRL_DESC ) {
*(char**)buf = "cipher_filter"; *(char**)buf = "cipher_filter";

View File

@ -61,6 +61,9 @@ typedef struct {
typedef struct { typedef struct {
DEK *dek; DEK *dek;
u32 datalen; u32 datalen;
int new_partial; /* use Openpgp partial packets header */
char *la_buffer; /* help buffer for OP partial stuff */
size_t la_buflen; /* and its used length */
CIPHER_HANDLE cipher_hd; CIPHER_HANDLE cipher_hd;
int header; int header;
} cipher_filter_context_t; } cipher_filter_context_t;

View File

@ -42,6 +42,10 @@ free_pubkey_enc( PKT_pubkey_enc *enc )
{ {
int n, i; int n, i;
n = pubkey_get_nenc( enc->pubkey_algo ); n = pubkey_get_nenc( enc->pubkey_algo );
if( !n ) {
m_free(enc->data[0]);
enc->data[0] = NULL;
}
for(i=0; i < n; i++ ) for(i=0; i < n; i++ )
mpi_free( enc->data[i] ); mpi_free( enc->data[i] );
m_free(enc); m_free(enc);
@ -52,6 +56,10 @@ free_seckey_enc( PKT_signature *sig )
{ {
int n, i; int n, i;
n = pubkey_get_nenc( sig->pubkey_algo ); n = pubkey_get_nenc( sig->pubkey_algo );
if( !n ) {
m_free(sig->data[0]);
sig->data[0] = NULL;
}
for(i=0; i < n; i++ ) for(i=0; i < n; i++ )
mpi_free( sig->data[i] ); mpi_free( sig->data[i] );
m_free(sig->hashed_data); m_free(sig->hashed_data);
@ -66,6 +74,10 @@ release_public_key_parts( PKT_public_key *pk )
{ {
int n, i; int n, i;
n = pubkey_get_npkey( pk->pubkey_algo ); n = pubkey_get_npkey( pk->pubkey_algo );
if( !n ) {
m_free(pk->pkey[0]);
pk->pkey[0] = NULL;
}
for(i=0; i < n; i++ ) { for(i=0; i < n; i++ ) {
mpi_free( pk->pkey[i] ); mpi_free( pk->pkey[i] );
pk->pkey[i] = NULL; pk->pkey[i] = NULL;
@ -80,6 +92,22 @@ free_public_key( PKT_public_key *pk )
m_free(pk); m_free(pk);
} }
static void *
cp_fake_data( MPI a )
{
byte *d, *s;
u16 len;
if( !a )
return NULL;
s = (byte*)a;
len = (s[0] << 8) | s[1];
d = m_alloc( len+2 );
memcpy(d, s, len+2);
return d;
}
PKT_public_key * PKT_public_key *
copy_public_key( PKT_public_key *d, PKT_public_key *s ) copy_public_key( PKT_public_key *d, PKT_public_key *s )
{ {
@ -89,8 +117,12 @@ copy_public_key( PKT_public_key *d, PKT_public_key *s )
d = m_alloc(sizeof *d); d = m_alloc(sizeof *d);
memcpy( d, s, sizeof *d ); memcpy( d, s, sizeof *d );
n = pubkey_get_npkey( s->pubkey_algo ); n = pubkey_get_npkey( s->pubkey_algo );
for(i=0; i < n; i++ ) if( !n )
d->pkey[i] = mpi_copy( s->pkey[i] ); d->pkey[0] = cp_fake_data(s->pkey[0]);
else {
for(i=0; i < n; i++ )
d->pkey[i] = mpi_copy( s->pkey[i] );
}
return d; return d;
} }
@ -100,6 +132,10 @@ release_secret_key_parts( PKT_secret_key *sk )
int n, i; int n, i;
n = pubkey_get_nskey( sk->pubkey_algo ); n = pubkey_get_nskey( sk->pubkey_algo );
if( !n ) {
m_free(sk->skey[0]);
sk->skey[0] = NULL;
}
for(i=0; i < n; i++ ) { for(i=0; i < n; i++ ) {
mpi_free( sk->skey[i] ); mpi_free( sk->skey[i] );
sk->skey[i] = NULL; sk->skey[i] = NULL;
@ -122,8 +158,12 @@ copy_secret_key( PKT_secret_key *d, PKT_secret_key *s )
d = m_alloc(sizeof *d); d = m_alloc(sizeof *d);
memcpy( d, s, sizeof *d ); memcpy( d, s, sizeof *d );
n = pubkey_get_nskey( s->pubkey_algo ); n = pubkey_get_nskey( s->pubkey_algo );
for(i=0; i < n; i++ ) if( !n )
d->skey[i] = mpi_copy( s->skey[i] ); d->skey[0] = cp_fake_data(s->skey[0]);
else {
for(i=0; i < n; i++ )
d->skey[i] = mpi_copy( s->skey[i] );
}
return d; return d;
} }
@ -254,6 +294,8 @@ cmp_public_keys( PKT_public_key *a, PKT_public_key *b )
return -1; return -1;
n = pubkey_get_npkey( b->pubkey_algo ); n = pubkey_get_npkey( b->pubkey_algo );
if( !n )
return -1; /* can't compare due to unknown algorithm */
for(i=0; i < n; i++ ) { for(i=0; i < n; i++ ) {
if( mpi_cmp( a->pkey[i], b->pkey[i] ) ) if( mpi_cmp( a->pkey[i], b->pkey[i] ) )
return -1; return -1;
@ -278,6 +320,8 @@ cmp_public_secret_key( PKT_public_key *pk, PKT_secret_key *sk )
return -1; return -1;
n = pubkey_get_npkey( pk->pubkey_algo ); n = pubkey_get_npkey( pk->pubkey_algo );
if( !n )
return -1; /* can't compare due to unknown algorithm */
for(i=0; i < n; i++ ) { for(i=0; i < n; i++ ) {
if( mpi_cmp( pk->pkey[i] , sk->skey[i] ) ) if( mpi_cmp( pk->pkey[i] , sk->skey[i] ) )
return -1; return -1;

View File

@ -159,9 +159,7 @@ read_block( IOBUF a, compress_filter_context_t *cfx,
init_packet(pkt); init_packet(pkt);
while( (rc=parse_packet(a, pkt)) != -1 ) { while( (rc=parse_packet(a, pkt)) != -1 ) {
if( rc ) { /* ignore errors */ if( rc ) { /* ignore errors */
if( rc == G10ERR_PUBKEY_ALGO ) if( rc != G10ERR_UNKNOWN_PACKET ) {
parse_pubkey_warning( pkt );
else if( rc != G10ERR_UNKNOWN_PACKET ) {
log_error("read_block: read error: %s\n", g10_errstr(rc) ); log_error("read_block: read error: %s\n", g10_errstr(rc) );
rc = G10ERR_INV_KEYRING; rc = G10ERR_INV_KEYRING;
goto ready; goto ready;

View File

@ -130,7 +130,8 @@ keyid_from_sk( PKT_secret_key *sk, u32 *keyid )
keyid = dummy_keyid; keyid = dummy_keyid;
if( sk->version < 4 && is_RSA(sk->pubkey_algo) ) { if( sk->version < 4 && is_RSA(sk->pubkey_algo) ) {
lowbits = mpi_get_keyid( sk->skey[0], keyid ); /* take n */ lowbits = pubkey_get_npkey(sk->pubkey_algo) ?
mpi_get_keyid( sk->skey[0], keyid ) : 0; /* take n */
} }
else { else {
const byte *dp; const byte *dp;
@ -161,7 +162,8 @@ keyid_from_pk( PKT_public_key *pk, u32 *keyid )
keyid = dummy_keyid; keyid = dummy_keyid;
if( pk->version < 4 && is_RSA(pk->pubkey_algo) ) { if( pk->version < 4 && is_RSA(pk->pubkey_algo) ) {
lowbits = mpi_get_keyid( pk->pkey[0], keyid ); /* from n */ lowbits = pubkey_get_npkey(pk->pubkey_algo) ?
mpi_get_keyid( pk->pkey[0], keyid ) : 0 ; /* from n */
} }
else { else {
const byte *dp; const byte *dp;
@ -267,12 +269,14 @@ fingerprint_from_pk( PKT_public_key *pk, size_t *ret_len )
MD_HANDLE md; MD_HANDLE md;
md = md_open( DIGEST_ALGO_MD5, 0); md = md_open( DIGEST_ALGO_MD5, 0);
p = buf = mpi_get_buffer( pk->pkey[0], &n, NULL ); if( pubkey_get_npkey( pk->pubkey_algo ) > 1 ) {
md_write( md, p, n ); p = buf = mpi_get_buffer( pk->pkey[0], &n, NULL );
m_free(buf); md_write( md, p, n );
p = buf = mpi_get_buffer( pk->pkey[1], &n, NULL ); m_free(buf);
md_write( md, p, n ); p = buf = mpi_get_buffer( pk->pkey[1], &n, NULL );
m_free(buf); md_write( md, p, n );
m_free(buf);
}
md_final(md); md_final(md);
array = m_alloc( 16 ); array = m_alloc( 16 );
len = 16; len = 16;
@ -306,12 +310,14 @@ fingerprint_from_sk( PKT_secret_key *sk, size_t *ret_len )
MD_HANDLE md; MD_HANDLE md;
md = md_open( DIGEST_ALGO_MD5, 0); md = md_open( DIGEST_ALGO_MD5, 0);
p = buf = mpi_get_buffer( sk->skey[1], &n, NULL ); if( pubkey_get_npkey( sk->pubkey_algo ) > 1 ) {
md_write( md, p, n ); p = buf = mpi_get_buffer( sk->skey[1], &n, NULL );
m_free(buf); md_write( md, p, n );
p = buf = mpi_get_buffer( sk->skey[0], &n, NULL ); m_free(buf);
md_write( md, p, n ); p = buf = mpi_get_buffer( sk->skey[0], &n, NULL );
m_free(buf); md_write( md, p, n );
m_free(buf);
}
md_final(md); md_final(md);
array = m_alloc( 16 ); array = m_alloc( 16 );
len = 16; len = 16;

View File

@ -145,18 +145,21 @@ typedef struct {
typedef struct { typedef struct {
u32 len; /* reserved */ u32 len; /* reserved */
byte new_ctb;
byte algorithm; byte algorithm;
IOBUF buf; /* IOBUF reference */ IOBUF buf; /* IOBUF reference */
} PKT_compressed; } PKT_compressed;
typedef struct { typedef struct {
u32 len; /* length of encrypted data */ u32 len; /* length of encrypted data */
byte new_ctb;
IOBUF buf; /* IOBUF reference */ IOBUF buf; /* IOBUF reference */
} PKT_encrypted; } PKT_encrypted;
typedef struct { typedef struct {
u32 len; /* length of encrypted data */ u32 len; /* length of encrypted data */
IOBUF buf; /* IOBUF reference */ IOBUF buf; /* IOBUF reference */
byte new_ctb;
int mode; int mode;
u32 timestamp; u32 timestamp;
int namelen; int namelen;
@ -224,7 +227,6 @@ int list_packets( IOBUF a );
int set_packet_list_mode( int mode ); int set_packet_list_mode( int mode );
int search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos ); int search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos );
int parse_packet( IOBUF inp, PACKET *ret_pkt); int parse_packet( IOBUF inp, PACKET *ret_pkt);
void parse_pubkey_warning( PACKET *pkt );
int copy_all_packets( IOBUF inp, IOBUF out ); int copy_all_packets( IOBUF inp, IOBUF out );
int copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff ); int copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff );
int skip_some_packets( IOBUF inp, unsigned n ); int skip_some_packets( IOBUF inp, unsigned n );

View File

@ -43,6 +43,7 @@ static int copy_packet( IOBUF inp, IOBUF out, int pkttype,
unsigned long pktlen ); unsigned long pktlen );
static void skip_packet( IOBUF inp, 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 skip_rest( IOBUF inp, unsigned long pktlen );
static void *read_rest( IOBUF inp, ulong *r_pktlen );
static int parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, static int parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet ); PACKET *packet );
static int parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, static int parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen,
@ -59,11 +60,11 @@ static int parse_comment( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet ); PACKET *packet );
static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen ); static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen );
static int parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, static int parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *pkt ); PACKET *packet, int new_ctb);
static int parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, static int parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet ); PACKET *packet, int new_ctb );
static int parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, static int parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet ); PACKET *packet, int new_ctb);
static unsigned short static unsigned short
@ -96,6 +97,19 @@ set_packet_list_mode( int mode )
return old; 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 * Parse a Packet and return it in packet
* Returns: 0 := valid packet in pkt * Returns: 0 := valid packet in pkt
@ -177,36 +191,6 @@ skip_some_packets( IOBUF inp, unsigned n )
} }
void
parse_pubkey_warning( PACKET *pkt )
{
static byte unknown_pubkey_algos[256];
int unk=0, uns=0;
if( pkt->pkttype == PKT_PUBLIC_KEY
|| pkt->pkttype == PKT_PUBLIC_SUBKEY )
unk = pkt->pkt.public_key->pubkey_algo & 0xff;
else if( pkt->pkttype == PKT_SECRET_KEY
|| pkt->pkttype == PKT_SECRET_SUBKEY )
unk = pkt->pkt.secret_key->pubkey_algo & 0xff;
else if( pkt->pkttype == PKT_SIGNATURE )
uns = pkt->pkt.signature->pubkey_algo & 0xff;
if( unk ) {
if( !(unknown_pubkey_algos[unk]&1) ) {
log_info("can't handle key "
"with public key algorithm %d\n", unk );
unknown_pubkey_algos[unk] |= 1;
}
}
else if( uns ) {
if( !(unknown_pubkey_algos[unk]&2) ) {
log_info("can't handle signature "
"with public key algorithm %d\n", uns );
unknown_pubkey_algos[unk] |= 2;
}
}
}
/**************** /****************
* Parse packet. Set the variable skip points to to 1 if the packet * Parse packet. Set the variable skip points to to 1 if the packet
@ -223,7 +207,7 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos,
unsigned long pktlen; unsigned long pktlen;
byte hdr[8]; byte hdr[8];
int hdrlen; int hdrlen;
int pgp3 = 0; int new_ctb = 0;
*skip = 0; *skip = 0;
assert( !pkt->pkt.generic ); assert( !pkt->pkt.generic );
@ -238,8 +222,8 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos,
return G10ERR_INVALID_PACKET; return G10ERR_INVALID_PACKET;
} }
pktlen = 0; pktlen = 0;
pgp3 = !!(ctb & 0x40); new_ctb = !!(ctb & 0x40);
if( pgp3 ) { if( new_ctb ) {
pkttype = ctb & 0x3f; pkttype = ctb & 0x3f;
if( (c = iobuf_get(inp)) == -1 ) { if( (c = iobuf_get(inp)) == -1 ) {
log_error("%s: 1st length byte missing\n", iobuf_where(inp) ); log_error("%s: 1st length byte missing\n", iobuf_where(inp) );
@ -257,7 +241,7 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos,
hdr[hdrlen++] = c; hdr[hdrlen++] = c;
pktlen += c + 192; pktlen += c + 192;
} }
else if( c < 255 ) { else if( c == 255 ) {
pktlen = (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 24; pktlen = (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 24;
pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 16; pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 16;
pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 8; pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 8;
@ -268,8 +252,7 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos,
pktlen |= (hdr[hdrlen++] = c ); pktlen |= (hdr[hdrlen++] = c );
} }
else { /* partial body length */ else { /* partial body length */
log_debug("partial body length of %lu bytes\n", pktlen ); iobuf_set_partial_block_mode(inp, c & 0xff);
iobuf_set_partial_block_mode(inp, pktlen);
pktlen = 0;/* to indicate partial length */ pktlen = 0;/* to indicate partial length */
} }
} }
@ -305,7 +288,7 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos,
if( DBG_PACKET ) if( DBG_PACKET )
log_debug("parse_packet(iob=%d): type=%d length=%lu%s\n", log_debug("parse_packet(iob=%d): type=%d length=%lu%s\n",
iobuf_id(inp), pkttype, pktlen, pgp3?" (pgp3)":"" ); iobuf_id(inp), pkttype, pktlen, new_ctb?" (new_ctb)":"" );
pkt->pkttype = pkttype; pkt->pkttype = pkttype;
rc = G10ERR_UNKNOWN_PACKET; /* default error */ rc = G10ERR_UNKNOWN_PACKET; /* default error */
switch( pkttype ) { switch( pkttype ) {
@ -345,13 +328,13 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos,
rc = G10ERR_UNKNOWN_PACKET; rc = G10ERR_UNKNOWN_PACKET;
break; break;
case PKT_PLAINTEXT: case PKT_PLAINTEXT:
rc = parse_plaintext(inp, pkttype, pktlen, pkt ); rc = parse_plaintext(inp, pkttype, pktlen, pkt, new_ctb );
break; break;
case PKT_COMPRESSED: case PKT_COMPRESSED:
rc = parse_compressed(inp, pkttype, pktlen, pkt ); rc = parse_compressed(inp, pkttype, pktlen, pkt, new_ctb );
break; break;
case PKT_ENCRYPTED: case PKT_ENCRYPTED:
rc = parse_encrypted(inp, pkttype, pktlen, pkt ); rc = parse_encrypted(inp, pkttype, pktlen, pkt, new_ctb );
break; break;
default: default:
skip_packet(inp, pkttype, pktlen); skip_packet(inp, pkttype, pktlen);
@ -445,6 +428,28 @@ skip_rest( IOBUF inp, unsigned long pktlen )
} }
} }
static void *
read_rest( IOBUF inp, ulong *r_pktlen )
{
byte *p;
int i;
size_t pktlen = *r_pktlen;
if( iobuf_in_block_mode(inp) ) {
log_error("read_rest: can't store stream data\n");
p = NULL;
}
else {
p = m_alloc( pktlen + 2 );
p[0] = pktlen >> 8;
p[1] = pktlen & 0xff;
for(i=2; pktlen; pktlen--, i++ )
p[i] = iobuf_get(inp);
}
*r_pktlen = 0;
return p;
}
static int static int
parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet ) parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
@ -548,16 +553,21 @@ parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
k->version, k->pubkey_algo, (ulong)k->keyid[0], (ulong)k->keyid[1]); k->version, k->pubkey_algo, (ulong)k->keyid[0], (ulong)k->keyid[1]);
ndata = pubkey_get_nenc(k->pubkey_algo); ndata = pubkey_get_nenc(k->pubkey_algo);
if( !ndata && list_mode ) if( !ndata ) {
printf("\tunsupported algorithm %d\n", k->pubkey_algo ); if( list_mode )
printf("\tunsupported algorithm %d\n", k->pubkey_algo );
for( i=0; i < ndata; i++ ) { unknown_pubkey_warning( k->pubkey_algo );
n = pktlen; k->data[0] = NULL; /* no need to store the encrypted data */
k->data[i] = mpi_read(inp, &n, 0); pktlen -=n; }
if( list_mode ) { else {
printf("\tdata: "); for( i=0; i < ndata; i++ ) {
mpi_print(stdout, k->data[i], mpi_print_mode ); n = pktlen;
putchar('\n'); 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');
}
} }
} }
@ -783,17 +793,24 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
} }
ndata = pubkey_get_nsig(sig->pubkey_algo); ndata = pubkey_get_nsig(sig->pubkey_algo);
if( !ndata && list_mode ) if( !ndata ) {
printf("\tunknown algorithm %d\n", sig->pubkey_algo ); if( list_mode )
printf("\tunknown algorithm %d\n", sig->pubkey_algo );
for( i=0; i < ndata; i++ ) { unknown_pubkey_warning( sig->pubkey_algo );
n = pktlen; /* we store the plain material in data[0], so that we are able
sig->data[i] = mpi_read(inp, &n, 0 ); * to write it back with build_packet() */
pktlen -=n; sig->data[0] = read_rest(inp, &pktlen );
if( list_mode ) { }
printf("\tdata: "); else {
mpi_print(stdout, sig->data[i], mpi_print_mode ); for( i=0; i < ndata; i++ ) {
putchar('\n'); 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');
}
} }
} }
@ -923,8 +940,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
if( !npkey ) { if( !npkey ) {
if( list_mode ) if( list_mode )
printf("\tunknown algorithm %d\n", algorithm ); printf("\tunknown algorithm %d\n", algorithm );
rc = G10ERR_PUBKEY_ALGO; unknown_pubkey_warning( algorithm );
goto leave;
} }
@ -932,6 +948,11 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
PKT_secret_key *sk = pkt->pkt.secret_key; PKT_secret_key *sk = pkt->pkt.secret_key;
byte temp[8]; byte temp[8];
if( !npkey ) {
sk->skey[0] = read_rest( inp, &pktlen );
goto leave;
}
for(i=0; i < npkey; i++ ) { for(i=0; i < npkey; i++ ) {
n = pktlen; sk->skey[i] = mpi_read(inp, &n, 0 ); pktlen -=n; n = pktlen; sk->skey[i] = mpi_read(inp, &n, 0 ); pktlen -=n;
if( list_mode ) { if( list_mode ) {
@ -1053,6 +1074,11 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
else { else {
PKT_public_key *pk = pkt->pkt.public_key; PKT_public_key *pk = pkt->pkt.public_key;
if( !npkey ) {
pk->pkey[0] = read_rest( inp, &pktlen );
goto leave;
}
for(i=0; i < npkey; i++ ) { for(i=0; i < npkey; i++ ) {
n = pktlen; pk->pkey[i] = mpi_read(inp, &n, 0 ); pktlen -=n; n = pktlen; pk->pkey[i] = mpi_read(inp, &n, 0 ); pktlen -=n;
if( list_mode ) { if( list_mode ) {
@ -1135,7 +1161,8 @@ parse_trust( IOBUF inp, int pkttype, unsigned long pktlen )
static int static int
parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt ) parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *pkt, int new_ctb )
{ {
int mode, namelen; int mode, namelen;
PKT_plaintext *pt; PKT_plaintext *pt;
@ -1149,6 +1176,7 @@ parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--; mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
namelen = 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 = pkt->pkt.plaintext = m_alloc(sizeof *pkt->pkt.plaintext + namelen -1);
pt->new_ctb = new_ctb;
pt->mode = mode; pt->mode = mode;
pt->namelen = namelen; pt->namelen = namelen;
if( pktlen ) { if( pktlen ) {
@ -1187,7 +1215,8 @@ parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
static int static int
parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt ) parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *pkt, int new_ctb )
{ {
PKT_compressed *zd; PKT_compressed *zd;
@ -1198,6 +1227,7 @@ parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
zd = pkt->pkt.compressed = m_alloc(sizeof *pkt->pkt.compressed ); zd = pkt->pkt.compressed = m_alloc(sizeof *pkt->pkt.compressed );
zd->len = 0; /* not yet used */ zd->len = 0; /* not yet used */
zd->algorithm = iobuf_get_noeof(inp); zd->algorithm = iobuf_get_noeof(inp);
zd->new_ctb = new_ctb;
zd->buf = inp; zd->buf = inp;
if( list_mode ) if( list_mode )
printf(":compressed packet: algo=%d\n", zd->algorithm); printf(":compressed packet: algo=%d\n", zd->algorithm);
@ -1206,13 +1236,15 @@ parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
static int static int
parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt ) parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *pkt, int new_ctb )
{ {
PKT_encrypted *ed; PKT_encrypted *ed;
ed = pkt->pkt.encrypted = m_alloc(sizeof *pkt->pkt.encrypted ); ed = pkt->pkt.encrypted = m_alloc(sizeof *pkt->pkt.encrypted );
ed->len = pktlen; ed->len = pktlen;
ed->buf = NULL; ed->buf = NULL;
ed->new_ctb = new_ctb;
if( pktlen && pktlen < 10 ) { if( pktlen && pktlen < 10 ) {
log_error("packet(%d) too short\n", pkttype); log_error("packet(%d) too short\n", pkttype);
skip_rest(inp, pktlen); skip_rest(inp, pktlen);

View File

@ -575,9 +575,7 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root )
kbpos->count=0; kbpos->count=0;
while( (rc=parse_packet(a, pkt)) != -1 ) { while( (rc=parse_packet(a, pkt)) != -1 ) {
if( rc ) { /* ignore errors */ if( rc ) { /* ignore errors */
if( rc == G10ERR_PUBKEY_ALGO ) if( rc != G10ERR_UNKNOWN_PACKET ) {
parse_pubkey_warning( pkt );
else if( rc != G10ERR_UNKNOWN_PACKET ) {
log_error("read_keyblock: read error: %s\n", g10_errstr(rc) ); log_error("read_keyblock: read error: %s\n", g10_errstr(rc) );
rc = G10ERR_INV_KEYRING; rc = G10ERR_INV_KEYRING;
goto ready; goto ready;
@ -640,9 +638,7 @@ keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs )
init_packet(pkt); init_packet(pkt);
while( (rc=parse_packet(kbpos->fp, pkt)) != -1 ) { while( (rc=parse_packet(kbpos->fp, pkt)) != -1 ) {
if( rc ) { /* ignore errors */ if( rc ) { /* ignore errors */
if( rc == G10ERR_PUBKEY_ALGO ) if( rc != G10ERR_UNKNOWN_PACKET ) {
parse_pubkey_warning( pkt );
else if( rc != G10ERR_UNKNOWN_PACKET ) {
log_error("read_keyblock: read error: %s\n", g10_errstr(rc) ); log_error("read_keyblock: read error: %s\n", g10_errstr(rc) );
rc = G10ERR_INV_KEYRING; rc = G10ERR_INV_KEYRING;
goto ready; goto ready;

View File

@ -34,6 +34,7 @@
#define CIPHER_ALGO_SAFER_SK128 5 #define CIPHER_ALGO_SAFER_SK128 5
#define CIPHER_ALGO_DES_SK 6 #define CIPHER_ALGO_DES_SK 6
#define CIPHER_ALGO_BLOWFISH160 42 /* blowfish 160 bit key (not in OpenPGP)*/ #define CIPHER_ALGO_BLOWFISH160 42 /* blowfish 160 bit key (not in OpenPGP)*/
#define CIPHER_ALGO_SKIPJACK 101 /* experimental: skipjack */
#define CIPHER_ALGO_DUMMY 110 /* no encryption at all */ #define CIPHER_ALGO_DUMMY 110 /* no encryption at all */
#define PUBKEY_ALGO_RSA 1 #define PUBKEY_ALGO_RSA 1

View File

@ -1,3 +1,7 @@
Thu Jul 2 15:55:44 1998 Werner Koch (wk@isil.d.shuttle.de)
* iobuf.c (block_filter): Add writing of OP partial length headers.
Fri Jun 26 10:38:35 1998 Werner Koch (wk@isil.d.shuttle.de) Fri Jun 26 10:38:35 1998 Werner Koch (wk@isil.d.shuttle.de)
* ttyio.c (do_get): all iso8859-1 characters are now allowed. * ttyio.c (do_get): all iso8859-1 characters are now allowed.

View File

@ -37,14 +37,24 @@ typedef struct {
char fname[1]; /* name of the file */ char fname[1]; /* name of the file */
} file_filter_ctx_t ; } file_filter_ctx_t ;
/* The first partial length header block must be of size 512
* to make it easier (and efficienter) we use a min. block size of 512
* for all chznks (but the last one) */
#define OP_MIN_PARTIAL_CHUNK 512
#define OP_MIN_PARTIAL_CHUNK_2POW 9
typedef struct { typedef struct {
int usage; int usage;
size_t size; size_t size;
size_t count; size_t count;
int partial; /* 1 = partial header, 2 in last partial packet */ int partial; /* 1 = partial header, 2 in last partial packet */
char *buffer; /* used for partial header */
size_t buflen; /* used size of buffer */
int first_c; /* of partial header (which is > 0)*/
int eof; int eof;
} block_filter_ctx_t; } block_filter_ctx_t;
static int underflow(IOBUF a); static int underflow(IOBUF a);
/**************** /****************
@ -152,7 +162,14 @@ block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
break; break;
} }
else if( a->partial ) { else if( a->partial ) {
if( (c = iobuf_get(chain)) == -1 ) { /* These OpenPGP introduced huffman encoded length
* bytes are really a mess :-( */
if( a->first_c ) {
c = a->first_c;
a->first_c = 0;
assert( c >= 224 && c < 255 );
}
else if( (c = iobuf_get(chain)) == -1 ) {
log_error("block_filter: 1st length byte missing\n"); log_error("block_filter: 1st length byte missing\n");
rc = G10ERR_READ_FILE; rc = G10ERR_READ_FILE;
break; break;
@ -183,11 +200,22 @@ block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
break; break;
} }
} }
else if( c == 255 ) {
a->size = iobuf_get(chain) << 24;
a->size |= iobuf_get(chain) << 16;
a->size |= iobuf_get(chain) << 8;
if( (c = iobuf_get(chain)) == -1 ) {
log_error("block_filter: invalid 4 byte length\n");
rc = G10ERR_READ_FILE;
break;
}
a->size |= c;
}
else { /* next partial body length */ else { /* next partial body length */
a->size = 1 << (c & 0x1f); a->size = 1 << (c & 0x1f);
} }
} }
else { else { /* the gnupg partial length scheme - much better :-) */
c = iobuf_get(chain); c = iobuf_get(chain);
a->size = c << 8; a->size = c << 8;
c = iobuf_get(chain); c = iobuf_get(chain);
@ -220,33 +248,85 @@ block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
*ret_len = n; *ret_len = n;
} }
else if( control == IOBUFCTRL_FLUSH ) { else if( control == IOBUFCTRL_FLUSH ) {
size_t avail, n; if( a->partial ) { /* the complicated openpgp scheme */
size_t blen, n, nbytes = size + a->buflen;
assert( !a->partial ); assert( a->buflen <= OP_MIN_PARTIAL_CHUNK );
for(p=buf; !rc && size; ) { if( nbytes < OP_MIN_PARTIAL_CHUNK ) {
n = size; /* not enough to write a partial block out , so we store it*/
avail = a->size - a->count; if( !a->buffer )
if( !avail ) { a->buffer = m_alloc( OP_MIN_PARTIAL_CHUNK );
if( n > a->size ) { memcpy( a->buffer + a->buflen, buf, size );
iobuf_put( chain, (a->size >> 8) & 0xff ); a->buflen += size;
iobuf_put( chain, a->size & 0xff ); }
avail = a->size; else { /* okay, we can write out something */
a->count = 0; /* do this in a loop to use the most efficient block lengths */
} p = buf;
else { do {
iobuf_put( chain, (n >> 8) & 0xff ); /* find the best matching block length - this is limited
iobuf_put( chain, n & 0xff ); * by the size of the internal buffering */
avail = n; for( blen=OP_MIN_PARTIAL_CHUNK*2,
a->count = a->size - n; c=OP_MIN_PARTIAL_CHUNK_2POW+1; blen < nbytes;
blen *=2, c++ )
;
blen /= 2; c--;
/* write the partial length header */
assert( c <= 0x1f ); /*;-)*/
c |= 0xe0;
iobuf_put( chain, c );
if( (n=a->buflen) ) { /* write stuff from the buffer */
assert( n == OP_MIN_PARTIAL_CHUNK);
if( iobuf_write(chain, a->buffer, n ) )
rc = G10ERR_WRITE_FILE;
a->buflen = 0;
nbytes -= n;
}
if( (n = nbytes) > blen )
n = blen;
if( n && iobuf_write(chain, p, n ) )
rc = G10ERR_WRITE_FILE;
p += n;
nbytes -= n;
} while( !rc && nbytes >= OP_MIN_PARTIAL_CHUNK );
/* store the rest in the buffer */
if( !rc && nbytes ) {
assert( !a->buflen );
assert( nbytes < OP_MIN_PARTIAL_CHUNK );
if( !a->buffer )
a->buffer = m_alloc( OP_MIN_PARTIAL_CHUNK );
memcpy( a->buffer, p, nbytes );
a->buflen = nbytes;
} }
} }
if( n > avail ) }
n = avail; else { /* the gnupg scheme */
if( iobuf_write(chain, p, n ) ) size_t avail, n;
rc = G10ERR_WRITE_FILE;
a->count += n; for(p=buf; !rc && size; ) {
p += n; n = size;
size -= n; avail = a->size - a->count;
if( !avail ) {
if( n > a->size ) {
iobuf_put( chain, (a->size >> 8) & 0xff );
iobuf_put( chain, a->size & 0xff );
avail = a->size;
a->count = 0;
}
else {
iobuf_put( chain, (n >> 8) & 0xff );
iobuf_put( chain, n & 0xff );
avail = n;
a->count = a->size - n;
}
}
if( n > avail )
n = avail;
if( iobuf_write(chain, p, n ) )
rc = G10ERR_WRITE_FILE;
a->count += n;
p += n;
size -= n;
}
} }
} }
else if( control == IOBUFCTRL_INIT ) { else if( control == IOBUFCTRL_INIT ) {
@ -259,6 +339,8 @@ block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
else else
a->count = a->size; /* force first length bytes */ a->count = a->size; /* force first length bytes */
a->eof = 0; a->eof = 0;
a->buffer = NULL;
a->buflen = 0;
} }
else if( control == IOBUFCTRL_DESC ) { else if( control == IOBUFCTRL_DESC ) {
*(char**)buf = "block_filter"; *(char**)buf = "block_filter";
@ -266,6 +348,39 @@ block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
else if( control == IOBUFCTRL_FREE ) { else if( control == IOBUFCTRL_FREE ) {
if( a->usage == 2 ) { /* write the end markers */ if( a->usage == 2 ) { /* write the end markers */
if( a->partial ) { if( a->partial ) {
u32 len;
/* write out the remaining bytes without a partial header
* the length of this header may be 0 - but if it is
* the first block we are not allowed to use a partial header
* and frankly we can't do so, because this length must be
* a power of 2. This is _really_ complicated because we
* have to check the possible length of a packet prior
* to it's creation: a chein of filters becomes complicated
* and we need a lot of code to handle compressed packets etc.
* :-(((((((
*/
/* construct header */
len = a->buflen;
if( len < 192 )
rc = iobuf_put(chain, len );
else if( len < 8384 ) {
if( !(rc=iobuf_put( chain, ((len-192) / 256) + 192)) )
rc = iobuf_put( chain, ((len-192) % 256));
}
else { /* use a 4 byte header */
if( !(rc=iobuf_put( chain, 0xff )) )
if( !(rc=iobuf_put( chain, (len >> 24)&0xff )) )
if( !(rc=iobuf_put( chain, (len >> 16)&0xff )) )
if( !(rc=iobuf_put( chain, (len >> 8)&0xff )))
rc=iobuf_put( chain, len & 0xff );
}
if( !rc && len )
rc = iobuf_write(chain, a->buffer, len );
if( rc ) {
log_error("block_filter: write error: %s\n",strerror(errno));
rc = G10ERR_WRITE_FILE;
}
m_free( a->buffer ); a->buffer = NULL; a->buflen = 0;
} }
else { else {
iobuf_writebyte(chain, 0); iobuf_writebyte(chain, 0);
@ -994,7 +1109,7 @@ iobuf_set_block_mode( IOBUF a, size_t n )
/**************** /****************
* enable partial block mode as described in the OpenPGP draft. * enable partial block mode as described in the OpenPGP draft.
* LEN is the first length * LEN is the first length byte on read, but ignored on writes.
*/ */
void void
iobuf_set_partial_block_mode( IOBUF a, size_t len ) iobuf_set_partial_block_mode( IOBUF a, size_t len )
@ -1008,7 +1123,8 @@ iobuf_set_partial_block_mode( IOBUF a, size_t len )
} }
else { else {
ctx->partial = 1; ctx->partial = 1;
ctx->size = len; ctx->size = 0;
ctx->first_c = len;
iobuf_push_filter(a, block_filter, ctx ); iobuf_push_filter(a, block_filter, ctx );
} }
} }