From 0d9ffec5efcafa9f6499a2c4e4e2784290faec2f Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 6 Jan 1998 21:01:36 +0000 Subject: Bug in blowfish behoben --- g10/build-packet.c | 14 +++--- g10/g10.c | 14 +++++- g10/getkey.c | 10 ++++- g10/keydb.h | 7 +-- g10/keygen.c | 12 +++--- g10/main.h | 1 + g10/packet.h | 1 + g10/ringedit.c | 39 ++++++++++++++--- g10/seckey-cert.c | 17 ++++++++ g10/sign.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 214 insertions(+), 24 deletions(-) (limited to 'g10') diff --git a/g10/build-packet.c b/g10/build-packet.c index 25d708ceb..6c526e346 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -230,12 +230,13 @@ do_secret_cert( IOBUF out, int ctb, PKT_secret_cert *skc ) mpi_write(a, skc->d.elg.p ); mpi_write(a, skc->d.elg.g ); mpi_write(a, skc->d.elg.y ); - iobuf_put(a, skc->d.elg.protect_algo ); - if( skc->d.elg.protect_algo ) { - assert( skc->d.elg.is_protected == 1 ); + if( skc->d.elg.is_protected ) { assert( skc->d.elg.protect_algo == CIPHER_ALGO_BLOWFISH ); + iobuf_put(a, skc->d.elg.protect_algo ); iobuf_write(a, skc->d.elg.protect.blowfish.iv, 8 ); } + else + iobuf_put(a, 0 ); mpi_write(a, skc->d.elg.x ); write_16(a, skc->d.elg.csum ); @@ -243,12 +244,13 @@ do_secret_cert( IOBUF out, int ctb, PKT_secret_cert *skc ) else if( skc->pubkey_algo == PUBKEY_ALGO_RSA ) { mpi_write(a, skc->d.rsa.rsa_n ); mpi_write(a, skc->d.rsa.rsa_e ); - iobuf_put(a, skc->d.rsa.protect_algo ); - if( skc->d.rsa.protect_algo ) { - assert( skc->d.rsa.is_protected == 1 ); + if( skc->d.rsa.is_protected ) { assert( skc->d.rsa.protect_algo == CIPHER_ALGO_BLOWFISH ); + iobuf_put(a, skc->d.rsa.protect_algo ); iobuf_write(a, skc->d.rsa.protect.blowfish.iv, 8 ); } + else + iobuf_put(a, 0 ); mpi_write(a, skc->d.rsa.rsa_d ); mpi_write(a, skc->d.rsa.rsa_p ); mpi_write(a, skc->d.rsa.rsa_q ); diff --git a/g10/g10.c b/g10/g10.c index cac8672ed..ac12d52db 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -38,7 +38,7 @@ enum cmd_values { aNull = 0, aSym, aStore, aEncr, aPrimegen, aKeygen, aSign, aSignEncr, aPrintMDs, aSignKey, aClearsig, aListPackets, aEditSig, - aKMode, aKModeC, + aKMode, aKModeC, aChangePass, aTest }; @@ -158,7 +158,6 @@ main( int argc, char **argv ) { 512, "cache-all" ,0, "hold everything in memory"}, { 513, "gen-prime" , 0, "\r" }, { 514, "test" , 0, "\r" }, - { 515, "change-passphrase", 0, "change the passphrase of your secret keyring"}, { 515, "fingerprint", 0, "show the fingerprints"}, { 516, "print-mds" , 0, "print all message digests"}, { 517, "secret-keyring" ,2, "add this secret keyring to the list" }, @@ -169,6 +168,7 @@ main( int argc, char **argv ) { 522, "no-greeting", 0, "\r" }, { 523, "passphrase-fd",1, "\r" }, { 524, "edit-sig" ,0, "edit a key signature" }, + { 525, "change-passphrase", 0, "change the passphrase of your secret keyring"}, {0} }; ARGPARSE_ARGS pargs; @@ -297,6 +297,7 @@ main( int argc, char **argv ) case 522: greeting = 0; break; case 523: set_passphrase_fd( pargs.r.ret_int ); break; case 524: set_cmd( &cmd, aEditSig); break; + case 525: set_cmd( &cmd, aChangePass); break; default : errors++; pargs.err = configfp? 1:2; break; } } @@ -406,6 +407,15 @@ main( int argc, char **argv ) log_error("edit_keysig('%s'): %s\n", fname_print, g10_errstr(rc) ); break; + case aChangePass: /* Chnage the passphrase */ + if( argc > 1 ) /* no arg: use default, 1 arg use this one */ + usage(1); + /* note: fname is the user id! */ + if( (rc = change_passphrase(fname)) ) + log_error("change_passphrase('%s'): %s\n", fname_print, + g10_errstr(rc) ); + break; + case aKMode: /* list keyring */ if( !argc ) { /* list the default public keyrings */ int i, seq=0; diff --git a/g10/getkey.c b/g10/getkey.c index 2195762f5..3ec6a6bf4 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -83,7 +83,7 @@ add_keyring( const char *name ) * combine it with the keyblock stuff from ringedit.c * For now we will simple add the filename as keyblock resource */ - rc = add_keyblock_resource( name, 0 ); + rc = add_keyblock_resource( name, 0, 0 ); if( rc ) log_error("keyblock resource '%s': %s\n", name, g10_errstr(rc) ); } @@ -115,6 +115,14 @@ add_secret_keyring( const char *name ) strcpy(sl->d, name ); sl->next = secret_keyrings; secret_keyrings = sl; + + /* FIXME: We should remove much out of this mpdule and + * combine it with the keyblock stuff from ringedit.c + * For now we will simple add the filename as keyblock resource + */ + rc = add_keyblock_resource( name, 0, 1 ); + if( rc ) + log_error("secret keyblock resource '%s': %s\n", name, g10_errstr(rc) ); } diff --git a/g10/keydb.h b/g10/keydb.h index f3a42caba..6770f866e 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -125,10 +125,11 @@ KBNODE walk_kbtree2( KBNODE root, KBNODE *context, int all ); void clear_kbnode_flags( KBNODE n ); /*-- ringedit.c --*/ -int add_keyblock_resource( const char *filename, int force ); -int get_keyblock_handle( const char *filename, KBPOS *kbpos ); -int search_keyblock( PACKET *pkt, KBPOS *kbpos ); +int add_keyblock_resource( const char *filename, int force, int secret ); +int get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos ); +int search_keyblock( PACKET *pkt, KBPOS *kbpos, int secret ); int search_keyblock_byname( KBPOS *kbpos, const char *username ); +int search_secret_keyblock_byname( KBPOS *kbpos, const char *username ); int lock_keyblock( KBPOS *kbpos ); void unlock_keyblock( KBPOS *kbpos ); int read_keyblock( KBPOS *kbpos, KBNODE *ret_root ); diff --git a/g10/keygen.c b/g10/keygen.c index 43924395c..958be3af4 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -507,24 +507,24 @@ generate_keypair() /* we can now write the certificates */ /* FIXME: should we check wether the user-id already exists? */ - if( get_keyblock_handle( pub_fname, &pub_kbpos ) ) { - if( add_keyblock_resource( pub_fname, 1 ) ) { + if( get_keyblock_handle( pub_fname, 0, &pub_kbpos ) ) { + if( add_keyblock_resource( pub_fname, 1, 0 ) ) { log_error("can add keyblock file '%s'\n", pub_fname ); rc = G10ERR_CREATE_FILE; } - else if( get_keyblock_handle( pub_fname, &pub_kbpos ) ) { + else if( get_keyblock_handle( pub_fname, 0, &pub_kbpos ) ) { log_error("can get keyblock handle for '%s'\n", pub_fname ); rc = G10ERR_CREATE_FILE; } } if( rc ) ; - else if( get_keyblock_handle( sec_fname, &sec_kbpos ) ) { - if( add_keyblock_resource( sec_fname, 1 ) ) { + else if( get_keyblock_handle( sec_fname, 1, &sec_kbpos ) ) { + if( add_keyblock_resource( sec_fname, 1, 1 ) ) { log_error("can add keyblock file '%s'\n", sec_fname ); rc = G10ERR_CREATE_FILE; } - else if( get_keyblock_handle( sec_fname, &sec_kbpos ) ) { + else if( get_keyblock_handle( sec_fname, 1, &sec_kbpos ) ) { log_error("can get keyblock handle for '%s'\n", sec_fname ); rc = G10ERR_CREATE_FILE; } diff --git a/g10/main.h b/g10/main.h index 15caaab9a..02b0a277c 100644 --- a/g10/main.h +++ b/g10/main.h @@ -49,6 +49,7 @@ int sign_file( const char *filename, int detached, STRLIST locusr, int encrypt, STRLIST remusr ); int sign_key( const char *username, STRLIST locusr ); int edit_keysigs( const char *username ); +int change_passphrase( const char *username ); /*-- sig-check.c --*/ int check_key_signature( KBNODE root, KBNODE node ); diff --git a/g10/packet.h b/g10/packet.h index 4a5a5a3cc..03a7f328f 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -238,6 +238,7 @@ PKT_secret_cert *copy_secret_cert( PKT_secret_cert *d, PKT_secret_cert *s ); int signature_check( PKT_signature *sig, MD_HANDLE *digest ); /*-- seckey-cert.c --*/ +int is_secret_key_protected( PKT_secret_cert *cert ); int check_secret_key( PKT_secret_cert *cert ); int protect_secret_key( PKT_secret_cert *cert, DEK *dek ); diff --git a/g10/ringedit.c b/g10/ringedit.c index 05a8bb299..8b7431961 100644 --- a/g10/ringedit.c +++ b/g10/ringedit.c @@ -58,6 +58,7 @@ struct resource_table_struct { int used; + int secret; /* this is a secret keyring */ char *fname; IOBUF iobuf; }; @@ -94,7 +95,7 @@ check_pos( KBPOS *kbpos ) * Register a resource (which currently may ionly be a keyring file). */ int -add_keyblock_resource( const char *filename, int force ) +add_keyblock_resource( const char *filename, int force, int secret ) { IOBUF iobuf; int i; @@ -109,6 +110,7 @@ add_keyblock_resource( const char *filename, int force ) if( !iobuf && !force ) return G10ERR_OPEN_FILE; resource_table[i].used = 1; + resource_table[i].secret = !!secret; resource_table[i].fname = m_strdup(filename); resource_table[i].iobuf = iobuf; return 0; @@ -120,12 +122,12 @@ add_keyblock_resource( const char *filename, int force ) * to get a handle for insert_keyblock for a new keyblock. */ int -get_keyblock_handle( const char *filename, KBPOS *kbpos ) +get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos ) { int i; for(i=0; i < MAX_RESOURCES; i++ ) - if( resource_table[i].used ) { + if( resource_table[i].used && !resource_table[i].secret == !secret ) { /* fixme: dos needs case insensitive file compare */ if( !strcmp( resource_table[i].fname, filename ) ) { memset( kbpos, 0, sizeof *kbpos ); @@ -148,12 +150,12 @@ get_keyblock_handle( const char *filename, KBPOS *kbpos ) * Returns: 0 if found, -1 if not found or an errorcode. */ int -search_keyblock( PACKET *pkt, KBPOS *kbpos ) +search_keyblock( PACKET *pkt, KBPOS *kbpos, int secret ) { int i, rc, last_rc=-1; for(i=0; i < MAX_RESOURCES; i++ ) { - if( resource_table[i].used ) { + if( resource_table[i].used && !resource_table[i].secret == !secret ) { /* note: here we have to add different search functions, * depending on the type of the resource */ rc = keyring_search( pkt, kbpos, resource_table[i].iobuf ); @@ -192,11 +194,36 @@ search_keyblock_byname( KBPOS *kbpos, const char *username ) init_packet( &pkt ); pkt.pkttype = PKT_PUBLIC_CERT; pkt.pkt.public_cert = pkc; - rc = search_keyblock( &pkt, kbpos ); + rc = search_keyblock( &pkt, kbpos, 0 ); free_public_cert(pkc); return rc; } +/**************** + * Combined function to search for a username and get the position + * of the keyblock. This function does not unprotect the secret key. + */ +int +search_secret_keyblock_byname( KBPOS *kbpos, const char *username ) +{ + PACKET pkt; + PKT_secret_cert *skc = m_alloc_clear( sizeof *skc ); + int rc; + + rc = get_seckey_byname( skc, username, 0 ); + if( rc ) { + free_secret_cert(skc); + return rc; + } + + init_packet( &pkt ); + pkt.pkttype = PKT_SECRET_CERT; + pkt.pkt.secret_cert = skc; + rc = search_keyblock( &pkt, kbpos, 1 ); + free_secret_cert(skc); + return rc; +} + /**************** * Lock the keyblock; wait until it's available diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c index c1ea596ac..7f76b31e8 100644 --- a/g10/seckey-cert.c +++ b/g10/seckey-cert.c @@ -284,6 +284,23 @@ check_secret_key( PKT_secret_cert *cert ) return rc; } +/**************** + * check wether the secret key is protected. + * Returns: 0 not protected, -1 on error or the protection algorithm + */ +int +is_secret_key_protected( PKT_secret_cert *cert ) +{ + if( cert->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) + return cert->d.elg.is_protected? cert->d.elg.protect_algo : 0; + #ifdef HAVE_RSA_CIPHER + else if( cert->pubkey_algo == PUBKEY_ALGO_RSA ) + return cert->d.rsa.is_protected? cert->d.rsa.protect_algo : 0; + #endif + else + return -1; /* unsupported */ +} + /**************** * Protect the secret key certificate with the passphrase from DEK diff --git a/g10/sign.c b/g10/sign.c index a8541391d..d0596d669 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -695,6 +695,129 @@ edit_keysigs( const char *username ) } +int +change_passphrase( const char *username ) +{ + int rc = 0; + KBNODE keyblock = NULL; + KBNODE kbctx, node; + KBPOS kbpos; + PKT_secret_cert *skc; + int any; + u32 skc_keyid[2]; + char *answer; + int changed=0; + + /* search the userid */ + rc = search_secret_keyblock_byname( &kbpos, username ); + if( rc ) { + log_error("secret key for user '%s' not found\n", username ); + goto leave; + } + + /* read the keyblock */ + rc = read_keyblock( &kbpos, &keyblock ); + if( rc ) { + log_error("error reading the certificate: %s\n", g10_errstr(rc) ); + goto leave; + } + + /* get the keyid from the keyblock */ + for( kbctx=NULL; (node=walk_kbtree( keyblock, &kbctx)) ; ) { + if( node->pkt->pkttype == PKT_SECRET_CERT ) + break; + } + if( !node ) { + log_error("Oops; secret key not found anymore!\n"); + rc = G10ERR_GENERAL; + goto leave; + } + + skc = node->pkt->pkt.secret_cert; + keyid_from_skc( skc, skc_keyid ); + tty_printf("sec %4u%c/%08lX %s ", + nbits_from_skc( skc ), + pubkey_letter( skc->pubkey_algo ), + skc_keyid[1], datestr_from_skc(skc) ); + { + size_t n; + char *p = get_user_id( skc_keyid, &n ); + tty_print_string( p, n ); + m_free(p); + tty_printf("\n"); + } + + clear_kbnode_flags( keyblock ); + switch( is_secret_key_protected( skc ) ) { + case -1: + rc = G10ERR_PUBKEY_ALGO; + break; + case 0: + tty_printf("This key is not protected.\n"); + break; + default: + tty_printf("Key is protected.\n"); + rc = check_secret_key( skc ); + break; + } + + if( rc ) + tty_printf("Can't edit this key: %s\n", g10_errstr(rc)); + else { + DEK *dek = m_alloc_secure( sizeof *dek ); + + tty_printf( "Enter the new passphrase for this secret key.\n\n" ); + + for(;;) { + dek->algo = CIPHER_ALGO_BLOWFISH; + rc = make_dek_from_passphrase( dek , 2 ); + if( rc == -1 ) { + rc = 0; + tty_printf( "You don't want a passphrase -" + " this is probably a *bad* idea!\n\n"); + answer = tty_get("Do you really want to do this? "); + tty_kill_prompt(); + if( answer_is_yes(answer) ) + changed++; + m_free(answer); + break; + } + else if( rc == G10ERR_PASSPHRASE ) { + tty_printf("passphrase not correctly repeated; try again.\n"); + } + else if( rc ) { + m_free(dek); dek = NULL; + log_error("Error getting the passphrase: %s\n", g10_errstr(rc)); + break; + } + else { /* okay */ + skc->d.elg.protect_algo = CIPHER_ALGO_BLOWFISH; + randomize_buffer(skc->d.elg.protect.blowfish.iv, 8, 1); + rc = protect_secret_key( skc, dek ); + if( rc ) + log_error("protect_secret_key failed: %s\n", g10_errstr(rc) ); + else + changed++; + break; + } + } + m_free(dek); + } + + + if( changed ) { + rc = update_keyblock( &kbpos, keyblock ); + if( rc ) { + log_error("update_keyblock failed: %s\n", g10_errstr(rc) ); + goto leave; + } + } + + leave: + release_kbnode( keyblock ); + return rc; +} + /**************** * Create a signature packet for the given public key certificate -- cgit v1.2.3