diff --git a/TODO b/TODO index 3e39c0886..7eea85eeb 100644 --- a/TODO +++ b/TODO @@ -49,3 +49,5 @@ * add multi-user-id-sigs handling to import.c + * add tag 3 packet support to "-c" + diff --git a/g10/ChangeLog b/g10/ChangeLog index 2402a59c1..b4a74ab72 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -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. diff --git a/g10/build-packet.c b/g10/build-packet.c index 8d897ca88..384957515 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -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 @@ -314,6 +319,37 @@ do_secret_cert( IOBUF out, int ctb, PKT_secret_cert *skc ) return rc; } +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 ) { @@ -348,7 +384,6 @@ do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ) - static u32 calc_plaintext( PKT_plaintext *pt ) { diff --git a/g10/free-packet.c b/g10/free-packet.c index 09971c4cf..d998ce29d 100644 --- a/g10/free-packet.c +++ b/g10/free-packet.c @@ -31,6 +31,11 @@ #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; diff --git a/g10/keydb.h b/g10/keydb.h index d1a7e4571..96dc652df 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -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 ); diff --git a/g10/keyedit.c b/g10/keyedit.c index 634baa1c6..37824d84d 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -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); } diff --git a/g10/keygen.c b/g10/keygen.c index a4addfc25..1d3f9004e 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -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); } diff --git a/g10/mainproc.c b/g10/mainproc.c index 22af3561d..7e0ba18b7 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -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. */ @@ -145,13 +145,48 @@ 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; diff --git a/g10/packet.h b/g10/packet.h index 2393964c2..fb8ac20d8 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -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 */ @@ -54,6 +54,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; @@ -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 ); diff --git a/g10/parse-packet.c b/g10/parse-packet.c index eb56b09ae..f7913d3f9 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -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; diff --git a/g10/passphrase.c b/g10/passphrase.c index 46ff83163..5ae3966ac 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -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); + 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 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); - } - 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); } diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index d95d12380..340551cb2 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -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 ); diff --git a/zlib/Makefile b/zlib/Makefile index 404a76d02..a060f7842 100644 --- a/zlib/Makefile +++ b/zlib/Makefile @@ -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 =