partly added creation of OP partial length headers
authorWerner Koch <wk@gnupg.org>
Thu, 2 Jul 1998 19:31:46 +0000 (19:31 +0000)
committerWerner Koch <wk@gnupg.org>
Thu, 2 Jul 1998 19:31:46 +0000 (19:31 +0000)
17 files changed:
TODO
cipher/ChangeLog
cipher/cipher.c
g10/ChangeLog
g10/armor.c
g10/build-packet.c
g10/cipher.c
g10/filter.h
g10/free-packet.c
g10/import.c
g10/keyid.c
g10/packet.h
g10/parse-packet.c
g10/ringedit.c
include/cipher.h
util/ChangeLog
util/iobuf.c

diff --git a/TODO b/TODO
index b0a620a..50d799a 100644 (file)
--- a/TODO
+++ b/TODO
@@ -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
 
     * make preferences work
index 92ca470..2e47f9a 100644 (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)
 
        * Makefile.am: Support for extensions
index df38850..25b1e8f 100644 (file)
@@ -305,10 +305,10 @@ cipher_open( int algo, int mode, int secure )
     if( algo == CIPHER_ALGO_DUMMY )
        hd->mode = CIPHER_MODE_DUMMY;
     else if( mode == CIPHER_MODE_AUTO_CFB ) {
-       if( algo != CIPHER_ALGO_BLOWFISH160 )
-           hd->mode = CIPHER_MODE_PHILS_CFB;
-       else
+       if( algo == CIPHER_ALGO_BLOWFISH160 || algo >= 100 )
            hd->mode = CIPHER_MODE_CFB;
+       else
+           hd->mode = CIPHER_MODE_PHILS_CFB;
     }
     else
        hd->mode = mode;
index ccee5b9..7094ed6 100644 (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)
 
        * packet.h: changed all "_cert" to "_key", "subcert" to "subkey".
index 82b240f..7fe2f81 100644 (file)
@@ -87,8 +87,9 @@ static char *head_strings[] = {
     "BEGIN PGP PUBLIC KEY BLOCK",
     "BEGIN PGP SIGNATURE",
     "BEGIN PGP SIGNED MESSAGE",
-    "BEGIN PGP ARMORED FILE",
-    "BEGIN PGP SECRET KEY BLOCK",
+    "BEGIN PGP ARMORED FILE",       /* gnupg extension */
+    "BEGIN PGP PRIVATE KEY BLOCK",
+    "BEGIN PGP SECRET KEY BLOCK",   /* only used by pgp2 */
     NULL
 };
 static char *tail_strings[] = {
@@ -97,6 +98,7 @@ static char *tail_strings[] = {
     "END PGP SIGNATURE",
     "END dummy",
     "END PGP ARMORED FILE",
+    "END PGP PRIVATE KEY BLOCK",
     "END PGP SECRET KEY BLOCK",
     NULL
 };
index cb08275..b8acc57 100644 (file)
@@ -64,14 +64,21 @@ static int write_version( IOBUF out, int ctb );
 int
 build_packet( IOBUF out, PACKET *pkt )
 {
-    int rc=0, ctb;
+    int new_ctb=0, rc=0, ctb;
 
     if( DBG_PACKET )
        log_debug("build_packet() type=%d\n", pkt->pkttype );
-    if( pkt->pkttype == PKT_OLD_COMMENT )
-       pkt->pkttype = PKT_COMMENT;
     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);
     else
        ctb = 0x80 | ((pkt->pkttype & 15)<<2);
@@ -152,6 +159,19 @@ calc_packet_length( PACKET *pkt )
     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
 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 );
     iobuf_put(a, 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++ )
        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 );
     nskey = pubkey_get_nskey( sk->pubkey_algo );
     npkey = pubkey_get_npkey( sk->pubkey_algo );
+    if( npkey ) {
+       write_fake_data( a, sk->skey[0] );
+       goto leave;
+    }
     assert( npkey < nskey );
 
     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] );
     write_16(a, sk->csum );
 
+  leave:
     write_header2(out, ctb, iobuf_get_temp_length(a), sk->hdrbytes, 1 );
     if( iobuf_write_temp( out, a ) )
        rc = G10ERR_WRITE_FILE;
@@ -326,6 +353,9 @@ do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc )
     return rc;
 }
 
+
+
+
 static int
 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] );
     iobuf_put(a,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++ )
        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[1] );
     n = pubkey_get_nsig( sig->pubkey_algo );
