Aenderungen in der Eifel
authorWerner Koch <wk@gnupg.org>
Sun, 3 May 1998 15:42:08 +0000 (15:42 +0000)
committerWerner Koch <wk@gnupg.org>
Sun, 3 May 1998 15:42:08 +0000 (15:42 +0000)
13 files changed:
TODO
g10/ChangeLog
g10/build-packet.c
g10/free-packet.c
g10/keydb.h
g10/keyedit.c
g10/keygen.c
g10/mainproc.c
g10/packet.h
g10/parse-packet.c
g10/passphrase.c
g10/seckey-cert.c
zlib/Makefile

diff --git a/TODO b/TODO
index 3e39c08..7eea85e 100644 (file)
--- a/TODO
+++ b/TODO
@@ -49,3 +49,5 @@
 
     * add multi-user-id-sigs handling to import.c
 
+    * add tag 3 packet support to "-c"
+
index 2402a59..b4a74ab 100644 (file)
@@ -1,3 +1,14 @@
+Fri May  1 12:44:39 1998  Werner Koch,mobil,,, (wk@tobold)
+
+       * packet.h (count): Chnaged s2k count from byte to u32.
+       * seckey-cert.c (do_check): Changed s2k algo 3 to 4, changed
+       reading of count.
+       * build-packet.c (do_secret_cert): ditto.
+       * parse-packet.c (parse_certificate): ditto.
+
+       * parse-packet.c (parse_symkeyenc): New.
+       * build-packet.c (do_symkey_enc): New.
+
 Thu Apr 30 16:33:34 1998  Werner Koch  (wk@isil.d.shuttle.de)
 
        * sign.c (clearsign_file): Fixed "Hash: " armor line.
index 8d897ca..3849575 100644 (file)
@@ -38,6 +38,7 @@ static int do_comment( IOBUF out, int ctb, PKT_comment *rem );
 static int do_user_id( IOBUF out, int ctb, PKT_user_id *uid );
 static int do_public_cert( IOBUF out, int ctb, PKT_public_cert *pk );
 static int do_secret_cert( IOBUF out, int ctb, PKT_secret_cert *pk );
+static int do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc );
 static int do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc );
 static u32 calc_plaintext( PKT_plaintext *pt );
 static int do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt );
@@ -85,6 +86,9 @@ build_packet( IOBUF out, PACKET *pkt )
       case PKT_SECRET_CERT:
        rc = do_secret_cert( out, ctb, pkt->pkt.secret_cert );
        break;
+      case PKT_SYMKEY_ENC:
+       rc = do_symkey_enc( out, ctb, pkt->pkt.symkey_enc );
+       break;
       case PKT_PUBKEY_ENC:
        rc = do_pubkey_enc( out, ctb, pkt->pkt.pubkey_enc );
        break;
@@ -129,6 +133,7 @@ calc_packet_length( PACKET *pkt )
       case PKT_COMMENT:
       case PKT_PUBLIC_CERT:
       case PKT_SECRET_CERT:
+      case PKT_SYMKEY_ENC:
       case PKT_PUBKEY_ENC:
       case PKT_ENCRYPTED:
       case PKT_SIGNATURE:
@@ -270,13 +275,13 @@ do_secret_cert( IOBUF out, int ctb, PKT_secret_cert *skc )
        if( skc->is_protected ) {
            iobuf_put(a, 0xff );
            iobuf_put(a, skc->protect.algo );
-           iobuf_put(a, skc->protect.s2k );
-           iobuf_put(a, skc->protect.hash );
-           if( skc->protect.s2k == 1
-               || skc->protect.s2k == 3 )
-               iobuf_write(a, skc->protect.salt, 8 );
-           if( skc->protect.s2k == 3 )
-               iobuf_put(a, skc->protect.count );
+           iobuf_put(a, skc->protect.s2k.mode );
+           iobuf_put(a, skc->protect.s2k.hash_algo );
+           if( skc->protect.s2k.mode == 1
+               || skc->protect.s2k.mode == 4 )
+               iobuf_write(a, skc->protect.s2k.salt, 8 );
+           if( skc->protect.s2k.mode == 4 )
+               write_32(a, skc->protect.s2k.count );
            iobuf_write(a, skc->protect.iv, 8 );
        }
        else
@@ -315,6 +320,37 @@ do_secret_cert( IOBUF out, int ctb, PKT_secret_cert *skc )
 }
 
 static int
