diff options
Diffstat (limited to 'g10')
-rw-r--r-- | g10/OPTIONS | 3 | ||||
-rw-r--r-- | g10/cipher.c | 9 | ||||
-rw-r--r-- | g10/encode.c | 6 | ||||
-rw-r--r-- | g10/encr-data.c | 3 | ||||
-rw-r--r-- | g10/g10.c | 39 | ||||
-rw-r--r-- | g10/keygen.c | 102 | ||||
-rw-r--r-- | g10/keyid.c | 127 | ||||
-rw-r--r-- | g10/main.h | 4 | ||||
-rw-r--r-- | g10/mainproc.c | 2 | ||||
-rw-r--r-- | g10/options.h | 6 | ||||
-rw-r--r-- | g10/pubkey-enc.c | 5 | ||||
-rw-r--r-- | g10/seskey.c | 4 |
12 files changed, 248 insertions, 62 deletions
diff --git a/g10/OPTIONS b/g10/OPTIONS index a5961763b..684abd2d9 100644 --- a/g10/OPTIONS +++ b/g10/OPTIONS @@ -165,6 +165,9 @@ no-default-keyring no-greeting # suppress the initial copyright etc. messages but do not enter batch mode. +no-verbose +# set verbose level to 0 + options filename # Ignored in option files. diff --git a/g10/cipher.c b/g10/cipher.c index 6900e896c..37bba3458 100644 --- a/g10/cipher.c +++ b/g10/cipher.c @@ -67,7 +67,8 @@ cipher_filter( void *opaque, int control, randomize_buffer( temp, 8, 1 ); temp[8] = temp[6]; temp[9] = temp[7]; - if( cfx->dek->algo == CIPHER_ALGO_BLOWFISH ) { + if( cfx->dek->algo == CIPHER_ALGO_BLOWFISH + || cfx->dek->algo == CIPHER_ALGO_BLOWFISH128 ) { cfx->bf_ctx = m_alloc_secure( sizeof *cfx->bf_ctx ); blowfish_setkey( cfx->bf_ctx, cfx->dek->key, cfx->dek->keylen ); blowfish_setiv( cfx->bf_ctx, NULL ); @@ -80,13 +81,15 @@ cipher_filter( void *opaque, int control, cfx->header=1; } - if( cfx->dek->algo == CIPHER_ALGO_BLOWFISH ) + if( cfx->dek->algo == CIPHER_ALGO_BLOWFISH + || cfx->dek->algo == CIPHER_ALGO_BLOWFISH128 ) blowfish_encode_cfb( cfx->bf_ctx, buf, buf, size); if( iobuf_write( a, buf, size ) ) rc = G10ERR_WRITE_FILE; } else if( control == IOBUFCTRL_FREE ) { - if( cfx->dek->algo == CIPHER_ALGO_BLOWFISH ) + if( cfx->dek->algo == CIPHER_ALGO_BLOWFISH + || cfx->dek->algo == CIPHER_ALGO_BLOWFISH128 ) m_free(cfx->bf_ctx); } else if( control == IOBUFCTRL_DESC ) { diff --git a/g10/encode.c b/g10/encode.c index b0b148dd1..688cbfc08 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -88,7 +88,7 @@ encode_simple( const char *filename, int mode ) cfx.dek = NULL; if( mode ) { cfx.dek = m_alloc_secure( sizeof *cfx.dek ); - cfx.dek->algo = DEFAULT_CIPHER_ALGO; + cfx.dek->algo = opt.def_cipher_algo; if( (rc = make_dek_from_passphrase( cfx.dek , 2 )) ) { m_free(cfx.dek); iobuf_close(inp); @@ -199,7 +199,7 @@ encode_crypt( const char *filename, STRLIST remusr ) /* create a session key */ cfx.dek = m_alloc_secure( sizeof *cfx.dek ); - cfx.dek->algo = DEFAULT_CIPHER_ALGO; + cfx.dek->algo = opt.def_cipher_algo; make_session_key( cfx.dek ); if( DBG_CIPHER ) log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen ); @@ -269,7 +269,7 @@ encrypt_filter( void *opaque, int control, else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */ if( !efx->header_okay ) { efx->cfx.dek = m_alloc_secure( sizeof *efx->cfx.dek ); - efx->cfx.dek->algo = DEFAULT_CIPHER_ALGO; + efx->cfx.dek->algo = opt.def_cipher_algo; make_session_key( efx->cfx.dek ); if( DBG_CIPHER ) log_hexdump("DEK is: ", diff --git a/g10/encr-data.c b/g10/encr-data.c index aed1890a6..43e48a96d 100644 --- a/g10/encr-data.c +++ b/g10/encr-data.c @@ -51,7 +51,8 @@ decrypt_data( PKT_encrypted *ed, DEK *dek ) byte temp[16]; - if( dek->algo != CIPHER_ALGO_BLOWFISH ) + if( dek->algo != CIPHER_ALGO_BLOWFISH + && dek->algo != CIPHER_ALGO_BLOWFISH128 ) return G10ERR_CIPHER_ALGO; if( ed->len && ed->len < 10 ) log_bug("Nanu\n"); /* oops: found a bug */ @@ -169,6 +169,10 @@ main( int argc, char **argv ) { 523, "passphrase-fd",1, "\r" }, { 524, "edit-sig" ,0, "edit a key signature" }, { 525, "change-passphrase", 0, "change the passphrase of your secret keyring"}, + { 526, "no-verbose", 0, "\r"}, + { 527, "cipher-algo", 2 , "select default cipher algorithm" }, + { 528, "pubkey-algo", 2 , "select default puplic key algorithm" }, + { 529, "digest-algo", 2 , "select default message digest algorithm" }, {0} }; ARGPARSE_ARGS pargs; @@ -194,6 +198,9 @@ main( int argc, char **argv ) opt.compress = -1; /* defaults to standard compress level */ + opt.def_cipher_algo = CIPHER_ALGO_BLOWFISH; + opt.def_pubkey_algo = PUBKEY_ALGO_ELGAMAL; + opt.def_digest_algo = DIGEST_ALGO_RMD160; /* check wether we have a config file on the commandline */ orig_argc = argc; @@ -298,6 +305,19 @@ main( int argc, char **argv ) case 523: set_passphrase_fd( pargs.r.ret_int ); break; case 524: set_cmd( &cmd, aEditSig); break; case 525: set_cmd( &cmd, aChangePass); break; + case 526: opt.verbose = 0; opt.list_sigs=0; break; + case 527: + opt.def_cipher_algo = string_to_cipher_algo(pargs.r.ret_str); + break; + case 528: + opt.def_pubkey_algo = string_to_pubkey_algo(pargs.r.ret_str); + break; + case 529: + opt.def_digest_algo = string_to_digest_algo(pargs.r.ret_str); + break; + + + break; default : errors++; pargs.err = configfp? 1:2; break; } } @@ -308,6 +328,18 @@ main( int argc, char **argv ) goto next_pass; } m_free( configname ); configname = NULL; + if( !opt.def_cipher_algo || check_cipher_algo(opt.def_cipher_algo) ) { + log_error("selected cipher algorithm is invalid\n"); + errors++; + } + if( !opt.def_pubkey_algo || check_pubkey_algo(opt.def_pubkey_algo) ) { + log_error("selected pubkey algorithm is invalid\n"); + errors++; + } + if( !opt.def_digest_algo || check_digest_algo(opt.def_digest_algo) ) { + log_error("selected digest algorithm is invalid\n"); + errors++; + } if( errors ) exit(2); @@ -351,6 +383,13 @@ main( int argc, char **argv ) else { fname_print = "[stdin]"; fname = NULL; + if( get_passphrase_fd() == 0 ) { + /* reading data and passphrase form stdin: + * we assume the first line is the passphrase, so + * we read it now + */ + /* FIXME: doit */ + } } switch( cmd ) { diff --git a/g10/keygen.c b/g10/keygen.c index 958be3af4..fddeedbbc 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -305,6 +305,7 @@ generate_keypair() int rc; int algo; const char *algo_name; + char *aname, *acomment, *amail; #ifndef TEST_ALGO if( opt.batch || opt.answer_yes || opt.answer_no ) @@ -404,27 +405,102 @@ generate_keypair() uid = m_alloc(strlen(TEST_UID)+1); strcpy(uid, TEST_UID); #else - tty_printf( "\nYou need a User-ID to identify your key; please use your name and your\n" - "email address in this suggested format:\n" - " \"Heinrich Heine <[email protected]>\n" ); + tty_printf( "\n" +"You need a User-ID to identify your key; the software constructs the user id\n" +"from Real Name, Comment and Email Address in this form:\n" +" \"Heinrich Heine (Der Dichter) <[email protected]>\"\n" ); uid = NULL; + aname=acomment=amail=NULL; for(;;) { + char *p; + + if( !aname ) { + for(;;) { + m_free(aname); + aname = tty_get("Real name: "); + trim_spaces(aname); + tty_kill_prompt(); + if( strpbrk( aname, "<([])>" ) ) + tty_printf("Invalid character in name\n"); + else if( strlen(aname) < 5 ) + tty_printf("Name must be at least 5 characters long\n"); + else + break; + } + } + if( !amail ) { + for(;;) { + m_free(amail); + amail = tty_get("Email address: "); + trim_spaces(amail); + strlwr(amail); + tty_kill_prompt(); + if( !*amail ) + break; /* no email address is okay */ + else if( strcspn( amail, "abcdefghijklmnopqrstuvwxyz_-.@" ) + || string_count_chr(amail,'@') != 1 + || *amail == '@' + || amail[strlen(amail)-1] == '@' + || amail[strlen(amail)-1] == '.' + || strstr(amail, "..") ) + tty_printf("Not a valid email address\n"); + else + break; + } + } + if( !acomment ) { + for(;;) { + m_free(acomment); + acomment = tty_get("Comment: "); + trim_spaces(acomment); + tty_kill_prompt(); + if( !*acomment ) + break; /* no comment is okay */ + else if( strpbrk( acomment, "()" ) ) + tty_printf("Invalid character in comment\n"); + else + break; + } + } + m_free(uid); - tty_printf("\n"); - uid = tty_get("Your User-ID: "); - tty_kill_prompt(); - if( strlen(uid) < 5 ) - tty_printf("Please enter a string of at least 5 characters\n"); - else { - tty_printf("You selected this USER-ID:\n \"%s\"\n\n", uid); - answer = tty_get("Is this correct? "); + uid = p = m_alloc(strlen(aname)+strlen(amail)+strlen(acomment)+10); + p = stpcpy(p, aname ); + if( *acomment ) + p = stpcpy(stpcpy(stpcpy(p," ("), acomment),")"); + if( *amail ) + p = stpcpy(stpcpy(stpcpy(p," <"), amail),">"); + + tty_printf("You selected this USER-ID:\n \"%s\"\n\n", uid); + for(;;) { + answer = tty_get("Edit (N)ame, (C)omment, (E)mail or (O)kay? "); tty_kill_prompt(); - if( answer_is_yes(answer) ) { - m_free(answer); + if( strlen(answer) > 1 ) + ; + else if( *answer == 'N' || *answer == 'n' ) { + m_free(aname); aname = NULL; + break; + } + else if( *answer == 'C' || *answer == 'c' ) { + m_free(acomment); acomment = NULL; + break; + } + else if( *answer == 'E' || *answer == 'e' ) { + m_free(amail); amail = NULL; + break; + } + else if( *answer == 'O' || *answer == 'o' ) { + m_free(aname); aname = NULL; + m_free(acomment); acomment = NULL; + m_free(amail); amail = NULL; break; } m_free(answer); } + m_free(answer); + if( !amail && !acomment && !amail ) + break; + m_free(uid); uid = NULL; } #endif diff --git a/g10/keyid.c b/g10/keyid.c index 5848459c8..43413e083 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -46,6 +46,77 @@ pubkey_letter( int algo ) } } +/* this is special code for V3 which uses ElGamal and + * calculates a fingerprint like V4, but with rmd160 + * and a version byte of 3. Returns an rmd160 handle, caller must + * do rmd160_final() + */ + +static RMDHANDLE +v3_elg_fingerprint_md( PKT_public_cert *pkc ) +{ + RMDHANDLE md; + byte *buf1, *buf2, *buf3; + byte *p1, *p2, *p3; + unsigned n1, n2, n3; + unsigned n; + + p1 = buf1 = mpi_get_buffer( pkc->d.elg.p, &n1, NULL ); + for( ; !*p1 && n1; p1++, n1-- ) /* skip leading null bytes */ + ; + p2 = buf2 = mpi_get_buffer( pkc->d.elg.g, &n2, NULL ); + for( ; !*p2 && n2; p2++, n2-- ) /* skip leading null bytes */ + ; + p3 = buf3 = mpi_get_buffer( pkc->d.elg.y, &n3, NULL ); + for( ; !*p3 && n3; p3++, n3-- ) /* skip leading null bytes */ + ; + + /* calculate length of packet (1+4+2+1+2+n1+2+n2+2+n3) */ + n = 14 + n1 + n2 + n3; + md = rmd160_open(0); + + rmd160_putchar( md, 0x99 ); /* ctb */ + rmd160_putchar( md, n >> 8 ); /* 2 byte length header */ + rmd160_putchar( md, n ); + rmd160_putchar( md, 3 ); /* version */ + { u32 a = pkc->timestamp; + rmd160_putchar( md, a >> 24 ); + rmd160_putchar( md, a >> 16 ); + rmd160_putchar( md, a >> 8 ); + rmd160_putchar( md, a ); + } + { u16 a = pkc->valid_days; + rmd160_putchar( md, a >> 8 ); + rmd160_putchar( md, a ); + } + rmd160_putchar( md, pkc->pubkey_algo ); + rmd160_putchar( md, n1>>8); rmd160_putchar( md, n1 ); rmd160_write( md, p1, n1 ); + rmd160_putchar( md, n2>>8); rmd160_putchar( md, n2 ); rmd160_write( md, p2, n2 ); + rmd160_putchar( md, n3>>8); rmd160_putchar( md, n3 ); rmd160_write( md, p3, n3 ); + m_free(buf1); + m_free(buf2); + m_free(buf3); + + return md; +} + + +static RMDHANDLE +v3_elg_fingerprint_md_skc( PKT_secret_cert *skc ) +{ + PKT_public_cert pkc; + byte *p; + + pkc.pubkey_algo = skc->pubkey_algo; + pkc.timestamp = skc->timestamp; + pkc.valid_days = skc->valid_days; + pkc.pubkey_algo = skc->pubkey_algo; + pkc.d.elg.p = skc->d.elg.p; + pkc.d.elg.g = skc->d.elg.g; + pkc.d.elg.y = skc->d.elg.y; + return v3_elg_fingerprint_md( &pkc ); +} + /**************** * Get the keyid from the secret key certificate and put it into keyid @@ -61,7 +132,14 @@ keyid_from_skc( PKT_secret_cert *skc, u32 *keyid ) keyid = dummy_keyid; if( skc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { - lowbits = mpi_get_keyid( skc->d.elg.y, keyid ); + const byte *dp; + RMDHANDLE md; + md = v3_elg_fingerprint_md_skc(skc); + dp = rmd160_final( md ); + keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ; + keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ; + lowbits = keyid[1]; + rmd160_close(md); } else if( skc->pubkey_algo == PUBKEY_ALGO_RSA ) { lowbits = mpi_get_keyid( skc->d.rsa.rsa_n, keyid ); @@ -87,7 +165,14 @@ keyid_from_pkc( PKT_public_cert *pkc, u32 *keyid ) keyid = dummy_keyid; if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { - lowbits = mpi_get_keyid( pkc->d.elg.y, keyid ); + const byte *dp; + RMDHANDLE md; + md = v3_elg_fingerprint_md(pkc); + dp = rmd160_final( md ); + keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ; + keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ; + lowbits = keyid[1]; + rmd160_close(md); } else if( pkc->pubkey_algo == PUBKEY_ALGO_RSA ) { lowbits = mpi_get_keyid( pkc->d.rsa.rsa_n, keyid ); @@ -213,47 +298,21 @@ fingerprint_from_skc( PKT_secret_cert *skc, size_t *ret_len ) return p; } + + + byte * fingerprint_from_pkc( PKT_public_cert *pkc, size_t *ret_len ) { byte *p, *buf, *array; + const char *dp; size_t len; unsigned n; if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) { RMDHANDLE md; - const char *dp; - - md = rmd160_open(0); - - { u32 a = pkc->timestamp; - rmd160_putchar( md, a >> 24 ); - rmd160_putchar( md, a >> 16 ); - rmd160_putchar( md, a >> 8 ); - rmd160_putchar( md, a ); - } - { u16 a = pkc->valid_days; - rmd160_putchar( md, a >> 8 ); - rmd160_putchar( md, a ); - } - rmd160_putchar( md, pkc->pubkey_algo ); - p = buf = mpi_get_buffer( pkc->d.elg.p, &n, NULL ); - for( ; !*p && n; p++, n-- ) - ; - rmd160_putchar( md, n>>8); rmd160_putchar( md, n ); rmd160_write( md, p, n ); - m_free(buf); - p = buf = mpi_get_buffer( pkc->d.elg.g, &n, NULL ); - for( ; !*p && n; p++, n-- ) - ; - rmd160_putchar( md, n>>8); rmd160_putchar( md, n ); rmd160_write( md, p, n ); - m_free(buf); - p = buf = mpi_get_buffer( pkc->d.elg.y, &n, NULL ); - for( ; !*p && n; p++, n-- ) - ; - rmd160_putchar( md, n>>8); rmd160_putchar( md, n ); rmd160_write( md, p, n ); - m_free(buf); - - dp = rmd160_final(md); + md = v3_elg_fingerprint_md(pkc); + dp = rmd160_final( md ); array = m_alloc( 20 ); len = 20; memcpy(array, dp, 20 ); diff --git a/g10/main.h b/g10/main.h index 02b0a277c..747ab70a8 100644 --- a/g10/main.h +++ b/g10/main.h @@ -24,10 +24,6 @@ #include "cipher.h" #include "keydb.h" -#define DEFAULT_CIPHER_ALGO CIPHER_ALGO_BLOWFISH -#define DEFAULT_PUBKEY_ALGO PUBKEY_ALGO_ELGAMAL -#define DEFAULT_DIGEST_ALGO DIGEST_ALGO_RMD160 - typedef struct { int header_okay; diff --git a/g10/mainproc.c b/g10/mainproc.c index b46cb1344..a99c975fd 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -232,7 +232,7 @@ proc_encrypted( CTX c, PACKET *pkt ) if( !c->dek && !c->last_was_pubkey_enc ) { /* assume this is conventional encrypted data */ c->dek = m_alloc_secure( sizeof *c->dek ); - c->dek->algo = DEFAULT_CIPHER_ALGO; + c->dek->algo = opt.def_cipher_algo; result = make_dek_from_passphrase( c->dek, 0 ); } else if( !c->dek ) diff --git a/g10/options.h b/g10/options.h index 31aa95522..0df1f41ea 100644 --- a/g10/options.h +++ b/g10/options.h @@ -36,9 +36,9 @@ struct { int list_sigs; /* list signatures */ int no_armor; int list_packets; /* list-packets mode */ - int reserved6; - int reserved7; - int reserved8; + int def_cipher_algo; + int def_pubkey_algo; + int def_digest_algo; int reserved9; int reserved10; int reserved11; diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index f3f02abde..2f8fb45f4 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -131,6 +131,11 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek ) { rc = G10ERR_WRONG_SECKEY; goto leave; } dek->algo = CIPHER_ALGO_BLOWFISH; break; + case CIPHER_ALGO_BLOWFISH128: + if( i != 18 ) /* length of blowfish-128 is 16 (+2 bytes checksum) */ + { rc = G10ERR_WRONG_SECKEY; goto leave; } + dek->algo = CIPHER_ALGO_BLOWFISH128; + break; default: rc = G10ERR_CIPHER_ALGO; goto leave; diff --git a/g10/seskey.c b/g10/seskey.c index 7d3cba27b..2698c73c7 100644 --- a/g10/seskey.c +++ b/g10/seskey.c @@ -41,6 +41,10 @@ make_session_key( DEK *dek ) dek->keylen = 20; randomize_buffer( dek->key, dek->keylen, 1 ); break; + case CIPHER_ALGO_BLOWFISH128: + dek->keylen = 16; + randomize_buffer( dek->key, dek->keylen, 1 ); + break; default: log_bug("invalid algo %d in make_session_key()\n"); } |