+    if( !n )
+       write_fake_data( a, sig->data[0] );
     for(i=0; i < n; 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 ) )
        return -1;
     if( !len ) {
-       log_bug("can't write partial headers yet\n");
+       iobuf_set_partial_block_mode(out, 512 );
     }
     else {
        if( len < 192 ) {
index c6a43c6..b975d26 100644 (file)
 #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 */
        assert(a);
        if( !cfx->header ) {
-           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;
+           write_header( cfx, a );
        }
        cipher_encrypt( cfx->cipher_hd, buf, buf, size);
        if( iobuf_write( a, buf, size ) )
            rc = G10ERR_WRITE_FILE;
     }
     else if( control == IOBUFCTRL_FREE ) {
+      #if 0
+       if( cfx->new_partial && cfx->cfx->la_buffer ) {
+
+       }
+      #endif
        cipher_close(cfx->cipher_hd);
+       m_free(cfx->la_buffer); cfx->la_buffer = NULL;
     }
     else if( control == IOBUFCTRL_DESC ) {
        *(char**)buf = "cipher_filter";
index 2dc8a3e..108e64c 100644 (file)
@@ -61,6 +61,9 @@ typedef struct {
 typedef struct {
     DEK *dek;
     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;
     int header;
 } cipher_filter_context_t;
index 6b3b768..9d623ec 100644 (file)
@@ -42,6 +42,10 @@ free_pubkey_enc( PKT_pubkey_enc *enc )
 {
     int n, i;
     n = pubkey_get_nenc( enc->pubkey_algo );
+    if( !n ) {
+       m_free(enc->data[0]);
+       enc->data[0] = NULL;
+    }
     for(i=0; i < n; i++ )
        mpi_free( enc->data[i] );
     m_free(enc);
@@ -52,6 +56,10 @@ free_seckey_enc( PKT_signature *sig )
 {
     int n, i;
     n = pubkey_get_nenc( sig->pubkey_algo );
+    if( !n ) {
+       m_free(sig->data[0]);
+       sig->data[0] = NULL;
+    }
     for(i=0; i < n; i++ )
        mpi_free( sig->data[i] );
     m_free(sig->hashed_data);
@@ -66,6 +74,10 @@ release_public_key_parts( PKT_public_key *pk )
 {
     int n, i;
     n = pubkey_get_npkey( pk->pubkey_algo );
+    if( !n ) {
+       m_free(pk->pkey[0]);
+       pk->pkey[0] = NULL;
+    }
     for(i=0; i < n; i++ ) {
        mpi_free( pk->pkey[i] );
        pk->pkey[i] = NULL;
@@ -80,6 +92,22 @@ free_public_key( PKT_public_key *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 *
 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);
     memcpy( d, s, sizeof *d );
     n = pubkey_get_npkey( s->pubkey_algo );
-    for(i=0; i < n; i++ )
-       d->pkey[i] = mpi_copy( s->pkey[i] );
+    if( !n )
+       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;
 }
 
@@ -100,6 +132,10 @@ release_secret_key_parts( PKT_secret_key *sk )
     int n, i;
 
     n = pubkey_get_nskey( sk->pubkey_algo );
+    if( !n ) {
+       m_free(sk->skey[0]);
+       sk->skey[0] = NULL;
+    }
     for(i=0; i < n; i++ ) {
        mpi_free( sk->skey[i] );
        sk->skey[i] = NULL;
@@ -122,8 +158,12 @@ copy_secret_key( PKT_secret_key *d, PKT_secret_key *s )
        d = m_alloc(sizeof *d);
     memcpy( d, s, sizeof *d );
     n = pubkey_get_nskey( s->pubkey_algo );
-    for(i=0; i < n; i++ )
-       d->skey[i] = mpi_copy( s->skey[i] );
+    if( !n )
+       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;
 }
 
@@ -254,6 +294,8 @@ cmp_public_keys( PKT_public_key *a, PKT_public_key *b )
        return -1;
 
     n = pubkey_get_npkey( b->pubkey_algo );
+    if( !n )
+       return -1; /* can't compare due to unknown algorithm */
     for(i=0; i < n; i++ ) {
        if( mpi_cmp( a->pkey[i], b->pkey[i] ) )
            return -1;
@@ -278,6 +320,8 @@ cmp_public_secret_key( PKT_public_key *pk, PKT_secret_key *sk )
        return -1;
 
     n = pubkey_get_npkey( pk->pubkey_algo );
+    if( !n )
+       return -1; /* can't compare due to unknown algorithm */
     for(i=0; i < n; i++ ) {
        if( mpi_cmp( pk->pkey[i] , sk->skey[i] ) )
            return -1;
index 719a8e8..1467f09 100644 (file)
@@ -159,9 +159,7 @@ read_block( IOBUF a, compress_filter_context_t *cfx,
     init_packet(pkt);
     while( (rc=parse_packet(a, pkt)) != -1 ) {
        if( rc ) {  /* ignore errors */
-           if( rc == G10ERR_PUBKEY_ALGO )
-               parse_pubkey_warning( pkt );
-           else if( rc != G10ERR_UNKNOWN_PACKET ) {
+           if( rc != G10ERR_UNKNOWN_PACKET ) {
                log_error("read_block: read error: %s\n", g10_errstr(rc) );
                rc = G10ERR_INV_KEYRING;
                goto ready;
index 499c892..74bbf8c 100644 (file)
@@ -130,7 +130,8 @@ keyid_from_sk( PKT_secret_key *sk, u32 *keyid )
        keyid = dummy_keyid;
 
     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 {
        const byte *dp;
@@ -161,7 +162,8 @@ keyid_from_pk( PKT_public_key *pk, u32 *keyid )
        keyid = dummy_keyid;
 
     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 {
        const byte *dp;
@@ -267,12 +269,14 @@ fingerprint_from_pk( PKT_public_key *pk, size_t *ret_len )
        MD_HANDLE md;
 
        md = md_open( DIGEST_ALGO_MD5, 0);
-       p = buf = mpi_get_buffer( pk->pkey[0], &n, NULL );
-       md_write( md, p, n );
-       m_free(buf);
-       p = buf = mpi_get_buffer( pk->pkey[1], &n, NULL );
-       md_write( md, p, n );
-       m_free(buf);
+       if( pubkey_get_npkey( pk->pubkey_algo ) > 1 ) {
+           p = buf = mpi_get_buffer( pk->pkey[0], &n, NULL );
+           md_write( md, p, n );
+           m_free(buf);
+           p = buf = mpi_get_buffer( pk->pkey[1], &n, NULL );
+           md_write( md, p, n );
+           m_free(buf);
+       }
        md_final(md);
        array = m_alloc( 16 );
        len = 16;
@@ -306,12 +310,14 @@ fingerprint_from_sk( PKT_secret_key *sk, size_t *ret_len )
        MD_HANDLE md;
 
        md = md_open( DIGEST_ALGO_MD5, 0);
-       p = buf = mpi_get_buffer( sk->skey[1], &n, NULL );
-       md_write( md, p, n );
-       m_free(buf);
-       p = buf = mpi_get_buffer( sk->skey[0], &n, NULL );
-       md_write( md, p, n );
-       m_free(buf);
+       if( pubkey_get_npkey( sk->pubkey_algo ) > 1 ) {
+           p = buf = mpi_get_buffer( sk->skey[1], &n, NULL );
+           md_write( md, p, n );
+           m_free(buf);
+           p = buf = mpi_get_buffer( sk->skey[0], &n, NULL );
+           md_write( md, p, n );
+           m_free(buf);
+       }
        md_final(md);
        array = m_alloc( 16 );
        len = 16;
index b3a9d75..4524328 100644 (file)
@@ -145,18 +145,21 @@ typedef struct {
 
 typedef struct {
     u32  len;            /* reserved */
+    byte  new_ctb;
     byte  algorithm;
     IOBUF buf;           /* IOBUF reference */
 } PKT_compressed;
 
 typedef struct {
     u32  len;            /* length of encrypted data */
+    byte  new_ctb;
     IOBUF buf;           /* IOBUF reference */
 } PKT_encrypted;
 
 typedef struct {
     u32  len;            /* length of encrypted data */
     IOBUF buf;           /* IOBUF reference */
+    byte new_ctb;
     int mode;
     u32 timestamp;
     int  namelen;
@@ -224,7 +227,6 @@ int list_packets( IOBUF a );
 int set_packet_list_mode( int mode );
 int search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos );
 int parse_packet( IOBUF inp, PACKET *ret_pkt);
-void parse_pubkey_warning( PACKET *pkt );
 int copy_all_packets( IOBUF inp, IOBUF out );
 int copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff );
 int skip_some_packets( IOBUF inp, unsigned n );
index 153c4bc..20afd41 100644 (file)
@@ -43,6 +43,7 @@ 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, ulong *r_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,
@@ -59,11 +60,11 @@ static int  parse_comment( IOBUF inp, int pkttype, unsigned long pktlen,
                                                           PACKET *packet );
 static void parse_trust( 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,
-                                                          PACKET *packet );
+                                              PACKET *packet, int new_ctb );
 static int  parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
-                                                          PACKET *packet );
+                                              PACKET *packet, int new_ctb);
 
 
 static unsigned short
@@ -96,6 +97,19 @@ set_packet_list_mode( int mode )
     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
@@ -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
@@ -223,7 +207,7 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos,
     unsigned long pktlen;
     byte hdr[8];
     int hdrlen;
-    int pgp3 = 0;
+    int new_ctb = 0;
 
     *skip = 0;
     assert( !pkt->pkt.generic );
@@ -238,8 +222,8 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos,
        return G10ERR_INVALID_PACKET;
     }
     pktlen = 0;
-    pgp3 = !!(ctb & 0x40);
-    if( pgp3 ) {
+    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) );
@@ -257,7 +241,7 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos,
            hdr[hdrlen++] = c;
            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)) << 16;
            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 );
        }
        else { /* partial body length */
-           log_debug("partial body length of %lu bytes\n", pktlen );
-           iobuf_set_partial_block_mode(inp, pktlen);
+           iobuf_set_partial_block_mode(inp, c & 0xff);
            pktlen = 0;/* to indicate partial length */
        }
     }
@@ -305,7 +288,7 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos,
 
     if( DBG_PACKET )
        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;
     rc = G10ERR_UNKNOWN_PACKET; /* default error */
     switch( pkttype ) {
@@ -345,13 +328,13 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos,
        rc = G10ERR_UNKNOWN_PACKET;
        break;
       case PKT_PLAINTEXT:
-       rc = parse_plaintext(inp, pkttype, pktlen, pkt );
+       rc = parse_plaintext(inp, pkttype, pktlen, pkt, new_ctb );
        break;
       case PKT_COMPRESSED:
-       rc = parse_compressed(inp, pkttype, pktlen, pkt );
+       rc = parse_compressed(inp, pkttype, pktlen, pkt, new_ctb );
        break;
       case PKT_ENCRYPTED:
-       rc = parse_encrypted(inp, pkttype, pktlen, pkt );
+       rc = parse_encrypted(inp, pkttype, pktlen, pkt, new_ctb );
        break;
       default:
        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
 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]);
 
     ndata = pubkey_get_nenc(k->pubkey_algo);
-    if( !ndata && list_mode )
-       printf("\tunsupported algorithm %d\n", k->pubkey_algo );
-
-    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( !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');
+           }
        }
     }
 
@@ -783,17 +793,24 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
     }
 
     ndata = pubkey_get_nsig(sig->pubkey_algo);
-    if( !ndata && list_mode )
-       printf("\tunknown algorithm %d\n", sig->pubkey_algo );
-
-    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( !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] = read_rest(inp, &pktlen );
+    }
+    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');
+           }
        }
     }
 
