summaryrefslogtreecommitdiffstats
path: root/g10/keygen.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--g10/keygen.c222
1 files changed, 136 insertions, 86 deletions
diff --git a/g10/keygen.c b/g10/keygen.c
index 96c68334e..1be65c42e 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -1636,94 +1636,141 @@ ask_key_flags(int algo,int subkey)
}
-/****************
- * Returns: 0 to create both a DSA and a Elgamal key.
- * and only if key flags are to be written the desired usage.
- */
+/* Ask for an algorithm. The function returns the algorithm id to
+ * create. If ADDMODE is false the function won't show an option to
+ * create the primary and subkey combined and won't set R_USAGE
+ * either. If a combined algorithm has been selected, the subkey
+ * algorithm is stored at R_SUBKEY_ALGO. */
static int
-ask_algo (int addmode, unsigned int *r_usage)
+ask_algo (int addmode, int *r_subkey_algo, unsigned int *r_usage)
{
- char *answer;
- int algo;
-
- *r_usage = 0;
- tty_printf(_("Please select what kind of key you want:\n"));
- if( !addmode )
- tty_printf(_(" (%d) DSA and Elgamal (default)\n"), 1 );
- tty_printf( _(" (%d) DSA (sign only)\n"), 2 );
- if (opt.expert)
- tty_printf( _(" (%d) DSA (set your own capabilities)\n"), 3 );
- if( addmode )
- tty_printf(_(" (%d) Elgamal (encrypt only)\n"), 4 );
- tty_printf( _(" (%d) RSA (sign only)\n"), 5 );
- if (addmode)
- tty_printf(_(" (%d) RSA (encrypt only)\n"), 6 );
- if (opt.expert)
- tty_printf( _(" (%d) RSA (set your own capabilities)\n"), 7 );
+ char *answer;
+ int algo;
+ int dummy_algo;
- for(;;) {
- answer = cpr_get("keygen.algo",_("Your selection? "));
- cpr_kill_prompt();
- algo = *answer? atoi(answer): 1;
- xfree(answer);
- if( algo == 1 && !addmode ) {
- algo = 0; /* create both keys */
- break;
+ if (!r_subkey_algo)
+ r_subkey_algo = &dummy_algo;
+
+ tty_printf (_("Please select what kind of key you want:\n"));
+
+ if (!addmode)
+ tty_printf (_(" (%d) RSA and RSA (default)\n"), 1 );
+ if (!addmode)
+ tty_printf (_(" (%d) DSA and Elgamal\n"), 2 );
+
+ tty_printf (_(" (%d) DSA (sign only)\n"), 3 );
+ tty_printf (_(" (%d) RSA (sign only)\n"), 4 );
+
+ if (addmode)
+ {
+ tty_printf (_(" (%d) Elgamal (encrypt only)\n"), 5 );
+ tty_printf (_(" (%d) RSA (encrypt only)\n"), 6 );
+ }
+ if (opt.expert)
+ {
+ tty_printf (_(" (%d) DSA (set your own capabilities)\n"), 7 );
+ tty_printf (_(" (%d) RSA (set your own capabilities)\n"), 8 );
+ }
+
+ for(;;)
+ {
+ *r_usage = 0;
+ *r_subkey_algo = 0;
+ answer = cpr_get ("keygen.algo", _("Your selection? "));
+ cpr_kill_prompt ();
+ algo = *answer? atoi (answer) : 1;
+ xfree(answer);
+ if (algo == 1 && !addmode)
+ {
+ algo = PUBKEY_ALGO_RSA;
+ *r_subkey_algo = PUBKEY_ALGO_RSA;
+ break;
}
- else if( algo == 7 && opt.expert ) {
- algo = PUBKEY_ALGO_RSA;
- *r_usage=ask_key_flags(algo,addmode);
- break;
+ else if (algo == 2 && !addmode)
+ {
+ algo = PUBKEY_ALGO_DSA;
+ *r_subkey_algo = PUBKEY_ALGO_ELGAMAL_E;
+ break;
}
- else if( algo == 6 && addmode ) {
- algo = PUBKEY_ALGO_RSA;
- *r_usage = PUBKEY_USAGE_ENC;
- break;
+ else if (algo == 3)
+ {
+ algo = PUBKEY_ALGO_DSA;
+ *r_usage = PUBKEY_USAGE_SIG;
+ break;
}
- else if( algo == 5 ) {
- algo = PUBKEY_ALGO_RSA;
- *r_usage = PUBKEY_USAGE_SIG;
- break;
+ else if (algo == 4)
+ {
+ algo = PUBKEY_ALGO_RSA;
+ *r_usage = PUBKEY_USAGE_SIG;
+ break;
}
- else if( algo == 4 && addmode ) {
- algo = PUBKEY_ALGO_ELGAMAL_E;
- *r_usage = PUBKEY_USAGE_ENC;
- break;
+ else if (algo == 5 && addmode)
+ {
+ algo = PUBKEY_ALGO_ELGAMAL_E;
+ *r_usage = PUBKEY_USAGE_ENC;
+ break;
}
- else if( algo == 3 && opt.expert ) {
- algo = PUBKEY_ALGO_DSA;
- *r_usage=ask_key_flags(algo,addmode);
- break;
+ else if (algo == 6 && addmode)
+ {
+ algo = PUBKEY_ALGO_RSA;
+ *r_usage = PUBKEY_USAGE_ENC;
+ break;
}
- else if( algo == 2 ) {
- algo = PUBKEY_ALGO_DSA;
- *r_usage = PUBKEY_USAGE_SIG;
- break;
+ else if (algo == 7 && opt.expert)
+ {
+ algo = PUBKEY_ALGO_DSA;
+ *r_usage = ask_key_flags (algo, addmode);
+ break;
}
- else
- tty_printf(_("Invalid selection.\n"));
+ else if (algo == 8 && opt.expert)
+ {
+ algo = PUBKEY_ALGO_RSA;
+ *r_usage = ask_key_flags (algo, addmode);
+ break;
+ }
+ else
+ tty_printf (_("Invalid selection.\n"));
}
-
- return algo;
+
+ return algo;
}
+/* Ask for the key size. ALGO is the algorithjm. If PRIMARY_KEYSIZE
+ is not 0, the function asks for the size of the encryption
+ subkey. */
static unsigned
-ask_keysize( int algo )
+ask_keysize (int algo, unsigned int primary_keysize)
{
unsigned int nbits, min, def=2048, max=4096;
+ int for_subkey = !!primary_keysize;
+ int autocomp = 0;
if(opt.expert)
min=512;
else
min=1024;
+ if (primary_keysize && !opt.expert)
+ {
+ /* Deduce the subkey size from the primary key size. */
+ if (algo == PUBKEY_ALGO_DSA && primary_keysize > 3072)
+ nbits = 3072; /* For performance reasons we don't support more
+ than 3072 bit DSA. However we won't see this
+ case anyway because DSA can't be used as an
+ encryption subkey ;-). */
+ else
+ nbits = primary_keysize;
+ autocomp = 1;
+ goto leave;
+ }
+
switch(algo)
{
case PUBKEY_ALGO_DSA:
if(opt.flags.dsa2)
{
- def=1024;
+ def=2048;
max=3072;
}
else
@@ -1743,18 +1790,16 @@ ask_keysize( int algo )
for(;;)
{
- char *prompt,*answer;
-
-#define PROMPTSTRING _("What keysize do you want? (%u) ")
-
- prompt=xmalloc(strlen(PROMPTSTRING)+20);
- sprintf(prompt,PROMPTSTRING,def);
+ char *prompt, *answer;
-#undef PROMPTSTRING
-
- answer = cpr_get("keygen.size",prompt);
- cpr_kill_prompt();
- nbits = *answer? atoi(answer): def;
+ if (for_subkey)
+ prompt = xasprintf (_("What keysize do you want "
+ "for the subkey? (%u) "), def);
+ else
+ prompt = xasprintf (_("What keysize do you want? (%u) "), def);
+ answer = cpr_get ("keygen.size", prompt);
+ cpr_kill_prompt ();
+ nbits = *answer? atoi (answer): def;
xfree(prompt);
xfree(answer);
@@ -1767,15 +1812,18 @@ ask_keysize( int algo )
tty_printf(_("Requested keysize is %u bits\n"), nbits );
+ leave:
if( algo == PUBKEY_ALGO_DSA && (nbits % 64) )
{
nbits = ((nbits + 63) / 64) * 64;
- tty_printf(_("rounded up to %u bits\n"), nbits );
+ if (!autocomp)
+ tty_printf(_("rounded up to %u bits\n"), nbits );
}
else if( (nbits % 32) )
{
nbits = ((nbits + 31) / 32) * 32;
- tty_printf(_("rounded up to %u bits\n"), nbits );
+ if (!autocomp)
+ tty_printf(_("rounded up to %u bits\n"), nbits );
}
return nbits;
@@ -3003,16 +3051,19 @@ generate_keypair (const char *fname, const char *card_serialno,
}
else
{
- algo = ask_algo( 0, &use );
- if( !algo )
- { /* default: DSA with ElG subkey of the specified size */
+ int subkey_algo;
+
+ algo = ask_algo (0, &subkey_algo, &use);
+ if (subkey_algo)
+ {
+ /* Create primary and subkey at once. */
both = 1;
r = xmalloc_clear( sizeof *r + 20 );
r->key = pKEYTYPE;
- sprintf( r->u.value, "%d", PUBKEY_ALGO_DSA );
+ sprintf( r->u.value, "%d", algo );
r->next = para;
para = r;
- nbits = ask_keysize( PUBKEY_ALGO_DSA );
+ nbits = ask_keysize (algo, 0);
r = xmalloc_clear( sizeof *r + 20 );
r->key = pKEYLENGTH;
sprintf( r->u.value, "%u", nbits);
@@ -3024,10 +3075,9 @@ generate_keypair (const char *fname, const char *card_serialno,
r->next = para;
para = r;
- algo = PUBKEY_ALGO_ELGAMAL_E;
r = xmalloc_clear( sizeof *r + 20 );
r->key = pSUBKEYTYPE;
- sprintf( r->u.value, "%d", algo );
+ sprintf( r->u.value, "%d", subkey_algo);
r->next = para;
para = r;
r = xmalloc_clear( sizeof *r + 20 );
@@ -3055,10 +3105,10 @@ generate_keypair (const char *fname, const char *card_serialno,
r->next = para;
para = r;
}
-
+ nbits = 0;
}
- nbits = ask_keysize( algo );
+ nbits = ask_keysize (algo, nbits);
r = xmalloc_clear( sizeof *r + 20 );
r->key = both? pSUBKEYLENGTH : pKEYLENGTH;
sprintf( r->u.value, "%u", nbits);
@@ -3658,9 +3708,9 @@ generate_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock)
if (rc)
goto leave;
- algo = ask_algo (1, &use);
+ algo = ask_algo (1, NULL, &use);
assert (algo);
- nbits = ask_keysize (algo);
+ nbits = ask_keysize (algo, 0);
expire = ask_expire_interval (0, NULL);
if (!cpr_enabled() && !cpr_get_answer_is_yes("keygen.sub.okay",
_("Really create? (y/N) ")))
@@ -4017,8 +4067,8 @@ gen_card_key_with_backup (int algo, int keyno, int is_primary,
mode_t oldmask;
keyid_from_sk (sk, NULL);
- sprintf (name_buffer,"sk_%08lX%08lX.gpg",
- (ulong)sk->keyid[0], (ulong)sk->keyid[1]);
+ snprintf (name_buffer, sizeof name_buffer, "sk_%08lX%08lX.gpg",
+ (ulong)sk->keyid[0], (ulong)sk->keyid[1]);
fname = make_filename (backup_dir, name_buffer, NULL);
oldmask = umask (077);