aboutsummaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
Diffstat (limited to 'g10')
-rw-r--r--g10/OPTIONS3
-rw-r--r--g10/cipher.c9
-rw-r--r--g10/encode.c6
-rw-r--r--g10/encr-data.c3
-rw-r--r--g10/g10.c39
-rw-r--r--g10/keygen.c102
-rw-r--r--g10/keyid.c127
-rw-r--r--g10/main.h4
-rw-r--r--g10/mainproc.c2
-rw-r--r--g10/options.h6
-rw-r--r--g10/pubkey-enc.c5
-rw-r--r--g10/seskey.c4
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 */
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 <[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");
}