From 762d3d7197f622296ea5360a73c46c88dcd26308 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 7 Jan 1998 20:47:46 +0000 Subject: [PATCH] patchlevel 2 --- TODO | 3 + VERSION | 2 +- cipher/Makefile.am | 1 + cipher/Makefile.in | 5 +- cipher/md.c | 10 +-- cipher/misc.c | 152 +++++++++++++++++++++++++++++++++++++++++++++ config.h.in | 7 +-- configure.in | 2 +- g10/OPTIONS | 3 + g10/cipher.c | 9 ++- g10/encode.c | 6 +- g10/encr-data.c | 3 +- g10/g10.c | 39 ++++++++++++ g10/keygen.c | 102 ++++++++++++++++++++++++++---- g10/keyid.c | 127 +++++++++++++++++++++++++++---------- g10/main.h | 4 -- g10/mainproc.c | 2 +- g10/options.h | 6 +- g10/pubkey-enc.c | 5 ++ g10/seskey.c | 4 ++ include/cipher.h | 8 ++- include/util.h | 6 ++ util/iobuf.c | 2 +- util/strgutil.c | 48 ++++++++++++++ 24 files changed, 475 insertions(+), 81 deletions(-) create mode 100644 cipher/misc.c diff --git a/TODO b/TODO index 41065cf28..bcd64edd7 100644 --- a/TODO +++ b/TODO @@ -35,3 +35,6 @@ * armor has now some problems. + * add g10 stuff to Mutt's pgpinvoke.c + + diff --git a/VERSION b/VERSION index 17e51c385..d917d3e26 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.1 +0.1.2 diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 2f0792cb9..0855d7da9 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -23,6 +23,7 @@ cipher_SOURCES = blowfish.c \ dsa.h \ dsa.c \ md.c \ + misc.c \ smallprime.c cipher_LIBADD = @CIPHER_EXTRA_OBJS@ diff --git a/cipher/Makefile.in b/cipher/Makefile.in index f71937966..7bd7691f8 100644 --- a/cipher/Makefile.in +++ b/cipher/Makefile.in @@ -60,6 +60,7 @@ cipher_SOURCES = blowfish.c \ dsa.h \ dsa.c \ md.c \ + misc.c \ smallprime.c cipher_LIBADD = @CIPHER_EXTRA_OBJS@ @@ -82,7 +83,7 @@ LIBS = @LIBS@ COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) LINK = $(CC) $(LDFLAGS) -o $@ cipher_OBJECTS = blowfish.o elgamal.o gost.o md5.o primegen.o random.o \ -rmd160.o sha1.o dsa.o md.o smallprime.o +rmd160.o sha1.o dsa.o md.o misc.o smallprime.o EXTRA_cipher_SOURCES = LIBFILES = libcipher.a AR = ar @@ -101,7 +102,7 @@ DEP_DISTFILES = $(DIST_COMMON) $(SOURCES) $(BUILT_SOURCES) $(HEADERS) \ TAR = tar DEP_FILES = $(srcdir)/.deps/blowfish.P $(srcdir)/.deps/dsa.P \ $(srcdir)/.deps/elgamal.P $(srcdir)/.deps/gost.P $(srcdir)/.deps/md.P \ -$(srcdir)/.deps/md5.P $(srcdir)/.deps/primegen.P \ +$(srcdir)/.deps/md5.P $(srcdir)/.deps/misc.P $(srcdir)/.deps/primegen.P \ $(srcdir)/.deps/random.P $(srcdir)/.deps/rmd160.P \ $(srcdir)/.deps/sha1.P $(srcdir)/.deps/smallprime.P SOURCES = $(cipher_SOURCES) diff --git a/cipher/md.c b/cipher/md.c index 71403c8c9..67f5356a8 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -26,17 +26,11 @@ #include "cipher.h" #include "errors.h" + int md_okay( int algo ) { - switch( algo ) { - case DIGEST_ALGO_MD5: - case DIGEST_ALGO_RMD160: - case DIGEST_ALGO_SHA1: - return 0; - default: - return G10ERR_DIGEST_ALGO; - } + return check_digest_algo( algo ); } diff --git a/cipher/misc.c b/cipher/misc.c new file mode 100644 index 000000000..cd0d31a49 --- /dev/null +++ b/cipher/misc.c @@ -0,0 +1,152 @@ +/* misc.c - utility functions + * Copyright (c) 1997 by Werner Koch (dd9jn) + * + * This file is part of G10. + * + * G10 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * G10 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include +#include +#include +#include +#include "util.h" +#include "cipher.h" + + +static struct { const char *name; int algo;} cipher_names[] = { + { "IDEA", CIPHER_ALGO_IDEA }, + { "3DES", CIPHER_ALGO_3DES }, + { "CAST", CIPHER_ALGO_CAST }, + { "BLOWFISH128", CIPHER_ALGO_BLOWFISH128 }, + { "ROT_N", CIPHER_ALGO_ROT_N }, + { "SAFER_SK128", CIPHER_ALGO_SAFER_SK128 }, + { "DES_SK", CIPHER_ALGO_DES_SK }, + { "BLOWFISH", CIPHER_ALGO_BLOWFISH }, + { "GOST", CIPHER_ALGO_GOST }, + {NULL} }; + +static struct { const char *name; int algo;} pubkey_names[] = { + { "RSA", PUBKEY_ALGO_RSA }, + { "RSA-E", PUBKEY_ALGO_RSA_E }, + { "RSA-S", PUBKEY_ALGO_RSA_S }, + { "ELGAMAL", PUBKEY_ALGO_ELGAMAL }, + { "ELG", PUBKEY_ALGO_ELGAMAL }, + { "DSA", PUBKEY_ALGO_DSA }, + {NULL} }; + +static struct { const char *name; int algo;} digest_names[] = { + { "MD5", DIGEST_ALGO_MD5 }, + { "SHA1", DIGEST_ALGO_SHA1 }, + { "SHA-1", DIGEST_ALGO_SHA1 }, + { "RMD160", DIGEST_ALGO_RMD160 }, + { "RMD-160", DIGEST_ALGO_RMD160 }, + { "RIPE-MD-160", DIGEST_ALGO_RMD160 }, + {NULL} }; + + +/**************** + * Map a string to the cipher algo + */ +int +string_to_cipher_algo( const char *string ) +{ + int i; + const char *s; + + for(i=0; s=cipher_names[i].name; i++ ) + if( !stricmp( s, string ) ) + return cipher_names[i].algo; + return 0; +} + + +/**************** + * Map a string to the pubkey algo + */ +int +string_to_pubkey_algo( const char *string ) +{ + int i; + const char *s; + + for(i=0; s=pubkey_names[i].name; i++ ) + if( !stricmp( s, string ) ) + return pubkey_names[i].algo; + return 0; +} + +/**************** + * Map a string to the digest algo + */ +int +string_to_digest_algo( const char *string ) +{ + int i; + const char *s; + + for(i=0; s=digest_names[i].name; i++ ) + if( !stricmp( s, string ) ) + return digest_names[i].algo; + return 0; +} + +/**************** + * Return 0 if the cipher algo is available + */ +int +check_cipher_algo( int algo ) +{ + switch( algo ) { + case CIPHER_ALGO_BLOWFISH128: + case CIPHER_ALGO_BLOWFISH: + return 0; + default: + return G10ERR_CIPHER_ALGO; + } +} + + +int +check_pubkey_algo( int algo ) +{ + switch( algo ) { + case PUBKEY_ALGO_ELGAMAL: + #ifdef HAVE_RSA_CIPHER + case PUBKEY_ALGO_RSA: + #endif + return 0; + default: + return G10ERR_PUBKEY_ALGO; + } +} + + +int +check_digest_algo( int algo ) +{ + switch( algo ) { + case DIGEST_ALGO_MD5: + case DIGEST_ALGO_RMD160: + case DIGEST_ALGO_SHA1: + return 0; + default: + return G10ERR_DIGEST_ALGO; + } +} + + + diff --git a/config.h.in b/config.h.in index 93f0acb96..2a3bd36e4 100644 --- a/config.h.in +++ b/config.h.in @@ -78,11 +78,8 @@ /* Define if you have the strerror function. */ #undef HAVE_STRERROR -/* Define if you have the strtol function. */ -#undef HAVE_STRTOL - -/* Define if you have the strtoul function. */ -#undef HAVE_STRTOUL +/* Define if you have the strlwr function. */ +#undef HAVE_STRLWR /* Define if you have the tcgetattr function. */ #undef HAVE_TCGETATTR diff --git a/configure.in b/configure.in index 65ae82e27..f01033baf 100644 --- a/configure.in +++ b/configure.in @@ -155,7 +155,7 @@ AC_CHECK_SIZEOF(unsigned long, 4) dnl Checks for library functions. AC_FUNC_VPRINTF -AC_CHECK_FUNCS(strerror strtol strtoul stpcpy tcgetattr) +AC_CHECK_FUNCS(strerror stpcpy strlwr tcgetattr) dnl check wether we have a random device AC_CACHE_CHECK(for random device, ac_cv_have_dev_random, 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 */ diff --git a/g10/g10.c b/g10/g10.c index ac12d52db..30776cc80 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -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 \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) \"\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"); } diff --git a/include/cipher.h b/include/cipher.h index ed553dcb2..fd7886c90 100644 --- a/include/cipher.h +++ b/include/cipher.h @@ -88,7 +88,13 @@ int cipher_debug_mode; #define is_valid_pubkey_algo(a) ( (a) == PUBKEY_ALGO_ELGAMAL ) #endif - +/*-- misc.c --*/ +int string_to_cipher_algo( const char *string ); +int string_to_pubkey_algo( const char *string ); +int string_to_digest_algo( const char *string ); +int check_cipher_algo( int algo ); +int check_pubkey_algo( int algo ); +int check_digest_algo( int algo ); /*-- md.c --*/ int md_okay( int algo ); diff --git a/include/util.h b/include/util.h index 46f337955..34015ffe6 100644 --- a/include/util.h +++ b/include/util.h @@ -92,10 +92,16 @@ int answer_is_yes( const char *s ); void free_strlist( STRLIST sl ); #define FREE_STRLIST(a) do { free_strlist((a)); (a) = NULL ; } while(0) char *memistr( char *buf, size_t buflen, const char *sub ); +char *trim_spaces( char *string ); +int string_count_chr( const char *string, int c ); + #define stricmp(a,b) strcasecmp((a),(b)) #ifndef HAVE_STPCPY char *stpcpy(char *a,const char *b); #endif +#ifndef HAVE_STRLWR +char *strlwr(char *a); +#endif /******** some macros ************/ diff --git a/util/iobuf.c b/util/iobuf.c index 981fb2efb..ad9821972 100644 --- a/util/iobuf.c +++ b/util/iobuf.c @@ -350,7 +350,7 @@ iobuf_create( const char *fname ) file_filter_ctx_t *fcx; size_t len; - if( !fname ) { + if( !fname || (*fname=='-' && !fname[1]) ) { fp = stdout; fname = "[stdout]"; } diff --git a/util/strgutil.c b/util/strgutil.c index daeefe8ae..ecdcb750c 100644 --- a/util/strgutil.c +++ b/util/strgutil.c @@ -62,6 +62,43 @@ memistr( char *buf, size_t buflen, const char *sub ) } +/**************** + * remove leading and trailing white spaces + */ +char * +trim_spaces( char *str ) +{ + char *string, *p, *mark; + + string = str; + /* find first non space character */ + for( p=string; *p && isspace( *(byte*)p ) ; p++ ) + ; + /* move characters */ + for( (mark = NULL); (*string = *p); string++, p++ ) + if( isspace( *(byte*)p ) ) { + if( !mark ) + mark = string ; + } + else + mark = NULL ; + if( mark ) + *mark = '\0' ; /* remove trailing spaces */ + + return str ; +} + + +int +string_count_chr( const char *string, int c ) +{ + int count; + for(count=0; *string; string++ ) + if( *string == c ) + count++; + return count; +} + /********************************************* ********** missing string functions ********* *********************************************/ @@ -78,3 +115,14 @@ stpcpy(char *a,const char *b) } #endif +#ifndef HAVE_STRLWR +char * +strlwr(char *s) +{ + char *p; + for(p=s; *p; p++ ) + *p = tolower(*p); + return s; +} +#endif +