@@ -923,8 +940,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
     if( !npkey ) {
        if( list_mode )
            printf("\tunknown algorithm %d\n", algorithm );
-       rc = G10ERR_PUBKEY_ALGO;
-       goto leave;
+       unknown_pubkey_warning( algorithm );
     }
 
 
@@ -932,6 +948,11 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
        PKT_secret_key *sk = pkt->pkt.secret_key;
        byte temp[8];
 
+       if( !npkey ) {
+           sk->skey[0] = read_rest( inp, &pktlen );
+           goto leave;
+       }
+
        for(i=0; i < npkey; i++ ) {
            n = pktlen; sk->skey[i] = mpi_read(inp, &n, 0 ); pktlen -=n;
            if( list_mode ) {
@@ -1053,6 +1074,11 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
     else {
        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++ ) {
            n = pktlen; pk->pkey[i] = mpi_read(inp, &n, 0 ); pktlen -=n;
            if( list_mode ) {
@@ -1135,7 +1161,8 @@ parse_trust( IOBUF inp, int pkttype, unsigned long pktlen )
 
 
 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;
     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--;
     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;
     if( pktlen ) {
@@ -1187,7 +1215,8 @@ parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *pkt )
 
 
 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;
 
@@ -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->len = 0; /* not yet used */
     zd->algorithm = iobuf_get_noeof(inp);
+    zd->new_ctb = new_ctb;
     zd->buf = inp;
     if( list_mode )
        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
-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;
 
     ed = pkt->pkt.encrypted =  m_alloc(sizeof *pkt->pkt.encrypted );
     ed->len = pktlen;
     ed->buf = NULL;
+    ed->new_ctb = new_ctb;
     if( pktlen && pktlen < 10 ) {
        log_error("packet(%d) too short\n", pkttype);
        skip_rest(inp, pktlen);
index 4250975..8762470 100644 (file)
@@ -575,9 +575,7 @@ keyring_read( KBPOS *kbpos, KBNODE *ret_root )
     kbpos->count=0;
     while( (rc=parse_packet(a, pkt)) != -1 ) {
        if( rc ) {  /* ignore errors */
-           if( rc == G10ERR_PUBKEY_ALGO )
-               parse_pubkey_warning( pkt );
-           else if( rc != G10ERR_UNKNOWN_PACKET ) {
+           if( rc != G10ERR_UNKNOWN_PACKET ) {
                log_error("read_keyblock: read error: %s\n", g10_errstr(rc) );
                rc = G10ERR_INV_KEYRING;
                goto ready;
@@ -640,9 +638,7 @@ keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs )
     init_packet(pkt);
     while( (rc=parse_packet(kbpos->fp, pkt)) != -1 ) {
        if( rc ) {  /* ignore errors */
-           if( rc == G10ERR_PUBKEY_ALGO )
-               parse_pubkey_warning( pkt );
-           else if( rc != G10ERR_UNKNOWN_PACKET ) {
+           if( rc != G10ERR_UNKNOWN_PACKET ) {
                log_error("read_keyblock: read error: %s\n", g10_errstr(rc) );
                rc = G10ERR_INV_KEYRING;
                goto ready;
index 972b2ff..cea0a21 100644 (file)
@@ -34,6 +34,7 @@
 #define CIPHER_ALGO_SAFER_SK128  5
 #define CIPHER_ALGO_DES_SK      6
 #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 PUBKEY_ALGO_RSA        1
index e65a8d4..76e8513 100644 (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)
 
        * ttyio.c (do_get): all iso8859-1 characters are now allowed.
index 772dfa1..7be3431 100644 (file)
@@ -37,14 +37,24 @@ typedef struct {
     char fname[1]; /* name of the file */
 } 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 {
     int usage;
     size_t size;
     size_t count;
     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;
 } block_filter_ctx_t;
 
+
 static int underflow(IOBUF a);
 
 /****************
@@ -152,7 +162,14 @@ block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
                    break;
                }
                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");
                        rc = G10ERR_READ_FILE;
                        break;
@@ -183,11 +200,22 @@ block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
                            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 */
                        a->size = 1 << (c & 0x1f);
                    }
                }
-               else {
+               else { /* the gnupg partial length scheme - much better :-) */
                    c = iobuf_get(chain);
                    a->size = c << 8;
                    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;
     }
     else if( control == IOBUFCTRL_FLUSH ) {
-       size_t avail, n;
-
-       assert( !a->partial );
-       for(p=buf; !rc && size; ) {
-           n = size;
-           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;
+       if( a->partial ) { /* the complicated openpgp scheme */
+           size_t blen, n, nbytes = size + a->buflen;
+
+           assert( a->buflen <= OP_MIN_PARTIAL_CHUNK );
+           if( nbytes < OP_MIN_PARTIAL_CHUNK ) {
+               /* not enough to write a partial block out , so we store it*/
+               if( !a->buffer )
+                   a->buffer = m_alloc( OP_MIN_PARTIAL_CHUNK );
+               memcpy( a->buffer + a->buflen, buf, size );
+               a->buflen += size;
+           }
+           else { /* okay, we can write out something */
+               /* do this in a loop to use the most efficient block lengths */
+               p = buf;
+               do {
+                   /* find the best matching block length - this is limited
+                    * by the size of the internal buffering */
+                   for( blen=OP_MIN_PARTIAL_CHUNK*2,
+                           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;
                }
-               else {
-                   iobuf_put( chain, (n >> 8) & 0xff );
-                   iobuf_put( chain, n & 0xff );
-                   avail = n;
-                   a->count = a->size - n;
+           }
+       }
+       else { /* the gnupg scheme */
+           size_t avail, n;
+
+           for(p=buf; !rc && size; ) {
+               n = size;
+               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;
            }
-           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 ) {
@@ -259,6 +339,8 @@ block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
        else
            a->count = a->size; /* force first length bytes */
        a->eof = 0;
+       a->buffer = NULL;
+       a->buflen = 0;
     }
     else if( control == IOBUFCTRL_DESC ) {
        *(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 ) {
        if( a->usage == 2 ) { /* write the end markers */
            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 {
                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.
- * LEN is the first length
+ * LEN is the first length byte on read, but ignored on writes.
  */
 void
 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 {
        ctx->partial = 1;
-       ctx->size = len;
+       ctx->size = 0;
+       ctx->first_c = len;
        iobuf_push_filter(a, block_filter, ctx );
     }
 }