+do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc )
+{
+    int rc = 0;
+    IOBUF a = iobuf_temp();
+
+    assert( enc->version == 4 );
+    switch( enc->s2k.mode ) {
+      case 0: case 1: case 4: break;
+      default: log_bug("do_symkey_enc: s2k=%d\n", enc->s2k.mode );
+    }
+    iobuf_put( a, enc->version );
+    iobuf_put( a, enc->cipher_algo );
+    iobuf_put( a, enc->s2k.mode );
+    iobuf_put( a, enc->s2k.hash_algo );
+    if( enc->s2k.mode == 1 || enc->s2k.mode == 4 ) {
+       iobuf_write(a, enc->s2k.salt, 8 );
+       if( enc->s2k.mode == 4 )
+           write_32(a, enc->s2k.count);
+    }
+    if( enc->seskeylen )
+       iobuf_write(a, enc->seskey, enc->seskeylen );
+
+    write_header(out, ctb, iobuf_get_temp_length(a) );
+    if( iobuf_write_temp( out, a ) )
+       rc = G10ERR_WRITE_FILE;
+
+    iobuf_close(a);
+    return rc;
+}
+
+static int
 do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc )
 {
     int rc = 0;
@@ -348,7 +384,6 @@ do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc )
 
 
 
-
 static u32
 calc_plaintext( PKT_plaintext *pt )
 {
index 09971c4..d998ce2 100644 (file)
 #include "cipher.h"
 #include "memory.h"
 
+void
+free_symkey_enc( PKT_symkey_enc *enc )
+{
+    m_free(enc);
+}
 
 void
 free_pubkey_enc( PKT_pubkey_enc *enc )
@@ -277,6 +282,9 @@ free_packet( PACKET *pkt )
       case PKT_PUBKEY_ENC:
        free_pubkey_enc( pkt->pkt.pubkey_enc );
        break;
+      case PKT_SYMKEY_ENC:
+       free_symkey_enc( pkt->pkt.symkey_enc );
+       break;
       case PKT_PUBLIC_CERT:
        free_public_cert( pkt->pkt.public_cert );
        break;
index d1a7e45..96dc652 100644 (file)
@@ -97,8 +97,8 @@ int  build_skc_list( STRLIST locusr, SKC_LIST *ret_skc_list,
 /*-- passphrase.h --*/
 void set_passphrase_fd( int fd );
 int  get_passphrase_fd(void);
-DEK *get_passphrase_hash( u32 *keyid, char *text, byte *salt );
-int make_dek_from_passphrase( DEK *dek, int mode, byte *salt );
+DEK *get_passphrase_hash( u32 *keyid, char *text, STRING2KEY *s2k );
+int make_dek_from_passphrase( DEK *dek, int mode, STRING2KEY *s2k );
 
 /*-- getkey.c --*/
 void add_keyring( const char *name );
index 634baa1..37824d8 100644 (file)
@@ -624,15 +624,16 @@ change_passphrase( const char *username )
     if( rc )
        tty_printf("Can't edit this key: %s\n", g10_errstr(rc));
     else {
-       DEK *dek = m_alloc_secure( sizeof *dek + 8 );
-       byte *salt = (byte*)dek + sizeof( *dek );
+       DEK *dek = m_alloc_secure( sizeof *dek );
+       STRING2KEY *s2k = m_alloc_secure( sizeof *s2k );
 
        tty_printf( "Enter the new passphrase for this secret key.\n\n" );
 
        for(;;) {
            dek->algo = CIPHER_ALGO_BLOWFISH;
-           randomize_buffer(salt, 8, 1);
-           rc = make_dek_from_passphrase( dek , 2, salt );
+           s2k->mode = 1;
+           s2k->hash_algo = DIGEST_ALGO_RMD160;
+           rc = make_dek_from_passphrase( dek , 2, s2k );
            if( rc == -1 ) {
                rc = 0;
                tty_printf( "You don't want a passphrase -"
@@ -653,11 +654,8 @@ change_passphrase( const char *username )
                break;
            }
            else { /* okay */
-               skc->protect.algo = CIPHER_ALGO_BLOWFISH;
-               skc->protect.s2k  = 1;
-               skc->protect.hash = DIGEST_ALGO_RMD160;
-               memcpy(skc->protect.salt, salt, 8);
-               randomize_buffer(skc->protect.iv, 8, 1);
+               skc->protect.algo = dek->algo;
+               skc->protect.s2k = *s2k;
                rc = protect_secret_key( skc, dek );
                if( rc )
                    log_error("protect_secret_key failed: %s\n", g10_errstr(rc) );
@@ -666,6 +664,7 @@ change_passphrase( const char *username )
                break;
            }
        }
+       m_free(s2k);
        m_free(dek);
     }
 
index a4addfc..1d3f900 100644 (file)
@@ -95,7 +95,7 @@ write_selfsig( KBNODE root, KBNODE pub_root, PKT_secret_cert *skc )
 
 static int
 gen_elg(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
-       byte *salt, PKT_secret_cert **ret_skc, u16 valid_days )
+       STRING2KEY *s2k, PKT_secret_cert **ret_skc, u16 valid_days )
 {
     int rc;
     int i;
@@ -128,11 +128,8 @@ gen_elg(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
     *ret_skc = copy_secret_cert( NULL, skc );
 
     if( dek ) {
-       skc->protect.algo = CIPHER_ALGO_BLOWFISH;
-       skc->protect.s2k  = 1;
-       skc->protect.hash = DIGEST_ALGO_RMD160;
-       memcpy(skc->protect.salt, salt, 8);
-       randomize_buffer(skc->protect.iv, 8, 1);
+       skc->protect.algo = dek->algo;
+       skc->protect.s2k = *s2k;
        rc = protect_secret_key( skc, dek );
        if( rc ) {
            log_error("protect_secret_key failed: %s\n", g10_errstr(rc) );
@@ -148,7 +145,7 @@ gen_elg(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
     add_kbnode(pub_root, new_kbnode( pkt ));
 
     /* don't know whether it makes sense to have the factors, so for now
-     * we store them in the secret keyring (but they are secret) */
+     * we store them in the secret keyring (but they are not secret) */
     pkt = m_alloc_clear(sizeof *pkt);
     pkt->pkttype = PKT_SECRET_CERT;
     pkt->pkt.secret_cert = skc;
@@ -165,7 +162,7 @@ gen_elg(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
 #ifdef ENABLE_RSA_KEYGEN
 static int
 gen_rsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
-       byte *salt, PKT_secret_cert **ret_skc, u16 valid_days )
+       STRING2KEY *s2k, PKT_secret_cert **ret_skc, u16 valid_days )
 {
     int rc;
     PACKET *pkt;
@@ -229,7 +226,7 @@ gen_rsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
 
 static int
 gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
-        byte *salt, PKT_secret_cert **ret_skc, u16 valid_days )
+        STRING2KEY *s2k, PKT_secret_cert **ret_skc, u16 valid_days )
 {
     return G10ERR_GENERAL;
 }
@@ -279,7 +276,7 @@ generate_keypair()
     KBNODE sec_root = NULL;
     PKT_secret_cert *skc = NULL;
     DEK *dek = NULL;
-    byte *salt;
+    STRING2KEY *s2k;
     int rc;
     int algo;
     const char *algo_name;
@@ -530,14 +527,16 @@ generate_keypair()
 
     tty_printf(_("You need a Passphrase to protect your secret key.\n\n") );
 
-    dek = m_alloc_secure( sizeof *dek + 8 );
-    salt = (byte*)dek + sizeof *dek;
+    dek = m_alloc_secure( sizeof *dek );
+    s2k = m_alloc_secure( sizeof *s2k );
     for(;;) {
        dek->algo = CIPHER_ALGO_BLOWFISH;
-       randomize_buffer(salt, 8, 1);
-       rc = make_dek_from_passphrase( dek , 2, salt );
+       s2k->mode = 1;
+       s2k->hash_algo = DIGESTA_ALGO_RMD160;
+       rc = make_dek_from_passphrase( dek , 2, s2k );
        if( rc == -1 ) {
            m_free(dek); dek = NULL;
+           m_free(s2k); s2k = NULL;
            tty_printf(_(
            "You don't want a passphrase - this is probably a *bad* idea!\n"
            "I will do it anyway.  You can change your passphrase at any time,\n"
@@ -549,6 +548,7 @@ generate_keypair()
        }
        else if( rc ) {
            m_free(dek); dek = NULL;
+           m_free(s2k); s2k = NULL;
            m_free(uid);
            log_error("Error getting the passphrase: %s\n", g10_errstr(rc) );
            return;
@@ -581,13 +581,13 @@ generate_keypair()
 "number generator a better chance to gain enough entropy.\n") );
 
     if( algo == PUBKEY_ALGO_ELGAMAL )
-       rc = gen_elg(nbits, pub_root, sec_root, dek, salt,  &skc, valid_days );
+       rc = gen_elg(nbits, pub_root, sec_root, dek, s2k,  &skc, valid_days );
   #ifdef ENABLE_RSA_KEYGEN
     else if( algo == PUBKEY_ALGO_RSA )
-       rc = gen_rsa(nbits, pub_root, sec_root, dek, salt, &skc, valid_days  );
+       rc = gen_rsa(nbits, pub_root, sec_root, dek, s2k, &skc, valid_days  );
   #endif
     else if( algo == PUBKEY_ALGO_DSA )
-       rc = gen_dsa(nbits, pub_root, sec_root, dek, salt, &skc, valid_days  );
+       rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, &skc, valid_days  );
     else
        BUG();
     if( !rc ) {
@@ -667,6 +667,7 @@ generate_keypair()
        free_secret_cert(skc);
     m_free(uid);
     m_free(dek);
+    m_free(s2k);
     m_free(pub_fname);
     m_free(sec_fname);
 }
index 22af356..7e0ba18 100644 (file)
@@ -50,7 +50,7 @@ typedef struct {
     int encrypt_only; /* process only encrytion messages */
     STRLIST signed_data;
     DEK *dek;
-    int last_was_pubkey_enc;
+    int last_was_session_key;
     KBNODE list;   /* the current list of packets */
     int have_data;
     IOBUF iobuf;    /* used to get the filename etc. */
@@ -146,12 +146,47 @@ add_signature( CTX c, PACKET *pkt )
 
 
 static void
+proc_symkey_enc( CTX c, PACKET *pkt )
+{
+   /* FIXME:   NOT READY */
+   #if 0
+    PKT_symkey_enc *enc;
+    int result = 0;
+
+    c->last_was_session_key = 1;
+    enc = pkt->pkt.symkey_enc;
+    if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL
+       || enc->pubkey_algo == PUBKEY_ALGO_DSA
+       || enc->pubkey_algo == PUBKEY_ALGO_RSA  ) {
+       m_free(c->dek ); /* paranoid: delete a pending DEK */
+       c->dek = m_alloc_secure( sizeof *c->dek );
+       if( (result = get_session_key( enc, c->dek )) ) {
+           /* error: delete the DEK */
+           m_free(c->dek); c->dek = NULL;
+       }
+    }
+    else
+       result = G10ERR_PUBKEY_ALGO;
+
+    if( result == -1 )
+       ;
+    else if( !result ) {
+       if( opt.verbose > 1 )
+           log_info( "pubkey_enc packet: Good DEK\n" );
+    }
+    else
+       log_error( "pubkey_enc packet: %s\n", g10_errstr(result));
+    free_packet(pkt);
+  #endif
+}
+
+static void
 proc_pubkey_enc( CTX c, PACKET *pkt )
 {
     PKT_pubkey_enc *enc;
     int result = 0;
 
-    c->last_was_pubkey_enc = 1;
+    c->last_was_session_key = 1;
     enc = pkt->pkt.pubkey_enc;
     /*printf("enc: encrypted by a pubkey with keyid %08lX\n", enc->keyid[1] );*/
     if( enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL
@@ -179,15 +214,14 @@ proc_pubkey_enc( CTX c, PACKET *pkt )
 }
 
 
-
 static void
 proc_encrypted( CTX c, PACKET *pkt )
 {
     int result = 0;
 
     /*printf("dat: %sencrypted data\n", c->dek?"":"conventional ");*/
-    if( !c->dek && !c->last_was_pubkey_enc ) {
-       /* assume this is conventional encrypted data */
+    if( !c->dek && !c->last_was_session_key ) {
+       /* assume this is old conventional encrypted data */
        c->dek = m_alloc_secure( sizeof *c->dek );
        c->dek->algo = opt.def_cipher_algo;
        result = make_dek_from_passphrase( c->dek, 0, NULL );
@@ -207,7 +241,7 @@ proc_encrypted( CTX c, PACKET *pkt )
        log_error("encryption failed: %s\n", g10_errstr(result));
     }
     free_packet(pkt);
-    c->last_was_pubkey_enc = 0;
+    c->last_was_session_key = 0;
 }
 
 
@@ -232,7 +266,7 @@ proc_plaintext( CTX c, PACKET *pkt )
     if( rc )
        log_error( "handle plaintext failed: %s\n", g10_errstr(rc));
     free_packet(pkt);
-    c->last_was_pubkey_enc = 0;
+    c->last_was_session_key = 0;
 }
 
 
@@ -264,7 +298,7 @@ proc_compressed( CTX c, PACKET *pkt )
     if( rc )
        log_error("uncompressing failed: %s\n", g10_errstr(rc));
     free_packet(pkt);
-    c->last_was_pubkey_enc = 0;
+    c->last_was_session_key = 0;
 }
 
 
@@ -606,6 +640,7 @@ do_proc_packets( CTX c, IOBUF a )
              case PKT_PUBLIC_CERT:
              case PKT_SECRET_CERT:
              case PKT_USER_ID:
+             case PKT_SYMKEY_ENC:
              case PKT_PUBKEY_ENC:
              case PKT_ENCRYPTED:
                rc = G10ERR_UNEXPECTED;
@@ -625,6 +660,7 @@ do_proc_packets( CTX c, IOBUF a )
                rc = G10ERR_UNEXPECTED;
                goto leave;
              case PKT_SIGNATURE:   newpkt = add_signature( c, pkt ); break;
+             case PKT_SYMKEY_ENC:  proc_symkey_enc( c, pkt ); break;
              case PKT_PUBKEY_ENC:  proc_pubkey_enc( c, pkt ); break;
              case PKT_ENCRYPTED:   proc_encrypted( c, pkt ); break;
              case PKT_PLAINTEXT:   proc_plaintext( c, pkt ); break;
@@ -648,6 +684,7 @@ do_proc_packets( CTX c, IOBUF a )
              case PKT_USER_ID:     newpkt = add_user_id( c, pkt ); break;
              case PKT_SIGNATURE:   newpkt = add_signature( c, pkt ); break;
              case PKT_PUBKEY_ENC:  proc_pubkey_enc( c, pkt ); break;
+             case PKT_SYMKEY_ENC:  proc_symkey_enc( c, pkt ); break;
              case PKT_ENCRYPTED:   proc_encrypted( c, pkt ); break;
              case PKT_PLAINTEXT:   proc_plaintext( c, pkt ); break;
              case PKT_COMPRESSED:  proc_compressed( c, pkt ); break;
index 2393964..fb8ac20 100644 (file)
@@ -37,7 +37,7 @@ typedef enum {
        PKT_NONE           =0,
        PKT_PUBKEY_ENC     =1, /* public key encrypted packet */
        PKT_SIGNATURE      =2, /* secret key encrypted packet */
-       PKT_SESSION_KEY    =3, /* session key packet (OpenPGP)*/
+       PKT_SYMKEY_ENC     =3, /* session key packet (OpenPGP)*/
        PKT_ONEPASS_SIG    =4, /* one pass sig packet (OpenPGP)*/
        PKT_SECRET_CERT    =5, /* secret key certificate */
        PKT_PUBLIC_CERT    =6, /* public key certificate */
@@ -55,6 +55,21 @@ typedef enum {
 typedef struct packet_struct PACKET;
 
 typedef struct {
+    byte mode;
+    byte hash_algo;
+    byte salt[8];
+    u32  count;
+} STRING2KEY;
+
+typedef struct {
+    byte version;
+    byte cipher_algo;   /* cipher algorithm used */
+    STRING2KEY s2k;
+    byte seskeylen;   /* keylength in byte or 0 for no seskey */
+    byte seskey[1];
+} PKT_symkey_enc;
+
+typedef struct {
     u32     keyid[2];      /* 64 bit keyid */
     byte    version;
     byte    pubkey_algo;    /* algorithm used for public key scheme */
@@ -130,10 +145,7 @@ typedef struct {
                        /* and should never be passed to a mpi_xxx() */
     struct {
        byte algo;  /* cipher used to protect the secret information*/
-       byte s2k;
-       byte hash;
-       byte salt[8];
-       byte count;
+       STRING2KEY s2k;
        byte iv[8]; /* initialization vector for CFB mode */
     } protect;
     union {
@@ -180,6 +192,7 @@ struct packet_struct {
     pkttype_t pkttype;
     union {
        void *generic;
+       PKT_symkey_enc  *symkey_enc;    /* PKT_SYMKEY_ENC */
        PKT_pubkey_enc  *pubkey_enc;    /* PKT_PUBKEY_ENC */
        PKT_onepass_sig *onepass_sig;   /* PKT_ONEPASS_SIG */
        PKT_signature   *signature;     /* PKT_SIGNATURE */
@@ -217,6 +230,7 @@ u32 calc_packet_length( PACKET *pkt );
 void hash_public_cert( MD_HANDLE md, PKT_public_cert *pkc );
 
 /*-- free-packet.c --*/
+void free_symkey_enc( PKT_symkey_enc *enc );
 void free_pubkey_enc( PKT_pubkey_enc *enc );
 void free_seckey_enc( PKT_signature *enc );
 int  digest_algo_from_sig( PKT_signature *sig );
index eb56b09..f7913d3 100644 (file)
@@ -42,7 +42,9 @@ 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 int  parse_publickey( IOBUF inp, int pkttype, unsigned long 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 );
@@ -284,8 +286,11 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos,
        pkt->pkt.secret_cert = m_alloc_clear(sizeof *pkt->pkt.secret_cert );
        rc = parse_certificate(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_publickey(inp, pkttype, pktlen, pkt );
+       rc = parse_pubkeyenc(inp, pkttype, pktlen, pkt );
        break;
       case PKT_SIGNATURE:
        pkt->pkt.signature = m_alloc_clear(sizeof *pkt->pkt.signature );
@@ -407,7 +412,83 @@ skip_rest( IOBUF inp, unsigned long pktlen )
 
 
 static int
-parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
+parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
+{
+    PKT_symkey_enc *k;
+    int i, version, s2kmode, cipher_algo, hash_algo, seskeylen, minlen;
+
+    if( pktlen < 4 ) {
+       log_error("packet(%d) too short\n", pkttype);
+       goto leave;
+    }
+    version = iobuf_get_noeof(inp); pktlen--;
+    if( k->version != 4 ) {
+       log_error("packet(%d) with unknown version %d\n", pkttype, version);
+       goto leave;
+    }
+    if( pktlen > 200 ) { /* (we encode the seskeylen in a byte) */
+       log_error("packet(%d) too large\n", pkttype);
+       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 4:  /* iterated+salted s2k */
+       minlen = 12;
+       break;
+      default:
+       log_error("unknown S2K %d\n", s2kmode );
+       goto leave;
+    }
+    if( minlen > pktlen ) {
+       log_error("packet with S2K %d too short\n", s2kmode );
+       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 == 4 ) {
+       for(i=0; i < 8 && pktlen; i++, pktlen-- )
+           k->s2k.salt[i] = iobuf_get_noeof(inp);
+    }
+    if( s2kmode == 4 ) {
+       k->s2k.count = read_32(inp); pktlen -= 4;
+    }
+    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 == 4 ) {
+           printf("\tsalt ");
+           for(i=0; i < 8; i++ )
+               printf("%02x", k->s2k.salt[i]);
+           if( s2kmode == 4 )
+               printf(", count %lu\n", (ulong)k->s2k.count );
+       }
+    }
+
+  leave:
+    skip_rest(inp, pktlen);
+    return 0;
+}
+
+static int
+parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
 {
     unsigned n;
     PKT_pubkey_enc *k;
@@ -426,7 +507,7 @@ parse_publickey( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
     k->keyid[1] = read_32(inp); pktlen -= 4;
     k->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
     if( list_mode )
-       printf(":public key encoded packet: version %d, keyid %08lX%08lX\n",
+       printf(":pubkey enc packet: version %d, keyid %08lX%08lX\n",
                            k->version, (ulong)k->keyid[0], (ulong)k->keyid[1]);
     if( k->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) {
        n = pktlen;
@@ -845,34 +926,34 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
            cert->protect.algo = iobuf_get_noeof(inp); pktlen--;
            if( cert->protect.algo ) {
                cert->is_protected = 1;
-               cert->protect.count = 0;
+               cert->protect.s2k.count = 0;
                if( cert->protect.algo == 255 ) {
                    if( pktlen < 3 ) {
                        rc = G10ERR_INVALID_PACKET;
                        goto leave;
                    }
                    cert->protect.algo = iobuf_get_noeof(inp); pktlen--;
-                   cert->protect.s2k  = iobuf_get_noeof(inp); pktlen--;
-                   cert->protect.hash = iobuf_get_noeof(inp); pktlen--;
-                   switch( cert->protect.s2k ) {
+                   cert->protect.s2k.mode  = iobuf_get_noeof(inp); pktlen--;
+                   cert->protect.s2k.hash_algo = iobuf_get_noeof(inp); pktlen--;
+                   switch( cert->protect.s2k.mode ) {
                      case 1:
-                     case 3:
+                     case 4:
                        for(i=0; i < 8 && pktlen; i++, pktlen-- )
                            temp[i] = iobuf_get_noeof(inp);
-                       memcpy(cert->protect.salt, temp, 8 );
+                       memcpy(cert->protect.s2k.salt, temp, 8 );
                        break;
                    }
-                   switch( cert->protect.s2k ) {
+                   switch( cert->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" );
+                     case 4: if( list_mode ) printf(  "\titer+salt S2K" );
                        break;
                      default:
                        if( list_mode )
                            printf(  "\tunknown S2K %d\n",
-                                               cert->protect.s2k );
+                                               cert->protect.s2k.mode );
                        rc = G10ERR_INVALID_PACKET;
                        goto leave;
                    }
@@ -880,23 +961,23 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
                    if( list_mode ) {
                        printf(", algo: %d, hash: %d",
                                         cert->protect.algo,
-                                        cert->protect.hash );
-                       if( cert->protect.s2k == 1
-                           || cert->protect.s2k == 3 ) {
+                                        cert->protect.s2k.hash_algo );
+                       if( cert->protect.s2k.mode == 1
+                           || cert->protect.s2k.mode == 4 ) {
                            printf(", salt: ");
                            for(i=0; i < 8; i++ )
-                               printf("%02x", cert->protect.salt[i]);
+                               printf("%02x", cert->protect.s2k.salt[i]);
                        }
                        putchar('\n');
                    }
 
-                   if( cert->protect.s2k == 3 ) {
-                       if( !pktlen ) {
+                   if( cert->protect.s2k.mode == 4 ) {
+                       if( pktlen < 4 ) {
                            rc = G10ERR_INVALID_PACKET;
                            goto leave;
                        }
-                       cert->protect.count = iobuf_get_noeof(inp);
-                       pktlen--;
+                       cert->protect.s2k.count = read_32(inp);
+                       pktlen -= 4;
                    }
 
                }
@@ -905,9 +986,9 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
                        printf(  "\tprotect algo: %d\n",
                                                cert->protect.algo);
                    /* old version, we don't have a S2K, so we fake one */
-                   cert->protect.s2k = 0;
+                   cert->protect.s2k.mode = 0;
                    /* We need this kludge to cope with old GNUPG versions */
-                   cert->protect.hash =
+                   cert->protect.s2k.hash_algo =
                         cert->protect.algo == CIPHER_ALGO_BLOWFISH160?
                                      DIGEST_ALGO_RMD160 : DIGEST_ALGO_MD5;
                }
@@ -981,33 +1062,34 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
            cert->protect.algo = iobuf_get_noeof(inp); pktlen--;
            if( cert->protect.algo ) {
                cert->is_protected = 1;
-               cert->protect.count = 0;
+               cert->protect.s2k.count = 0;
                if( cert->protect.algo == 255 ) {
                    if( pktlen < 3 ) {
                        rc = G10ERR_INVALID_PACKET;
                        goto leave;
                    }
                    cert->protect.algo = iobuf_get_noeof(inp); pktlen--;
-                   cert->protect.s2k  = iobuf_get_noeof(inp); pktlen--;
-                   cert->protect.hash = iobuf_get_noeof(inp); pktlen--;
-                   switch( cert->protect.s2k ) {
+                   cert->protect.s2k.mode  = iobuf_get_noeof(inp); pktlen--;
+                   cert->protect.s2k.hash_algo = iobuf_get_noeof(inp); pktlen--;
+                   switch( cert->protect.s2k.mode ) {
                      case 1:
-                     case 3:
+                     case 4:
                        for(i=0; i < 8 && pktlen; i++, pktlen-- )
                            temp[i] = iobuf_get_noeof(inp);
-                       memcpy(cert->protect.salt, temp, 8 );
+                       memcpy(cert->protect.s2k.salt, temp, 8 );
                        break;
                    }
-                   switch( cert->protect.s2k ) {
+                   switch( cert->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" );
+                     case 4: if( list_mode ) printf(  "\titer+salt S2K" );
                        break;
                      default:
                        if( list_mode )
-                           printf(  "\tunknown S2K %d\n", cert->protect.s2k );
+                           printf(  "\tunknown S2K %d\n",
+                                                   cert->protect.s2k.mode );
                        rc = G10ERR_INVALID_PACKET;
                        goto leave;
                    }
@@ -1015,22 +1097,23 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
                    if( list_mode ) {
                        printf(", algo: %d, hash: %d",
                                         cert->protect.algo,
-                                        cert->protect.hash );
-                       if( cert->protect.s2k == 1 || cert->protect.s2k == 3 ){
+                                        cert->protect.s2k.hash_algo );
+                       if( cert->protect.s2k.mode == 1
+                           || cert->protect.s2k.mode == 4 ){
                            printf(", salt: ");
                            for(i=0; i < 8; i++ )
-                               printf("%02x", cert->protect.salt[i]);
+                               printf("%02x", cert->protect.s2k.salt[i]);
                        }
                        putchar('\n');
                    }
 
-                   if( cert->protect.s2k == 3 ) {
-                       if( !pktlen ) {
+                   if( cert->protect.s2k.mode == 4 ) {
+                       if( pktlen < 4 ) {
                            rc = G10ERR_INVALID_PACKET;
                            goto leave;
                        }
-                       cert->protect.count = iobuf_get_noeof(inp);
-                       pktlen--;
+                       cert->protect.s2k.count = read_32(inp);
+                       pktlen -= 4;
                    }
 
                }
@@ -1038,8 +1121,8 @@ parse_certificate( IOBUF inp, int pkttype, unsigned long pktlen,
                    if( list_mode )
                        printf(  "\tprotect algo: %d\n", cert->protect.algo);
                    /* old version, we don't have a S2K, so we fake one */
-                   cert->protect.s2k = 0;
-                   cert->protect.hash = DIGEST_ALGO_MD5;
+                   cert->protect.s2k.mode = 0;
+                   cert->protect.s2k.hash_algo = DIGEST_ALGO_MD5;
                }
                if( pktlen < 8 ) {
                    rc = G10ERR_INVALID_PACKET;
index 46ff831..5ae3966 100644 (file)
@@ -33,7 +33,7 @@
 
 static int pwfd = -1;
 
-static int hash_passphrase( DEK *dek, char *pw, byte *salt );
+static void hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k );
 
 void
 set_passphrase_fd( int fd )
@@ -107,12 +107,11 @@ get_passphrase_hash( u32 *keyid, char *text, byte *salt )
 
 /****************
  * This function is used to construct a DEK from a user input.
- * It uses the default CIPHER. If salt is != NULL, include these
- * 8 bytes in the hash.
+ * It uses the default CIPHER.
  * Returns: 0 = okay, -1 No passphrase entered, > 0 error
  */
 int
-make_dek_from_passphrase( DEK *dek, int mode, byte *salt )
+make_dek_from_passphrase( DEK *dek, int mode, STRING2KEY *s2k )
 {
     char *pw, *pw2;
     int rc=0;
@@ -132,45 +131,36 @@ make_dek_from_passphrase( DEK *dek, int mode, byte *salt )
     if( !*pw )
        rc = -1;
     else
-       rc = hash_passphrase( dek, pw, salt );
+       hash_passphrase( dek, pw, s2k, mode==2 );
     m_free(pw);
     return rc;
 }
 
 
-static int
-hash_passphrase( DEK *dek, char *pw, byte *salt )
+/****************
+ * Hash a passphrase using the supplied s2k. If create is true, create
+ * a new salt or whatelse must be filled into the s2k for a new key.
+ * always needs: dek->algo, s2k->mode, s2k->hash_algo.
+ */
+static void
+hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create )
 {
+    MD_HANDLE md;
     int rc = 0;
 
+    assert( s2k->hash_algo );
     dek->keylen = 0;
-    if( dek->algo == CIPHER_ALGO_BLOWFISH ) {
-       MD_HANDLE md;
-
-       md = md_open(DIGEST_ALGO_RMD160, 1);
-       if( salt )
-           md_write( md, salt, 8 );
-       md_write( md, pw, strlen(pw) );
-       md_final( md );
-       dek->keylen = 20;
-       memcpy( dek->key, md_read(md,0), dek->keylen );
-       md_close(md);
-    }
-    else if( dek->algo == CIPHER_ALGO_CAST ) {
-       MD_HANDLE md;
-
-       md = md_open(DIGEST_ALGO_SHA1, 1);
-       if( salt )
-           md_write( md, salt, 8 );
-       md_write( md, pw, strlen(pw) );
-       md_final( md );
-       /* use only the low 128 bits */
-       dek->keylen = 16;
-       memcpy( dek->key, md_read(md,0), dek->keylen );
-       md_close(md);
+    md = md_open( s2k->hash_algo, 1);
+    if( s2k->mode == 1 || s2k->mode == 4 ) {
+       if( create )
+           randomize_buffer(&s2k->salt, 8, 1);
+       md_write( md, s2k->salt, 8 );
     }
-    else
-       rc = G10ERR_UNSUPPORTED;
-    return rc;
+    md_write( md, pw, strlen(pw) );
+    md_final( md );
+    dek->keylen = cipher_get_keylen( dek->algo );
+    assert(dek->keylen > 0 && dek->keylen < DIM(dek->key) );
+    memcpy( dek->key, md_read(md,0), dek->keylen );
+    md_close(md);
 }
 
index d95d123..340551c 100644 (file)
@@ -54,9 +54,9 @@ do_check( PKT_secret_cert *cert )
          case CIPHER_ALGO_BLOWFISH:
          case CIPHER_ALGO_CAST:
            keyid_from_skc( cert, keyid );
-           if( cert->protect.s2k == 1 || cert->protect.s2k == 3 )
+           if( cert->protect.s2k.mode == 1 || cert->protect.s2k.mode == 4 )
                dek = get_passphrase_hash( keyid, NULL,
-                                                cert->protect.salt );
+                                                cert->protect.s2k.salt );
            else
                dek = get_passphrase_hash( keyid, NULL, NULL );
 
index 404a76d..a060f78 100644 (file)
@@ -93,7 +93,7 @@ POSUB = po
 RANLIB = ranlib
 USE_INCLUDED_LIBINTL = yes
 USE_NLS = yes
-VERSION = 0.2.16
+VERSION = 0.2.16a
 ZLIBS = 
 l =