aboutsummaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
Diffstat (limited to 'g10')
-rw-r--r--g10/ChangeLog19
-rw-r--r--g10/g10.c15
-rw-r--r--g10/keygen.c537
-rw-r--r--g10/main.h2
4 files changed, 502 insertions, 71 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index ac7e6c846..3b21ace0c 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,22 @@
+2000-03-08 10:38:38 Werner Koch ([email protected])
+
+ * keygen.c (ask_algo): Removed is_v4 return value and the commented
+ code to create Elg keys in a v3 packet. Removed the rounding
+ of key sizes here.
+ (do_create): Likewise removed arg v4_packet.
+ (gen_elg): Likewise removed arg version. Now rounding keysizes here.
+ (gen_dsa): Rounding keysize now here.
+ (release_parameter_list): New
+ (get_parameter*): New.
+ (proc_parameter_file): New.
+ (read_parameter_file): New.
+ (generate_keypair): Splitted. Now uses read_parameter_file when in
+ batch mode. Additional argument to specify a parameter file.
+ (do_generate_keypair): Main bulk of above fucntion and uses the
+ parameter list.
+ (do_create): Don't print long notice in batch mode.
+ * g10.c (main): Allow batched key generation.
+
Thu Mar 2 15:37:46 CET 2000 Werner Koch <[email protected]>
* pubkey-enc.c (get_it): Print a note about unknown cipher algos.
diff --git a/g10/g10.c b/g10/g10.c
index ae04184b9..38cd4bbec 100644
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -1258,10 +1258,17 @@ main( int argc, char **argv )
wrong_args(_("-k[v][v][v][c] [user-id] [keyring]") );
break;
- case aKeygen: /* generate a key (interactive) */
- if( argc )
- wrong_args("--gen-key");
- generate_keypair();
+ case aKeygen: /* generate a key */
+ if( opt.batch ) {
+ if( argc > 1 )
+ wrong_args("--gen-key [parameterfile]");
+ generate_keypair( argc? *argv : NULL );
+ }
+ else {
+ if( argc )
+ wrong_args("--gen-key");
+ generate_keypair(NULL);
+ }
break;
case aFastImport:
diff --git a/g10/keygen.c b/g10/keygen.c
index 11c840786..2ed5a70e4 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -35,6 +35,37 @@
#include "status.h"
#include "i18n.h"
+enum para_name {
+ pKEYTYPE,
+ pKEYLENGTH,
+ pSUBKEYTYPE,
+ pSUBKEYLENGTH,
+ pNAMEREAL,
+ pNAMEEMAIL,
+ pNAMECOMMENT,
+ pUSERID,
+ pEXPIREDATE,
+ pKEYEXPIRE, /* in n seconds */
+ pSUBKEYEXPIRE, /* in n seconds */
+ pPASSPHRASE,
+ pPASSPHRASE_DEK,
+ pPASSPHRASE_S2K
+};
+
+struct para_data_s {
+ struct para_data_s *next;
+ int lnr;
+ enum para_name key;
+ union {
+ DEK *dek;
+ STRING2KEY *s2k;
+ char value[1];
+ } u;
+};
+
+
+static void do_generate_keypair( struct para_data_s *para );
+
static void
write_uid( KBNODE root, const char *s )
@@ -192,8 +223,7 @@ write_keybinding( KBNODE root, KBNODE pub_root, PKT_secret_key *sk )
static int
gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
- STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval,
- int version )
+ STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval )
{
int rc;
int i;
@@ -204,6 +234,17 @@ gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
MPI *factors;
assert( is_ELGAMAL(algo) );
+
+ if( nbits < 512 ) {
+ nbits = 1024;
+ log_info(_("keysize invalid; using %u bits\n"), nbits );
+ }
+
+ if( (nbits % 32) ) {
+ nbits = ((nbits + 31) / 32) * 32;
+ log_info(_("keysize rounded up to %u bits\n"), nbits );
+ }
+
rc = pubkey_generate( algo, nbits, skey, &factors );
if( rc ) {
log_error("pubkey_generate failed: %s\n", g10_errstr(rc) );
@@ -213,7 +254,7 @@ gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
sk = m_alloc_clear( sizeof *sk );
pk = m_alloc_clear( sizeof *pk );
sk->timestamp = pk->timestamp = make_timestamp();
- sk->version = pk->version = version;
+ sk->version = pk->version = 4;
if( expireval ) {
sk->expiredate = pk->expiredate = sk->timestamp + expireval;
}
@@ -267,7 +308,7 @@ gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
* Generate a DSA key
*/
static int
-gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
+gen_dsa(unsigned int nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval )
{
int rc;
@@ -278,8 +319,15 @@ gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
MPI skey[5];
MPI *factors;
- if( nbits > 1024 )
+ if( nbits > 1024 || nbits < 512 ) {
nbits = 1024;
+ log_info(_("keysize invalid; using %u bits\n"), nbits );
+ }
+
+ if( (nbits % 64) ) {
+ nbits = ((nbits + 63) / 64) * 64;
+ log_info(_("keysize rounded up to %u bits\n"), nbits );
+ }
rc = pubkey_generate( PUBKEY_ALGO_DSA, nbits, skey, &factors );
if( rc ) {
@@ -379,7 +427,7 @@ check_valid_days( const char *s )
* Returns: 0 to create both a DSA and a ElGamal key.
*/
static int
-ask_algo( int *ret_v4, int addmode )
+ask_algo( int addmode )
{
char *answer;
int algo;
@@ -391,11 +439,7 @@ ask_algo( int *ret_v4, int addmode )
if( addmode )
tty_printf( _(" (%d) ElGamal (encrypt only)\n"), 3 );
tty_printf( _(" (%d) ElGamal (sign and encrypt)\n"), 4 );
- #if 0
- tty_printf( _(" (%d) ElGamal in a v3 packet\n"), 5 );
- #endif
- *ret_v4 = 1;
for(;;) {
answer = cpr_get("keygen.algo",_("Your selection? "));
cpr_kill_prompt();
@@ -420,13 +464,6 @@ ask_algo( int *ret_v4, int addmode )
algo = PUBKEY_ALGO_DSA;
break;
}
- #if 0
- else if( algo == 5 ) {
- algo = PUBKEY_ALGO_ELGAMAL_E;
- *ret_v4 = 0;
- break;
- }
- #endif
else
tty_printf(_("Invalid selection.\n"));
}
@@ -781,12 +818,12 @@ ask_passphrase( STRING2KEY **ret_s2k )
static int
do_create( int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root,
- DEK *dek, STRING2KEY *s2k, PKT_secret_key **sk, u32 expiredate,
- int v4_packet )
+ DEK *dek, STRING2KEY *s2k, PKT_secret_key **sk, u32 expiredate )
{
int rc=0;
- tty_printf(_(
+ if( !opt.batch )
+ tty_printf(_(
"We need to generate a lot of random bytes. It is a good idea to perform\n"
"some other action (type on the keyboard, move the mouse, utilize the\n"
"disks) during the prime generation; this gives the random number\n"
@@ -794,7 +831,7 @@ do_create( int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root,
if( algo == PUBKEY_ALGO_ELGAMAL || algo == PUBKEY_ALGO_ELGAMAL_E )
rc = gen_elg(algo, nbits, pub_root, sec_root, dek, s2k,
- sk, expiredate, v4_packet? 4:3 );
+ sk, expiredate );
else if( algo == PUBKEY_ALGO_DSA )
rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, sk, expiredate);
else
@@ -835,54 +872,409 @@ generate_user_id()
}
+static void
+release_parameter_list( struct para_data_s *r )
+{
+ struct para_data_s *r2;
+
+ for( ; r ; r = r2 ) {
+ r2 = r->next;
+ if( r->key == pPASSPHRASE_DEK )
+ m_free( r->u.dek );
+ else if( r->key == pPASSPHRASE_S2K )
+ m_free( r->u.s2k );
+
+ m_free(r);
+ }
+}
+
+static struct para_data_s *
+get_parameter( struct para_data_s *para, enum para_name key )
+{
+ struct para_data_s *r;
+
+ for( r = para; r && r->key != key; r = r->next )
+ ;
+ return r;
+}
+
+static const char *
+get_parameter_value( struct para_data_s *para, enum para_name key )
+{
+ struct para_data_s *r = get_parameter( para, key );
+ return (r && *r->u.value)? r->u.value : NULL;
+}
+
+static int
+get_parameter_algo( struct para_data_s *para, enum para_name key )
+{
+ struct para_data_s *r = get_parameter( para, key );
+ if( !r )
+ return -1;
+ if( isdigit( *r->u.value ) )
+ return atoi( r->u.value );
+ return string_to_pubkey_algo( r->u.value );
+}
+
+
+static u32
+get_parameter_u32( struct para_data_s *para, enum para_name key )
+{
+ struct para_data_s *r = get_parameter( para, key );
+
+ if( !r )
+ return 0;
+ return (unsigned int)strtoul( r->u.value, NULL, 10 );
+}
+
+static unsigned int
+get_parameter_uint( struct para_data_s *para, enum para_name key )
+{
+ return get_parameter_u32( para, key );
+}
+
+static DEK *
+get_parameter_dek( struct para_data_s *para, enum para_name key )
+{
+ struct para_data_s *r = get_parameter( para, key );
+ return r? r->u.dek : NULL;
+}
+
+static STRING2KEY *
+get_parameter_s2k( struct para_data_s *para, enum para_name key )
+{
+ struct para_data_s *r = get_parameter( para, key );
+ return r? r->u.s2k : NULL;
+}
+
+
+static int
+proc_parameter_file( struct para_data_s *para, const char *fname )
+{
+ struct para_data_s *r;
+ const char *s1, *s2, *s3;
+ size_t n;
+ char *p;
+ int i;
+
+ /* check that we have all required parameters */
+ assert( get_parameter( para, pKEYTYPE ) );
+ i = get_parameter_algo( para, pKEYTYPE );
+ if( i < 1 || check_pubkey_algo2( i, PUBKEY_USAGE_SIG ) ) {
+ r = get_parameter( para, pKEYTYPE );
+ log_error("%s:%d: invalid algorithm\n", fname, r->lnr );
+ return -1;
+ }
+
+ i = get_parameter_algo( para, pSUBKEYTYPE );
+ if( i > 1 && check_pubkey_algo( i ) ) {
+ r = get_parameter( para, pSUBKEYTYPE );
+ log_error("%s:%d: invalid algorithm\n", fname, r->lnr );
+ return -1;
+ }
+
+ if( !get_parameter_value( para, pUSERID ) ) {
+ /* create the formatted user ID */
+ s1 = get_parameter_value( para, pNAMEREAL );
+ s2 = get_parameter_value( para, pNAMECOMMENT );
+ s3 = get_parameter_value( para, pNAMEEMAIL );
+ if( s1 || s2 || s3 ) {
+ n = (s1?strlen(s1):0) + (s2?strlen(s2):0) + (s3?strlen(s3):0);
+ r = m_alloc_clear( sizeof *r + n + 20 );
+ r->key = pUSERID;
+ p = r->u.value;
+ if( s1 )
+ p = stpcpy(p, s1 );
+ if( s2 )
+ p = stpcpy(stpcpy(stpcpy(p," ("), s2 ),")");
+ if( s3 )
+ p = stpcpy(stpcpy(stpcpy(p," <"), s3 ),">");
+ r->next = para;
+ para = r;
+ }
+ }
+
+ r = get_parameter( para, pPASSPHRASE );
+ if( r && *r->u.value ) {
+ /* we have a plain text passphrase - create a DEK from it.
+ * It is a little bit ridiculous to keep it ih secure memory
+ * but becuase we do this alwasy, why not here */
+ STRING2KEY *s2k;
+ DEK *dek;
+
+ s2k = m_alloc_secure( sizeof *s2k );
+ s2k->mode = opt.s2k_mode;
+ s2k->hash_algo = opt.s2k_digest_algo;
+ set_next_passphrase( r->u.value );
+ dek = passphrase_to_dek( NULL, 0, opt.s2k_cipher_algo, s2k, 2 );
+ set_next_passphrase( NULL );
+ assert( dek );
+ memset( r->u.value, 0, strlen(r->u.value) );
+
+ r = m_alloc_clear( sizeof *r );
+ r->key = pPASSPHRASE_S2K;
+ r->u.s2k = s2k;
+ r->next = para;
+ para = r;
+ r = m_alloc_clear( sizeof *r );
+ r->key = pPASSPHRASE_DEK;
+ r->u.dek = dek;
+ r->next = para;
+ para = r;
+ }
+ do_generate_keypair( para );
+ return 0;
+}
+
+
+/****************
+ * Kludge to allow non interactive key generation controlled
+ * by a parameter file (which currently is only stdin)
+ * Note, that string parameters are expected to be in UTF-8
+ */
+static void
+read_parameter_file( const char *fname )
+{
+ static struct { const char *name;
+ enum para_name key;
+ } keywords[] = {
+ { "Key-Type", pKEYTYPE},
+ { "Key-Length", pKEYLENGTH },
+ { "Subkey-Type", pSUBKEYTYPE },
+ { "Subkey-Length", pSUBKEYLENGTH },
+ { "Name-Real", pNAMEREAL },
+ { "Name-Email", pNAMEEMAIL },
+ { "Name-Comment", pNAMECOMMENT },
+ { "Expire-Date", pEXPIREDATE },
+ { "Passphrase", pPASSPHRASE },
+ { NULL, 0 }
+ };
+ FILE *fp;
+ char line[1024], *p;
+ int lnr;
+ const char *err = NULL;
+ struct para_data_s *para, *r;
+ int i;
+
+ if( !fname || !*fname || !strcmp(fname,"-") ) {
+ fp = stdin;
+ fname = "-";
+ }
+ else {
+ fp = fopen( fname, "r" );
+ if( !fp ) {
+ log_error(_("can't open `%s': %s\n"), fname, strerror(errno) );
+ return;
+ }
+ }
+
+ lnr = 0;
+ err = NULL;
+ para = NULL;
+ while( fgets( line, DIM(line)-1, fp ) ) {
+ char *keyword, *value;
+
+ lnr++;
+ if( *line && line[strlen(line)-1] != '\n' ) {
+ err = "line too long";
+ break;
+ }
+ for( p = line; isspace(*p); p++ )
+ ;
+ if( !*p || *p == '#' )
+ continue;
+ keyword = p;
+ if( *keyword == '%' ) {
+ /* for now these are all comments but in future they may be used
+ * to control certain aspects */
+ continue;
+ }
+
+
+ if( !(p = strchr( p, ':' )) || p == keyword ) {
+ err = "missing colon";
+ break;
+ }
+ *p++ = 0;
+ for( ; isspace(*p); p++ )
+ ;
+ if( !*p ) {
+ err = "missing argument";
+ break;
+ }
+ value = p;
+ trim_trailing_ws( value, strlen(value) );
+
+ for(i=0; keywords[i].name; i++ ) {
+ if( !stricmp( keywords[i].name, keyword ) )
+ break;
+ }
+ if( !keywords[i].name ) {
+ err = "unknown keyword";
+ break;
+ }
+ if( keywords[i].key != pKEYTYPE && !para ) {
+ err = "parameter block does not start with \"Key-Type\"";
+ break;
+ }
+
+ if( keywords[i].key == pKEYTYPE && para ) {
+ proc_parameter_file( para, fname );
+ release_parameter_list( para );
+ para = NULL;
+ }
+ else {
+ for( r = para; r; r = r->next ) {
+ if( r->key == keywords[i].key )
+ break;
+ }
+ if( r ) {
+ err = "duplicate keyword";
+ break;
+ }
+ }
+ r = m_alloc_clear( sizeof *r + strlen( value ) );
+ r->lnr = lnr;
+ r->key = keywords[i].key;
+ strcpy( r->u.value, value );
+ r->next = para;
+ para = r;
+ }
+ if( err )
+ log_error("%s:%d: %s\n", fname, lnr, err );
+ else if( ferror(fp) ) {
+ log_error("%s:%d: read error: %s\n", fname, lnr, strerror(errno) );
+ }
+ else if( para ) {
+ proc_parameter_file( para, fname );
+ }
+ release_parameter_list( para );
+ if( strcmp( fname, "-" ) )
+ fclose(fp);
+}
+
+
/****************
* Generate a keypair
+ * (fname is only used in batch mode)
*/
void
-generate_keypair()
+generate_keypair( const char *fname )
{
- unsigned nbits;
- char *pub_fname = NULL;
- char *sec_fname = NULL;
+ unsigned int nbits;
char *uid = NULL;
- KBNODE pub_root = NULL;
- KBNODE sec_root = NULL;
- PKT_secret_key *sk = NULL;
DEK *dek;
STRING2KEY *s2k;
- int rc;
int algo;
- u32 expire;
- int v4;
int both = 0;
+ u32 expire;
+ struct para_data_s *para = NULL;
+ struct para_data_s *r;
- if( opt.batch || opt.answer_yes || opt.answer_no ) {
- log_error(_("Key generation can only be used in interactive mode\n"));
+ if( opt.batch ) {
+ read_parameter_file( fname );
return;
}
- algo = ask_algo( &v4, 0 );
- if( !algo ) {
- algo = PUBKEY_ALGO_ELGAMAL_E;
+ algo = ask_algo( 0 );
+ if( !algo ) { /* default: DSA with ElG subkey of the specified size */
both = 1;
+ r = m_alloc_clear( sizeof *r + 20 );
+ r->key = pKEYTYPE;
+ sprintf( r->u.value, "%d", PUBKEY_ALGO_DSA );
+ r->next = para;
+ para = r;
tty_printf(_("DSA keypair will have 1024 bits.\n"));
+ r = m_alloc_clear( sizeof *r + 20 );
+ r->key = pKEYLENGTH;
+ strcpy( r->u.value, "1024" );
+ r->next = para;
+ para = r;
+
+ algo = PUBKEY_ALGO_ELGAMAL_E;
+ r = m_alloc_clear( sizeof *r + 20 );
+ r->key = pSUBKEYTYPE;
+ sprintf( r->u.value, "%d", algo );
+ r->next = para;
+ para = r;
}
+ else {
+ r = m_alloc_clear( sizeof *r + 20 );
+ r->key = pKEYTYPE;
+ sprintf( r->u.value, "%d", algo );
+ r->next = para;
+ para = r;
+ }
+
nbits = ask_keysize( algo );
+ r = m_alloc_clear( sizeof *r + 20 );
+ r->key = both? pSUBKEYLENGTH : pKEYLENGTH;
+ sprintf( r->u.value, "%u", nbits);
+ r->next = para;
+ para = r;
+
expire = ask_expire_interval();
+ r = m_alloc_clear( sizeof *r + 20 );
+ r->key = pKEYEXPIRE;
+ sprintf( r->u.value, "%lu", (ulong)expire );
+ r->next = para;
+ para = r;
+ if( both ) {
+ r = m_alloc_clear( sizeof *r + 20 );
+ r->key = pSUBKEYEXPIRE;
+ sprintf( r->u.value, "%lu", (ulong)expire );
+ r->next = para;
+ para = r;
+ }
+
uid = ask_user_id(0);
if( !uid ) {
log_error(_("Key generation canceled.\n"));
+ release_parameter_list( para );
return;
}
+ r = m_alloc_clear( sizeof *r + strlen(uid) );
+ r->key = pUSERID;
+ strcpy( r->u.value, uid );
+ r->next = para;
+ para = r;
+
dek = ask_passphrase( &s2k );
+ if( dek ) {
+ r = m_alloc_clear( sizeof *r );
+ r->key = pPASSPHRASE_DEK;
+ r->u.dek = dek;
+ r->next = para;
+ para = r;
+ r = m_alloc_clear( sizeof *r );
+ r->key = pPASSPHRASE_S2K;
+ r->u.s2k = s2k;
+ r->next = para;
+ para = r;
+ }
+
+ proc_parameter_file( para, "[internal]" );
+ release_parameter_list( para );
+}
+
+static void
+do_generate_keypair( struct para_data_s *para )
+{
+ char *pub_fname = NULL;
+ char *sec_fname = NULL;
+ KBNODE pub_root = NULL;
+ KBNODE sec_root = NULL;
+ PKT_secret_key *sk = NULL;
+ const char *s;
+ int rc;
- /* now check whether we are allowed to write to the keyrings */
+ /* check whether we are allowed to write to the keyrings */
pub_fname = make_filename(opt.homedir, "pubring.gpg", NULL );
sec_fname = make_filename(opt.homedir, "secring.gpg", NULL );
if( opt.verbose ) {
- tty_printf(_("writing public certificate to `%s'\n"), pub_fname );
- tty_printf(_("writing secret certificate to `%s'\n"), sec_fname );
+ log_info(_("writing public certificate to `%s'\n"), pub_fname );
+ log_info(_("writing secret certificate to `%s'\n"), sec_fname );
}
/* we create the packets as a tree of kbnodes. Because the structure
@@ -893,24 +1285,31 @@ generate_keypair()
pub_root = make_comment_node("#"); delete_kbnode(pub_root);
sec_root = make_comment_node("#"); delete_kbnode(sec_root);
- if( both )
- rc = do_create( PUBKEY_ALGO_DSA, 1024, pub_root, sec_root,
- dek, s2k, &sk, expire, 1);
- else
- rc = do_create( algo, nbits, pub_root, sec_root,
- dek, s2k, &sk, expire, v4);
- if( !rc )
- write_uid(pub_root, uid );
- if( !rc )
- write_uid(sec_root, uid );
- if( !rc )
- rc = write_selfsig(pub_root, pub_root, sk);
- if( !rc )
- rc = write_selfsig(sec_root, pub_root, sk);
+ rc = do_create( get_parameter_algo( para, pKEYTYPE ),
+ get_parameter_uint( para, pKEYLENGTH ),
+ pub_root, sec_root,
+ get_parameter_dek( para, pPASSPHRASE_DEK ),
+ get_parameter_s2k( para, pPASSPHRASE_S2K ),
+ &sk,
+ get_parameter_u32( para, pKEYEXPIRE ) );
+ if( !rc && (s=get_parameter_value(para, pUSERID)) ) {
+ write_uid(pub_root, s );
+ if( !rc )
+ write_uid(sec_root, s );
+ if( !rc )
+ rc = write_selfsig(pub_root, pub_root, sk);
+ if( !rc )
+ rc = write_selfsig(sec_root, pub_root, sk);
+ }
- if( both ) {
- rc = do_create( algo, nbits, pub_root, sec_root,
- dek, s2k, NULL, expire, 1 );
+ if( get_parameter( para, pSUBKEYTYPE ) ) {
+ rc = do_create( get_parameter_algo( para, pSUBKEYTYPE ),
+ get_parameter_uint( para, pSUBKEYLENGTH ),
+ pub_root, sec_root,
+ get_parameter_dek( para, pPASSPHRASE_DEK ),
+ get_parameter_s2k( para, pPASSPHRASE_S2K ),
+ NULL,
+ get_parameter_u32( para, pSUBKEYEXPIRE ) );
if( !rc )
rc = write_keybinding(pub_root, pub_root, sk);
if( !rc )
@@ -959,12 +1358,17 @@ generate_keypair()
else if( (rc=insert_keyblock( &sec_kbpos, sec_root )) )
log_error("can't write secret key: %s\n", g10_errstr(rc) );
else {
- tty_printf(_("public and secret key created and signed.\n") );
- if( algo == PUBKEY_ALGO_DSA )
+ if( !opt.batch )
+ tty_printf(_("public and secret key created and signed.\n") );
+ if( !opt.batch
+ && get_parameter_algo( para, pKEYTYPE ) == PUBKEY_ALGO_DSA
+ && !get_parameter( para, pSUBKEYTYPE ) )
+ {
tty_printf(_("Note that this key cannot be used for "
"encryption. You may want to use\n"
"the command \"--edit-key\" to generate a "
"secondary key for this purpose.\n") );
+ }
}
if( !rc1 )
@@ -974,15 +1378,16 @@ generate_keypair()
}
- if( rc )
- tty_printf(_("Key generation failed: %s\n"), g10_errstr(rc) );
+ if( rc ) {
+ if( opt.batch )
+ log_error(_("Key generation failed: %s\n"), g10_errstr(rc) );
+ else
+ tty_printf(_("Key generation failed: %s\n"), g10_errstr(rc) );
+ }
release_kbnode( pub_root );
release_kbnode( sec_root );
if( sk ) /* the unprotected secret key */
free_secret_key(sk);
- m_free(uid);
- m_free(dek);
- m_free(s2k);
m_free(pub_fname);
m_free(sec_fname);
}
@@ -998,7 +1403,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
int okay=0, rc=0;
KBNODE node;
PKT_secret_key *sk = NULL; /* this is the primary sk */
- int v4, algo;
+ int algo;
u32 expire;
unsigned nbits;
char *passphrase = NULL;
@@ -1049,7 +1454,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
goto leave;
- algo = ask_algo( &v4, 1 );
+ algo = ask_algo( 1 );
assert(algo);
nbits = ask_keysize( algo );
expire = ask_expire_interval();
@@ -1066,7 +1471,7 @@ generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
}
rc = do_create( algo, nbits, pub_keyblock, sec_keyblock,
- dek, s2k, NULL, expire, v4 );
+ dek, s2k, NULL, expire );
if( !rc )
rc = write_keybinding(pub_keyblock, pub_keyblock, sk);
if( !rc )
diff --git a/g10/main.h b/g10/main.h
index 9a4969415..5a63fe636 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -92,7 +92,7 @@ void keyedit_menu( const char *username, STRLIST locusr, STRLIST cmds,
/*-- keygen.c --*/
u32 ask_expiredate(void);
-void generate_keypair(void);
+void generate_keypair( const char *fname );
int keygen_add_key_expire( PKT_signature *sig, void *opaque );
int keygen_add_std_prefs( PKT_signature *sig, void *opaque );
int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock );