diff --git a/INSTALL b/INSTALL index 2fb9f9871..bf72ad4d2 100644 --- a/INSTALL +++ b/INSTALL @@ -7,7 +7,7 @@ ./configure --enable-m-debug - to ebanle the integrated malloc debugging stuff. + to enable the integrated malloc debugging stuff. 2) Run make: diff --git a/README b/README index 931839083..f166cb774 100644 --- a/README +++ b/README @@ -1,20 +1,20 @@ - G10 - The GNU Enryption and Signing Tool + G10 - The GNU Encryption and Signing Tool ------------------------------------------ - THIS IS VERSION IS ONLY a TEST VERSION ! YOU SHOULD NOT + THIS IS VERSION IS ONLY A TEST VERSION ! YOU SHOULD NOT USE IT FOR OTHER PURPOSES THAN EVALUATING THE CURRENT CODE. + * Only some parts work. + * The data format may change in the next version! - * The code to generate keys is not secure! - - * Some features are not implemented + * Some features are not yet implemented I provide this version as a reality check to start discussion. - Please subscribe to g10@net.lut.ac.uk be sending a mail with + Please subscribe to g10@net.lut.ac.uk by sending a mail with the word "subscribe" in the body to "g10-request@net.lut.ac.uk". @@ -25,26 +25,139 @@ it cannot be compatible to old PGP versions, because those use IDEA (which is worldwide patented) and RSA (which is patented in the United States until Sep 20, 2000). I'm sorry about this, but - this is the world we have created (e.g. by using propiertary software). + this is the world we have created (e.g. by using proprietary software). Because the OpenPGP standard is still a draft, G10 is not yet compatible to it (or PGP 5) - but it will. The data structures used are compatible with PGP 2.x, so it can parse an list such files and PGP should be able to parse data created by G10 and complain - about unsupported alogorithms. + about unsupported algorithms. The default algorithms used by G10 are ElGamal for public-key encryption and signing; Blowfish with a 160 bit key for protecting the secret-key components, conventional and session encryption; RIPE MD-160 to create message digest. DSA, SHA-1 and CAST are also implemented, but not used on default. I decided not - to use DSA as default signing algorithm, cecause it allows only for + to use DSA as default signing algorithm, because it allows only for 1024 bit keys and this may be not enough in a couple of years. - Key generation takes a long time and should be improved! + + Resources + --------- + G10 needs a directory "~/.g10" to store the default keyrings + and other files. + + + Key Generation + -------------- + Create a key pair with this command: + + g10 --gen-key + + This asks some questions and then starts key generation. To create + good random numbers for prime number generation, it uses a /dev/random + which will emit only bytes if the kernel can gather enough entropy. + If you see no progress, you should start some other activities such + as a mouse moves or a "find /". Because we have no hardware device + to generate random we have to use this method. + + Key generation shows progress by printing different characters to + stderr: + "." Miller-Rabin test failed. + "+" Miller-Rabin test succeeded. + "!" Reloading the pool with fresh prime numbers + "^" Checking a new value for the generator + "~" Issued during generator checks + "<" Size of one factor decreased + ">" Size of one factor increased + + The prime number for ElGamal is generated this way: + + 1) Make a prime number q of 160, 200, 240 bits (depending on the keysize). + 2) Select the length of the other prime factors to be at least the size + of q and calculate the number of prime factors needed + 3) Make a pool of prime number, each of the length determined in step 2 + 4) Get a new permutation out of the pool or continue with step 3 + if we have tested all permutations. + 5) Calculate a candidate prime p = 2 * q * p[1] * ... * p[n] + 1 + 6) Check that this prime has the correct length (this may change q if + it seems not to be possible to make a prime of the desired length) + 7) Check whether this is a prime using trial divisions and the + Miller-Rabin test. + 8) Continue with step 4 if we did not find a prime in step 7. + 9) Find a generator for that prime. + + + Signatures + ---------- + To create a signature, use this: + + g10 -s file + + This creates a file file.g10 which is compressed and has a signature + attached. + + g10 -sa file + + Same as above, but file.g10 is ascii armored. + + g10 -s -o out file + + Creates a signature of file, but writes the output to the file "out". + + Encryption + ---------- + To encrypt data use this: + + g10 -e -r heine file + + This encrypts files with the public key of "heine" and writes it + to "file.g10" + + echo "hallo" | g10 -ea -r heine | mail heine + + Ditto, but encrypts "hallo\n" and mails it as ascii armored message. + + + Debug Flags + ----------- + Use the option "--debug n" to output debug informations. This option + can be used multiple times, all values are ORed; n maybe prefixed with + 0x to use hex-values. + + value used for + ----- ---------------------------------------------- + 1 packet reading/writing + 2 MPI details + 4 ciphers and primes (may reveal sensitive data) + 8 iobuf filter functions + 16 iobuf stuff + 32 memory allocation stuff + 64 caching + 128 show memory statistics at exit + Other Notes + ----------- + This is work in progress, so you may find duplicated code fragments, + ugly data structures, weird usage of filenames and other thinks. + I will run "indent" over the source when making a real distribution, + but for now I stick to my own formatting rules. + Compression does not work always; this is the reason that "-z 0" + is the default. + + This will be cleaned up of course. + + The primary FTP site is "ftp://ftp.guug.de/pub/gcrypt/" + The primary WWW page is "http://www.d.shuttle.de/isil/g10.html" + + Please direct bug reports to or better + post them to the mailing list . + + Have fun + + Werner diff --git a/TODO b/TODO index 429148048..064758907 100644 --- a/TODO +++ b/TODO @@ -5,7 +5,6 @@ * add a way to difference between errors and eof in the underflow/flush function of iobuf. * check that all output is filtered when displayed. - * keyring editing * add trust stuff * make ttyio.c work (hide passwords etc..) * use correct ASN values for DEK encoding diff --git a/cipher/elgamal.c b/cipher/elgamal.c index 3cc632525..1f1699f8f 100644 --- a/cipher/elgamal.c +++ b/cipher/elgamal.c @@ -149,7 +149,7 @@ elg_generate( ELG_public_key *pk, ELG_secret_key *sk, unsigned nbits ) do { if( DBG_CIPHER ) fputc('.', stderr); - mpi_set_bytes( x, nbits, get_random_byte, 1 ); /* fixme: should be 2 */ + mpi_set_bytes( x, nbits, get_random_byte, 2 ); } while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, p_min1 )<0 ) ); y = mpi_alloc(nbits/BITS_PER_MPI_LIMB); diff --git a/cipher/primegen.c b/cipher/primegen.c index b7029c4a4..8a72973e2 100644 --- a/cipher/primegen.c +++ b/cipher/primegen.c @@ -52,7 +52,7 @@ generate_public_prime( unsigned nbits ) { MPI prime; - prime = gen_prime( nbits, 0, 1 ); /* fixme: change to 2 */ + prime = gen_prime( nbits, 0, 2 ); fputc('\n', stderr); return prime; } @@ -70,6 +70,8 @@ generate_elg_prime( unsigned pbits, unsigned qbits, MPI g ) MPI prime; /* prime test value */ byte *perms = NULL; int i, j; + int count1, count2; + unsigned nprime; /* find number of needed prime factors */ for(n=1; (pbits - qbits - 1) / n >= qbits; n++ ) @@ -80,33 +82,32 @@ generate_elg_prime( unsigned pbits, unsigned qbits, MPI g ) fbits = (pbits - qbits -1) / n; while( qbits + n*fbits < pbits ) qbits++; - qbits++; /* one mpre to increase tzhe chance to get a weel formed prime*/ - log_debug("gen prime: pbits=%u qbits=%u fbits=%u n=%d\n", + if( DBG_CIPHER ) + log_debug("gen prime: pbits=%u qbits=%u fbits=%u n=%d\n", pbits, qbits, fbits, n ); prime = mpi_alloc( (pbits + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB ); - q = gen_prime( qbits, 0, 0 ); /* fixme: should be 2 */ - fputc('\n', stderr); + q = gen_prime( qbits, 0, 2 ); /* allocate an array to hold the factors + 2 for later usage */ factors = m_alloc_clear( (n+2) * sizeof *factors ); - /* make a pool of 2n+5 primes (this is an arbitrary value) */ - m = n*2+5; - if( m < 20 ) - m = 20; + /* make a pool of 3n+5 primes (this is an arbitrary value) */ + m = n*3+5; + if( m < 25 ) + m = 25; pool = m_alloc_clear( m * sizeof *pool ); /* permutate over the pool of primes */ + count1=count2=0; do { next_try: if( !perms ) { /* allocate new primes */ for(i=0; i < m; i++ ) { mpi_free(pool[i]); - pool[i] = gen_prime( fbits, 0, 0 ); /* fixme: should be 2 */ + pool[i] = gen_prime( fbits, 0, 2 ); } - fputc('\n', stderr); /* init m_out_of_n() */ perms = m_alloc_clear( m ); for(i=0; i < n; i++ ) { @@ -131,18 +132,43 @@ generate_elg_prime( unsigned pbits, unsigned qbits, MPI g ) for(i=0; i < n; i++ ) mpi_mul( prime, prime, factors[i] ); mpi_add_ui( prime, prime, 1 ); - } while( !( mpi_get_nbits( prime ) == pbits && check_prime( prime )) ); - putc('\n', stderr); + nprime = mpi_get_nbits(prime); + if( nprime < pbits ) { + if( ++count1 > 20 ) { + count1 = 0; + qbits++; + fputc('>', stderr); + q = gen_prime( qbits, 0, 2 ); + goto next_try; + } + } + else + count1 = 0; + if( nprime > pbits ) { + if( ++count2 > 20 ) { + count2 = 0; + qbits--; + fputc('<', stderr); + q = gen_prime( qbits, 0, 2 ); + goto next_try; + } + } + else + count2 = 0; + } while( !(nprime == pbits && check_prime( prime )) ); - log_mpidump( "prime : ", prime ); - log_mpidump( "factor q: ", q ); - for(i=0; i < n; i++ ) - log_mpidump( "factor pi: ", factors[i] ); - log_debug("bit sizes: prime=%u, q=%u",mpi_get_nbits(prime), mpi_get_nbits(q) ); - for(i=0; i < n; i++ ) - fprintf(stderr, ", p%d=%u", i, mpi_get_nbits(factors[i]) ); - putc('\n', stderr); + if( DBG_CIPHER ) { + putc('\n', stderr); + log_mpidump( "prime : ", prime ); + log_mpidump( "factor q: ", q ); + for(i=0; i < n; i++ ) + log_mpidump( "factor pi: ", factors[i] ); + log_debug("bit sizes: prime=%u, q=%u", mpi_get_nbits(prime), mpi_get_nbits(q) ); + for(i=0; i < n; i++ ) + fprintf(stderr, ", p%d=%u", i, mpi_get_nbits(factors[i]) ); + putc('\n', stderr); + } if( g ) { /* create a generator (start with 3)*/ MPI tmp = mpi_alloc( mpi_get_nlimbs(prime) ); @@ -155,22 +181,30 @@ generate_elg_prime( unsigned pbits, unsigned qbits, MPI g ) mpi_set_ui(g,2); do { mpi_add_ui(g, g, 1); - log_mpidump("checking g: ", g ); + if( DBG_CIPHER ) { + log_debug("checking g: "); + mpi_print( stderr, g, 1 ); + } + else + fputc('^', stderr); for(i=0; i < n+2; i++ ) { - log_mpidump(" against: ", factors[i] ); + fputc('~', stderr); mpi_fdiv_q(tmp, pmin1, factors[i] ); /* (no mpi_pow(), but it is okay to use this with mod prime) */ mpi_powm(b, g, tmp, prime ); if( !mpi_cmp_ui(b, 1) ) break; } - } while( i < n ); + if( DBG_CIPHER ) + fputc('\n', stderr); + } while( i < n+2 ); mpi_free(factors[n+1]); mpi_free(tmp); mpi_free(b); mpi_free(pmin1); - log_mpidump("found g: ", g ); } + if( !DBG_CIPHER ) + putc('\n', stderr); m_free( factors ); /* (factors are shallow copies) */ for(i=0; i < m; i++ ) @@ -232,7 +266,6 @@ gen_prime( unsigned nbits, int secret, int randomlevel ) } if( x ) continue; /* found a multiple of a already known prime */ - fputc('.', stderr); mpi_add_ui( prime, prime, step ); @@ -267,6 +300,7 @@ gen_prime( unsigned nbits, int secret, int randomlevel ) m_free(mods); return prime; } + fputc('.', stderr); } fputc(':', stderr); /* restart with a new random value */ } @@ -289,7 +323,6 @@ check_prime( MPI prime ) if( mpi_divisible_ui( prime, x ) ) return 0; } - fputc('.', stderr); #if 0 result = mpi_alloc( mpi_get_nlimbs(prime) ); @@ -308,6 +341,7 @@ check_prime( MPI prime ) /* perform stronger tests */ if( is_prime(prime, 5, &count ) ) return 1; /* is probably a prime */ + fputc('.', stderr); return 0; } diff --git a/cipher/random.c b/cipher/random.c index 2848aad74..83efc4b78 100644 --- a/cipher/random.c +++ b/cipher/random.c @@ -30,7 +30,7 @@ struct cache { int len; - byte buffer[100]; /* fixme: should be allocalted with m_alloc_secure()*/ + byte buffer[100]; /* fixme: should be allocated with m_alloc_secure()*/ }; static struct cache cache[3]; diff --git a/g10/Makefile.am b/g10/Makefile.am index eb3e8b238..e13459e97 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -1,6 +1,7 @@ ## Process this file with automake to produce Makefile.in INCLUDES = -I$(top_srcdir)/include +EXTRA_DIST = OPTIONS bin_PROGRAMS = g10 diff --git a/g10/Makefile.in b/g10/Makefile.in index 8aeca74c4..6ce262c02 100644 --- a/g10/Makefile.in +++ b/g10/Makefile.in @@ -39,6 +39,7 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ transform = @program_transform_name@ INCLUDES = -I$(top_srcdir)/include +EXTRA_DIST = OPTIONS bin_PROGRAMS = g10 diff --git a/g10/OPTIONS b/g10/OPTIONS new file mode 100644 index 000000000..dc5f3158f --- /dev/null +++ b/g10/OPTIONS @@ -0,0 +1,135 @@ +# This is a sample option file +# +# Unless you you specify which option file to use with the +# commandline option "--options filename", g10 uses per +# default the file ~/.g10/options. +# +# An option file can contain all long options which are +# available in G10. If the first non white space character of +# a line is a '#', this line is ignored. Empty lines are also +# ignored. +# +# Here is a list of all possible options. Not of all them make +# sense in an option file; consider this as a complete option +# reference + +add-key +# add key to the public keyring + +armor +# create ascii armored output + + +batch +# batch mode: never ask + +cache-all +# hold everything in memory + +change-passphrase +# change the passphrase of your secret keyring + +check +# check a signature + +check-key +# check signatures on a key in the keyring + +debug value|hexvalue +# set debugging flags, + +debug-all +# enable full debugging + +decrypt +# decrypt data (default) + +delete-key +# remove key from public keyring, + +detach-sign +# make a detached signature, + +dry-run +# don't make any changes + +encrypt +# encrypt data + +fingerprint +# show the fingerprints, + +gen-key +# generate a new key pair, + +gen-prime +# Generate a prime. +# With one argument: take it as the bitsize and make a simple prime of +# this size +# With two arguments: Generate a prime, usable for DL algorithms. +# With three arguments: same as above, but a third argument indicates +# taht a generator should also be calculated. + +keyring filename +# add this filename to the list of keyrings + +local-user user-string +# use this user-string to sign or decrypt + +no +# assume no on most questions + +no-armor +# Assume the input data is not in ascii armored format. + +no-default-keyring +# Do not add the default keyrings to the list of keyrings + +options filename +# Ignored in option files. + +output filename +# use filename for output + +print-mds +# print all message digests of all give filenames + +remote-user +# use this user-id for encryption" + + +secret-keyring filename +# add filename to the list of secret keyrings + +sign +# make a signature + +sign-key +# make a signature on a key in the keyring +# Argument is the userid of the key to sign. +# This looks for the key, displays the key and checks all +# existing signatures of this key. If the key is not yet signed +# by the default user (or the users given with "-l"), the programm +# displays the information of the key again, together with +# it's fingerprint and asked wehter it should be signed. This question +# is repeated for all users specified with "-l". The key is then signed +# and the keyring which contains the key is updated. + +store +# simply packs the input data into a rfc1991 packet format + +symmetric +# encrypt the input only with the symmetric (conventional) cipher. +# This asks for a passphrase. + +test +# Used for testing some parts of the program + +verbose +# Give more informations suring processing. If used 2 times, the input data +# is listed in detail. + +yes +# assume yes on most questions + + diff --git a/g10/g10.c b/g10/g10.c index aab502ede..a8a278997 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -131,8 +131,9 @@ main( int argc, char **argv ) { 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" }, - { 518, "config" , 2, "use this config file" }, + { 518, "options" , 2, "read options from file" }, { 519, "no-armor", 0, "\r"}, + { 520, "no-default-keyring", 0, "\r" }, {0} }; ARGPARSE_ARGS pargs; @@ -155,9 +156,10 @@ main( int argc, char **argv ) int parse_verbose = 0; int default_config =1; int errors=0; + int default_keyring = 1; - opt.compress = -1; /* defaults to default compression level */ + opt.compress = 0; /* defaults to no compression level */ /* check wether we have a config file on the commandline */ orig_argc = argc; @@ -212,10 +214,7 @@ main( int argc, char **argv ) case 'z': opt.compress = pargs.r.ret_int; break; case 'a': opt.armor = 1; opt.no_armor=0; break; case 'c': action = aSym; break; - case 'o': opt.outfile = pargs.r.ret_str; - if( opt.outfile[0] == '-' && !opt.outfile[1] ) - opt.outfile_is_stdout = 1; - break; + case 'o': opt.outfile = pargs.r.ret_str; break; case 'e': action = action == aSign? aSignEncr : aEncr; break; case 'b': detached_sig = 1; /* fall trough */ @@ -257,6 +256,7 @@ main( int argc, char **argv ) } break; case 519: opt.no_armor=1; opt.armor=0; break; + case 520: default_keyring = 0; break; default : errors++; pargs.err = configfp? 1:2; break; } } @@ -280,12 +280,12 @@ main( int argc, char **argv ) fputs(s, stderr); } - if( !sec_nrings ) { /* add default secret rings */ + if( !sec_nrings || default_keyring ) { /* add default secret rings */ char *p = make_filename("~/.g10", "secring.g10", NULL ); add_secret_keyring(p); m_free(p); } - if( !nrings ) { /* add default ring */ + if( !nrings || default_keyring ) { /* add default ring */ char *p = make_filename("~/.g10", "pubring.g10", NULL ); add_keyring(p); m_free(p); @@ -331,6 +331,7 @@ main( int argc, char **argv ) case aSignEncr: /* sign and encrypt the given file */ + log_fatal("signing and encryption is not yet implemented\n"); usage(1); /* FIXME */ break; diff --git a/g10/keygen.c b/g10/keygen.c index b171b0676..2582f9b47 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -39,17 +39,6 @@ #endif -static int -answer_is_yes( const char *s ) -{ - if( !stricmp(s, "yes") ) - return 1; - if( *s == 'y' && !s[1] ) - return 1; - if( *s == 'Y' && !s[1] ) - return 1; - return 0; -} static u16 @@ -356,7 +345,7 @@ generate_keypair() else if( algo == 3 ) { algo = PUBKEY_ALGO_DSA; algo_name = "DSA"; - break; + tty_printf("Sorry; DSA is not yet supported.\n"); } } @@ -380,8 +369,8 @@ generate_keypair() #endif if( algo == PUBKEY_ALGO_DSA && (nbits < 512 || nbits > 1024) ) tty_printf("DSA does only allow keysizes from 512 to 1024\n"); - else if( nbits < 128 ) /* FIXME: change this to 768 */ - tty_printf("keysize too small; please select a larger one\n"); + else if( nbits < 768 ) + tty_printf("keysize too small; 768 is smallest value allowed.\n"); else if( nbits > 2048 ) { tty_printf("Keysizes larger than 2048 are not suggested, because " "computations take REALLY long!\n"); @@ -441,20 +430,28 @@ generate_keypair() tty_printf( "You need a Passphrase to protect your secret key.\n\n" ); dek = m_alloc_secure( sizeof *dek ); - dek->algo = CIPHER_ALGO_BLOWFISH; - rc = make_dek_from_passphrase( dek , 2 ); - if( rc == -1 ) { - m_free(dek); dek = NULL; - tty_printf( + for(;;) { + dek->algo = CIPHER_ALGO_BLOWFISH; + rc = make_dek_from_passphrase( dek , 2 ); + if( rc == -1 ) { + m_free(dek); dek = NULL; + tty_printf( "You don't what a passphrase - this is probably a *bad* idea!\n" "I will do it anyway. You can change your passphrase at anytime,\n" "using this program with the option \"--change-passphrase\"\n\n" ); - } - else if( rc ) { - m_free(dek); dek = NULL; - m_free(uid); - log_error("Error getting the passphrase: %s\n", g10_errstr(rc) ); - return; + break; + } + else if( rc == G10ERR_PASSPHRASE ) { + tty_printf("passphrase not correctly repeated; try again.\n"); + } + else if( rc ) { + m_free(dek); dek = NULL; + m_free(uid); + log_error("Error getting the passphrase: %s\n", g10_errstr(rc) ); + return; + } + else + break; /* okay */ } @@ -474,6 +471,12 @@ generate_keypair() pub_root = make_comment_node("#created by G10 pre-release " VERSION ); sec_root = make_comment_node("#created by G10 pre-release " VERSION ); + tty_printf( +"We need to generate a lot of random bytes. It is a good idea to perform\n" +"some other action (work in another window, move the mouse, utilize the\n" +"network and the disks) during the prime generation; this gives the random\n" +"number generator a better chance to gain enough entropy.\n" ); + if( algo == PUBKEY_ALGO_ELGAMAL ) rc = gen_elg(nbits, pub_root, sec_root, dek, &skc ); #ifdef HAVE_RSA_CIPHER diff --git a/g10/main.h b/g10/main.h index 13e20a750..0d769c8b0 100644 --- a/g10/main.h +++ b/g10/main.h @@ -37,6 +37,9 @@ int encode_crypt( const char *filename, STRLIST remusr ); int sign_file( const char *filename, int detached, STRLIST locusr ); int sign_key( const char *username, STRLIST locusr ); +/*-- sig-check.c --*/ +int check_key_signature( KBNODE root, KBNODE node ); + /*-- keygen.c --*/ void generate_keypair(void); diff --git a/g10/openfile.c b/g10/openfile.c index 1a840f19c..4b7331dcd 100644 --- a/g10/openfile.c +++ b/g10/openfile.c @@ -87,7 +87,7 @@ open_outfile( const char *iname ) IOBUF a = NULL; int rc; - if( (!iname && !opt.outfile) || opt.outfile_is_stdout ) { + if( !iname && !opt.outfile ) { if( !(a = iobuf_create(NULL)) ) log_error("can't open [stdout]: %s\n", strerror(errno) ); else if( opt.verbose ) diff --git a/g10/options.h b/g10/options.h index 3be6c92c3..8338404ea 100644 --- a/g10/options.h +++ b/g10/options.h @@ -26,7 +26,7 @@ struct { int armor; int compress; char *outfile; - int outfile_is_stdout; + int reserved0; int batch; /* run in batch mode */ int answer_yes; /* answer yes on most questions */ int answer_no; /* answer no on most questions */ diff --git a/g10/passphrase.c b/g10/passphrase.c index 4e5e57bb3..a974ca9f5 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -27,6 +27,7 @@ #include "memory.h" #include "ttyio.h" #include "cipher.h" +#include "keydb.h" static int hash_passphrase( DEK *dek, char *pw ); @@ -44,8 +45,14 @@ get_passphrase_hash( u32 *keyid, char *text ) DEK *dek; if( keyid ) { + char *ustr; tty_printf("\nNeed a pass phrase to unlock the secret key!\n"); - tty_printf("KeyID: %08lX\n\n", keyid[1] ); + tty_printf("KeyID: " ); + ustr = get_user_id_string( keyid ); + tty_print_string( ustr, strlen(ustr) ); + m_free(ustr); + tty_printf("\n\n"); + } if( keyid && (p=getenv("G10PASSPHRASE")) ) { pw = m_alloc_secure(strlen(p)+1); diff --git a/g10/plaintext.c b/g10/plaintext.c index edd12891c..831a81089 100644 --- a/g10/plaintext.c +++ b/g10/plaintext.c @@ -56,13 +56,8 @@ handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx ) fname[pt->namelen] = 0; } - if( !*fname ) { /* no filename given */ - if( opt.outfile_is_stdout ) - fp = stdout; - else { - log_error("no outputfile given\n"); - goto leave; - } + if( !*fname ) { /* no filename given; write to stdout */ + fp = stdout; } else if( overwrite_filep( fname ) ) goto leave; diff --git a/g10/ringedit.c b/g10/ringedit.c index f1b18d24d..05a8bb299 100644 --- a/g10/ringedit.c +++ b/g10/ringedit.c @@ -558,7 +558,7 @@ keyring_delete( KBPOS *kbpos ) } len = kbpos->length; - log_debug("writing a dummy packet of length %lu\n", (ulong)len); + /*log_debug("writing a dummy packet of length %lu\n", (ulong)len);*/ if( len < 2 ) log_bug(NULL); diff --git a/g10/sig-check.c b/g10/sig-check.c index 040c969f5..bbeb3a956 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -198,8 +198,8 @@ signature_check( PKT_signature *sig, MD_HANDLE *digest ) } #endif/*HAVE_RSA_CIPHER*/ else { - log_debug("signature_check: unsupported pubkey algo %d\n", - pkc->pubkey_algo ); + /*log_debug("signature_check: unsupported pubkey algo %d\n", + pkc->pubkey_algo );*/ rc = G10ERR_PUBKEY_ALGO; goto leave; } @@ -219,13 +219,46 @@ signature_check( PKT_signature *sig, MD_HANDLE *digest ) int check_key_signature( KBNODE root, KBNODE node ) { + KBNODE unode; + MD_HANDLE *md; + PKT_public_cert *pkc; + PKT_signature *sig; + int algo; + int rc; + assert( node->pkt->pkttype == PKT_SIGNATURE ); assert( (node->pkt->pkt.signature->sig_class&~3) == 0x10 ); assert( root->pkt->pkttype == PKT_PUBLIC_CERT ); - /*FIXME!!!!!!*/ + pkc = root->pkt->pkt.public_cert; + sig = node->pkt->pkt.signature; - return 0; + if( sig->pubkey_algo == PUBKEY_ALGO_ELGAMAL ) + algo = sig->d.elg.digest_algo; + else if(sig->pubkey_algo == PUBKEY_ALGO_RSA ) + algo = sig->d.rsa.digest_algo; + else + return G10ERR_PUBKEY_ALGO; + if( (rc=md_okay(algo)) ) + return rc; + + unode = find_kbparent( root, node ); + + if( unode && unode->pkt->pkttype == PKT_USER_ID ) { + PKT_user_id *uid = unode->pkt->pkt.user_id; + + md = md_open( algo, 0 ); + hash_public_cert( md, pkc ); + md_write( md, uid->name, uid->len ); + rc = signature_check( sig, md ); + md_close(md); + } + else { + log_error("no user id for key signature packet\n"); + rc = G10ERR_SIG_CLASS; + } + + return rc; } diff --git a/include/util.h b/include/util.h index 23514ad1f..69cfc0bb0 100644 --- a/include/util.h +++ b/include/util.h @@ -84,6 +84,7 @@ char *make_filename( const char *first_part, ... ); /*-- miscutil.c --*/ u32 make_timestamp(void); void print_string( FILE *fp, byte *p, size_t n ); +int answer_is_yes( const char *s ); /*-- strgutil.c --*/ void free_strlist( STRLIST sl ); diff --git a/util/miscutil.c b/util/miscutil.c index 327eae860..d04d1595a 100644 --- a/util/miscutil.c +++ b/util/miscutil.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include "types.h" @@ -52,3 +53,15 @@ print_string( FILE *fp, byte *p, size_t n ) putc(*p, fp); } +int +answer_is_yes( const char *s ) +{ + if( !stricmp(s, "yes") ) + return 1; + if( *s == 'y' && !s[1] ) + return 1; + if( *s == 'Y' && !s[1] ) + return 1; + return 0; +} +