diff options
author | Werner Koch <wk@gnupg.org> | 2016-12-02 19:43:36 +0100 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2016-12-02 19:47:40 +0100 |
commit | ce29272e24e7b718b8fca9b84bc728e65f3dea24 (patch) | |
tree | 72f0ef8d2f20ed9faf40d332b95a3e3ef75ef1fe /g10 | |
parent | g10: Improve debugging output. (diff) | |
download | gnupg2-ce29272e24e7b718b8fca9b84bc728e65f3dea24.tar.xz gnupg2-ce29272e24e7b718b8fca9b84bc728e65f3dea24.zip |
gpg: New option --default-new-key-algo.
* common/openpgp-oid.c (openpgp_is_curve_supported): Add optional arg
R_ALGO and change all callers.
* common/util.h (GPG_ERR_UNKNOWN_FLAG): New error code.
* g10/options.h (struct opt): Add field DEF_NEW_KEY_ALGO.
* g10/gpg.c (oDefaultNewKeyAlgo): New enum.
(opts): New option "--default-new-key-algo".
(main): Set the option.
* g10/keygen.c: Remove DEFAULT_STD_ FUTURE_STD_ constants and replace
them by ...
(DEFAULT_STD_KEY_PARAM, FUTURE_STD_KEY_PARAM): new string constants.
(get_keysize_range): Remove arg R_DEF and return that value instead.
Change all callers.
(gen_rsa): Use get_keysize_range instead of the removed
DEFAULT_STD_KEYSIZE.
(parse_key_parameter_part): New function.
(parse_key_parameter_string): New function.
(quick_generate_keypair): Refactor using parse_key_parameter_string.
(generate_keypair): Ditto.
(parse_algo_usage_expire): Ditto.
--
This new option is intended to be used in the forthcoming
--set-profile command of gpgconf. It allows to provide a gpg
configuration with custom defaults for a new key using the simple
commands which use the default algorithm set.
Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'g10')
-rw-r--r-- | g10/call-agent.c | 3 | ||||
-rw-r--r-- | g10/gpg.c | 7 | ||||
-rw-r--r-- | g10/keygen.c | 511 | ||||
-rw-r--r-- | g10/options.h | 2 |
4 files changed, 393 insertions, 130 deletions
diff --git a/g10/call-agent.c b/g10/call-agent.c index 1d4bd664c..fd9b96413 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -624,7 +624,8 @@ learn_status_cb (void *opaque, const char *line) parm->key_attr[keyno].nbits = strtoul (line+n+3, NULL, 10); else if (algo == PUBKEY_ALGO_ECDH || algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_EDDSA) - parm->key_attr[keyno].curve = openpgp_is_curve_supported (line+n, NULL); + parm->key_attr[keyno].curve = openpgp_is_curve_supported (line + n, + NULL, NULL); } else if (keywordlen == 12 && !memcmp (keyword, "PRIVATE-DO-", 11) && strchr("1234", keyword[11])) @@ -407,6 +407,7 @@ enum cmd_and_opt_values oPrintDANERecords, oTOFUDefaultPolicy, oTOFUDBFormat, + oDefaultNewKeyAlgo, oWeakDigest, oUnwrap, oOnlySignTextIDs, @@ -836,6 +837,8 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_n (oNoAllowMultipleMessages, "no-allow-multiple-messages", "@"), ARGPARSE_s_n (oAllowWeakDigestAlgos, "allow-weak-digest-algos", "@"), + ARGPARSE_s_s (oDefaultNewKeyAlgo, "default-new-key-algo", "@"), + /* These two are aliases to help users of the PGP command line product use gpg with minimal pain. Many commands are common already as they seem to have borrowed commands from us. Now I'm @@ -3469,6 +3472,10 @@ main (int argc, char **argv) case oNoAutostart: opt.autostart = 0; break; + case oDefaultNewKeyAlgo: + opt.def_new_key_algo = pargs.r.ret_str; + break; + case oNoop: break; default: diff --git a/g10/keygen.c b/g10/keygen.c index d249556db..ad96cdd43 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -48,24 +48,10 @@ /* The default algorithms. If you change them remember to change them also in gpg.c:gpgconf_list. You should also check that the value - is inside the bounds enforced by ask_keysize and gen_xxx. */ -#define DEFAULT_STD_ALGO PUBKEY_ALGO_RSA -#define DEFAULT_STD_KEYSIZE 2048 -#define DEFAULT_STD_KEYUSE (PUBKEY_USAGE_CERT|PUBKEY_USAGE_SIG) -#define DEFAULT_STD_CURVE NULL -#define DEFAULT_STD_SUBALGO PUBKEY_ALGO_RSA -#define DEFAULT_STD_SUBKEYSIZE 2048 -#define DEFAULT_STD_SUBKEYUSE PUBKEY_USAGE_ENC -#define DEFAULT_STD_SUBCURVE NULL - -#define FUTURE_STD_ALGO PUBKEY_ALGO_EDDSA -#define FUTURE_STD_KEYSIZE 0 -#define FUTURE_STD_KEYUSE (PUBKEY_USAGE_CERT|PUBKEY_USAGE_SIG) -#define FUTURE_STD_CURVE "Ed25519" -#define FUTURE_STD_SUBALGO PUBKEY_ALGO_ECDH -#define FUTURE_STD_SUBKEYSIZE 0 -#define FUTURE_STD_SUBKEYUSE PUBKEY_USAGE_ENC -#define FUTURE_STD_SUBCURVE "Curve25519" + is inside the bounds enforced by ask_keysize and gen_xxx. See also + get_keysize_range which encodes the allowed ranges. */ +#define DEFAULT_STD_KEY_PARAM "rsa2048/cert,sign+rsa2048/encr" +#define FUTURE_STD_KEY_PARAM "ed25519/cert,sign+cv25519/encr" /* Flag bits used during key generation. */ #define KEYGEN_FLAG_NO_PROTECTION 1 @@ -157,8 +143,12 @@ static int write_keyblock (iobuf_t out, kbnode_t node); static gpg_error_t gen_card_key (int keyno, int algo, int is_primary, kbnode_t pub_root, u32 *timestamp, u32 expireval); +static unsigned int get_keysize_range (int algo, + unsigned int *min, unsigned int *max); + + static void print_status_key_created (int letter, PKT_public_key *pk, const char *handle) { @@ -1602,7 +1592,7 @@ gen_rsa (int algo, unsigned int nbits, KBNODE pub_root, log_assert (is_RSA(algo)); if (!nbits) - nbits = DEFAULT_STD_KEYSIZE; + nbits = get_keysize_range (algo, NULL, NULL); if (nbits < 1024) { @@ -2056,36 +2046,46 @@ ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage, } -static void -get_keysize_range (int algo, - unsigned int *min, unsigned int *def, unsigned int *max) +static unsigned int +get_keysize_range (int algo, unsigned int *min, unsigned int *max) { - *min = opt.compliance == CO_DE_VS ? 2048: 1024; - *def = DEFAULT_STD_KEYSIZE; - *max = 4096; + unsigned int def; + unsigned int dummy1, dummy2; + + if (!min) + min = &dummy1; + if (!max) + max = &dummy2; - /* Deviations from the standard values. */ switch(algo) { case PUBKEY_ALGO_DSA: *min = opt.expert? 768 : 1024; - *def=2048; *max=3072; + def=2048; break; case PUBKEY_ALGO_ECDSA: case PUBKEY_ALGO_ECDH: *min=256; - *def=256; *max=521; + def=256; break; case PUBKEY_ALGO_EDDSA: *min=255; - *def=255; *max=441; + def=255; + break; + + default: + *min = opt.compliance == CO_DE_VS ? 2048: 1024; + *max = 4096; + def = 2048; break; } + + return def; } @@ -2147,7 +2147,7 @@ ask_keysize (int algo, unsigned int primary_keysize) int for_subkey = !!primary_keysize; int autocomp = 0; - get_keysize_range (algo, &min, &def, &max); + def = get_keysize_range (algo, &min, &max); if (primary_keysize && !opt.expert) { @@ -2854,6 +2854,292 @@ generate_user_id (KBNODE keyblock, const char *uidstr) } +/* Helper for parse_key_parameter_string for one part of the + * specification string; i.e. ALGO/FLAGS. If STRING is NULL or empty + * success is returned. On error an error code is returned. Note + * that STRING may be modified by this function. NULL may be passed + * for any parameter. FOR_SUBKEY shall be true if this is used as a + * subkey. */ +static gpg_error_t +parse_key_parameter_part (char *string, int for_subkey, + int *r_algo, unsigned int *r_size, + unsigned int *r_keyuse, + char const **r_curve) +{ + char *flags; + int algo = 0; + char *endp; + const char *curve = NULL; + int ecdh_or_ecdsa = 0; + unsigned int size; + int keyuse; + int i; + const char *s; + + if (!string || !*string) + return 0; /* Success. */ + + flags = strchr (string, '/'); + if (flags) + *flags++ = 0; + + if (strlen (string) > 3 && digitp (string+3)) + { + if (!ascii_memcasecmp (string, "rsa", 3)) + algo = PUBKEY_ALGO_RSA; + else if (!ascii_memcasecmp (string, "dsa", 3)) + algo = PUBKEY_ALGO_DSA; + else if (!ascii_memcasecmp (string, "elg", 3)) + algo = PUBKEY_ALGO_ELGAMAL_E; + } + if (algo) + { + size = strtoul (string+3, &endp, 10); + if (size < 512 || size > 16384 || *endp) + return gpg_error (GPG_ERR_INV_VALUE); + } + else if ((curve = openpgp_is_curve_supported (string, &algo, &size))) + { + if (!algo) + { + algo = PUBKEY_ALGO_ECDH; /* Default ECC algorithm. */ + ecdh_or_ecdsa = 1; /* We may need to switch the algo. */ + } + } + else + return gpg_error (GPG_ERR_UNKNOWN_CURVE); + + /* Parse the flags. */ + keyuse = 0; + if (flags) + { + char **tokens = NULL; + + tokens = strtokenize (flags, ","); + if (!tokens) + return gpg_error_from_syserror (); + + for (i=0; (s = tokens[i]); i++) + { + if (!*s) + ; + else if (!ascii_strcasecmp (s, "sign")) + keyuse |= PUBKEY_USAGE_SIG; + else if (!ascii_strcasecmp (s, "encrypt") + || !ascii_strcasecmp (s, "encr")) + keyuse |= PUBKEY_USAGE_ENC; + else if (!ascii_strcasecmp (s, "auth")) + keyuse |= PUBKEY_USAGE_AUTH; + else if (!ascii_strcasecmp (s, "cert")) + keyuse |= PUBKEY_USAGE_CERT; + else if (!ascii_strcasecmp (s, "ecdsa")) + { + if (algo == PUBKEY_ALGO_ECDH || algo == PUBKEY_ALGO_ECDSA) + algo = PUBKEY_ALGO_ECDSA; + else + { + xfree (tokens); + return gpg_error (GPG_ERR_INV_FLAG); + } + ecdh_or_ecdsa = 0; + } + else if (!ascii_strcasecmp (s, "ecdh")) + { + if (algo == PUBKEY_ALGO_ECDH || algo == PUBKEY_ALGO_ECDSA) + algo = PUBKEY_ALGO_ECDH; + else + { + xfree (tokens); + return gpg_error (GPG_ERR_INV_FLAG); + } + ecdh_or_ecdsa = 0; + } + else if (!ascii_strcasecmp (s, "eddsa")) + { + /* Not required but we allow it for consistency. */ + if (algo == PUBKEY_ALGO_EDDSA) + ; + else + { + xfree (tokens); + return gpg_error (GPG_ERR_INV_FLAG); + } + } + else + { + xfree (tokens); + return gpg_error (GPG_ERR_UNKNOWN_FLAG); + } + } + + xfree (tokens); + } + + /* If not yet decided switch between ecdh and ecdsa. */ + if (ecdh_or_ecdsa && keyuse) + algo = (keyuse & PUBKEY_USAGE_ENC)? PUBKEY_ALGO_ECDH : PUBKEY_ALGO_ECDSA; + else if (ecdh_or_ecdsa) + algo = for_subkey? PUBKEY_ALGO_ECDH : PUBKEY_ALGO_ECDSA; + + /* Set or fix key usage. */ + if (!keyuse) + { + if (algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_EDDSA + || algo == PUBKEY_ALGO_DSA) + keyuse = PUBKEY_USAGE_SIG; + else if (algo == PUBKEY_ALGO_RSA) + keyuse = for_subkey? PUBKEY_USAGE_ENC : PUBKEY_USAGE_SIG; + else + keyuse = PUBKEY_USAGE_ENC; + } + else if (algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_EDDSA + || algo == PUBKEY_ALGO_DSA) + { + keyuse &= ~PUBKEY_USAGE_ENC; /* Forbid encryption. */ + } + else if (algo == PUBKEY_ALGO_ECDH || algo == PUBKEY_ALGO_ELGAMAL_E) + { + keyuse = PUBKEY_USAGE_ENC; /* Allow only encryption. */ + } + + /* Make sure a primary key can certify. */ + if (!for_subkey) + keyuse |= PUBKEY_USAGE_CERT; + + /* Check that usage is actually possible. */ + if (/**/((keyuse & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_AUTH|PUBKEY_USAGE_CERT)) + && !pubkey_get_nsig (algo)) + || ((keyuse & PUBKEY_USAGE_ENC) + && !pubkey_get_nenc (algo)) + || (for_subkey && (keyuse & PUBKEY_USAGE_CERT))) + return gpg_error (GPG_ERR_WRONG_KEY_USAGE); + + /* Return values. */ + if (r_algo) + *r_algo = algo; + if (r_size) + { + unsigned int min, def, max; + + /* Make sure the keysize is in the allowed range. */ + def = get_keysize_range (algo, &min, &max); + if (!size) + size = def; + else if (size < min) + size = min; + else if (size > max) + size = max; + + *r_size = fixup_keysize (size, algo, 1); + } + if (r_keyuse) + *r_keyuse = keyuse; + if (r_curve) + *r_curve = curve; + + return 0; +} + +/* Parse and return the standard key generation parameter. + * The string is expected to be in this format: + * + * ALGO[/FLAGS][+SUBALGO[/FLAGS]] + * + * Here ALGO is a string in the same format as printed by the + * keylisting. For example: + * + * rsa3072 := RSA with 3072 bit. + * dsa2048 := DSA with 2048 bit. + * elg2048 := Elgamal with 2048 bit. + * ed25519 := EDDSA using curve Ed25519. + * cv25519 := ECDH using curve Curve25519. + * nistp256:= ECDSA or ECDH using curve NIST P-256 + * + * All strings with an unknown prefix are considered an elliptic + * curve. Curves which have no implicit algorithm require that FLAGS + * is given to select whether ECDSA or ECDH is used; this can eoither + * be done using an algorithm keyword or usage keywords. + * + * FLAGS is a comma delimited string of keywords: + * + * cert := Allow usage Certify + * sign := Allow usage Sign + * encr := Allow usage Encrypt + * auth := Allow usage Authentication + * encrypt := Alias for "encr" + * ecdsa := Use algorithm ECDSA. + * eddsa := Use algorithm EdDSA. + * ecdh := Use algorithm ECDH. + * + * There are several defaults and fallbacks depending on the + * algorithm. PART can be used to select which part of STRING is + * used: + * -1 := Both parts + * 0 := Only the part of the primary key + * 1 := Only the part of the secondary key is parsed but returned + * in the args for the primary key (R_ALGO,....) + * + */ +gpg_error_t +parse_key_parameter_string (const char *string, int part, + int *r_algo, unsigned int *r_size, + unsigned *r_keyuse, + char const **r_curve, + int *r_subalgo, unsigned int *r_subsize, + unsigned *r_subkeyuse, + char const **r_subcurve) +{ + gpg_error_t err = 0; + char *primary, *secondary; + + if (r_algo) + *r_algo = 0; + if (r_size) + *r_size = 0; + if (r_keyuse) + *r_keyuse = 0; + if (r_curve) + *r_curve = NULL; + if (r_subalgo) + *r_subalgo = 0; + if (r_subsize) + *r_subsize = 0; + if (r_subkeyuse) + *r_subkeyuse = 0; + if (r_subcurve) + *r_subcurve = NULL; + + if (!string || !*string + || !strcmp (string, "default") || !strcmp (string, "-")) + string = opt.def_new_key_algo? opt.def_new_key_algo : DEFAULT_STD_KEY_PARAM; + else if (!strcmp (string, "future-default")) + string = FUTURE_STD_KEY_PARAM; + + primary = xstrdup (string); + secondary = strchr (primary, '+'); + if (secondary) + *secondary++ = 0; + if (part == -1 || part == 0) + { + err = parse_key_parameter_part (primary, 0, r_algo, r_size, + r_keyuse, r_curve); + if (!err && part == -1) + err = parse_key_parameter_part (secondary, 1, r_subalgo, r_subsize, + r_subkeyuse, r_subcurve); + } + else if (part == 1) + { + err = parse_key_parameter_part (secondary, 1, r_algo, r_size, + r_keyuse, r_curve); + } + + xfree (primary); + + return err; +} + + + /* Append R to the linked list PARA. */ static void append_to_parameter (struct para_data_s *para, struct para_data_s *r) @@ -2926,8 +3212,15 @@ get_parameter_algo( struct para_data_s *para, enum para_name key, if (!ascii_strcasecmp (r->u.value, "default")) { /* Note: If you change this default algo, remember to change it - also in gpg.c:gpgconf_list. */ - i = DEFAULT_STD_ALGO; + * also in gpg.c:gpgconf_list. */ + /* FIXME: We only allow the algo here and have a separate thing + * for the curve etc. That is a ugly but demanded for backward + * compatibility with the batch key generation. It would be + * better to make full use of parse_key_parameter_string. */ + parse_key_parameter_string (NULL, 0, + &i, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + if (r_default) *r_default = 1; } @@ -2952,8 +3245,8 @@ get_parameter_algo( struct para_data_s *para, enum para_name key, /* Parse a usage string. The usage keywords "auth", "sign", "encr" - * may be elimited by space, tab, or comma. On error -1 is returned - * instead of the usage flags/ */ + * may be delimited by space, tab, or comma. On error -1 is returned + * instead of the usage flags. */ static int parse_usagestr (const char *usagestr) { @@ -3639,25 +3932,27 @@ quick_generate_keypair (ctrl_t ctrl, const char *uid, const char *algostr, && (!*usagestr || !strcmp (usagestr, "default") || !strcmp (usagestr, "-"))) { - if (!strcmp (algostr, "future-default")) - { - para = quickgen_set_para (para, 0, - FUTURE_STD_ALGO, FUTURE_STD_KEYSIZE, - FUTURE_STD_CURVE, 0); - para = quickgen_set_para (para, 1, - FUTURE_STD_SUBALGO, FUTURE_STD_SUBKEYSIZE, - FUTURE_STD_SUBCURVE, 0); - } - else + /* Use default key parameters. */ + int algo, subalgo; + unsigned int size, subsize; + unsigned int keyuse, subkeyuse; + const char *curve, *subcurve; + + err = parse_key_parameter_string (algostr, -1, + &algo, &size, &keyuse, &curve, + &subalgo, &subsize, &subkeyuse, + &subcurve); + if (err) { - para = quickgen_set_para (para, 0, - DEFAULT_STD_ALGO, DEFAULT_STD_KEYSIZE, - DEFAULT_STD_CURVE, 0); - para = quickgen_set_para (para, 1, - DEFAULT_STD_SUBALGO, DEFAULT_STD_SUBKEYSIZE, - DEFAULT_STD_SUBCURVE, 0); + log_error (_("Key generation failed: %s\n"), gpg_strerror (err)); + goto leave; } + para = quickgen_set_para (para, 0, algo, size, curve, keyuse); + if (subalgo) + para = quickgen_set_para (para, 1, + subalgo, subsize, subcurve, subkeyuse); + if (*expirestr) { u32 expire; @@ -3736,6 +4031,7 @@ void generate_keypair (ctrl_t ctrl, int full, const char *fname, const char *card_serialno, int card_backup_key) { + gpg_error_t err; unsigned int nbits; char *uid = NULL; int algo; @@ -3768,14 +4064,14 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname, if (card_serialno) { #ifdef ENABLE_CARD_SUPPORT - gpg_error_t err; struct agent_card_info_s info; memset (&info, 0, sizeof (info)); err = agent_scd_getattr ("KEY-ATTR", &info); if (err) { - log_error (_("error getting current key info: %s\n"), gpg_strerror (err)); + log_error (_("error getting current key info: %s\n"), + gpg_strerror (err)); return; } @@ -3978,6 +4274,11 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname, } else /* Default key generation. */ { + int subalgo; + unsigned int size, subsize; + unsigned int keyuse, subkeyuse; + const char *curve, *subcurve; + tty_printf ( _("Note: Use \"%s %s\"" " for a full featured key generation dialog.\n"), #if USE_GPG2_HACK @@ -3986,12 +4287,22 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname, GPG_NAME #endif , "--full-gen-key" ); - para = quickgen_set_para (para, 0, - DEFAULT_STD_ALGO, DEFAULT_STD_KEYSIZE, - DEFAULT_STD_CURVE, 0); - para = quickgen_set_para (para, 1, - DEFAULT_STD_SUBALGO, DEFAULT_STD_SUBKEYSIZE, - DEFAULT_STD_SUBCURVE, 0); + + err = parse_key_parameter_string (NULL, -1, + &algo, &size, &keyuse, &curve, + &subalgo, &subsize, + &subkeyuse, &subcurve); + if (err) + { + log_error (_("Key generation failed: %s\n"), gpg_strerror (err)); + return; + } + para = quickgen_set_para (para, 0, algo, size, curve, keyuse); + if (subalgo) + para = quickgen_set_para (para, 1, + subalgo, subsize, subcurve, subkeyuse); + + } @@ -4479,87 +4790,38 @@ parse_algo_usage_expire (ctrl_t ctrl, int for_subkey, int *r_algo, unsigned int *r_usage, u32 *r_expire, unsigned int *r_nbits, char **r_curve) { + gpg_error_t err; int algo; unsigned int use, nbits; u32 expire; int wantuse; - unsigned int min, def, max; const char *curve = NULL; - int eccalgo = 0; *r_curve = NULL; nbits = 0; + /* Parse the algo string. */ - if (!algostr || !*algostr - || !strcmp (algostr, "default") || !strcmp (algostr, "-")) - { - algo = for_subkey? DEFAULT_STD_SUBALGO : DEFAULT_STD_ALGO; - use = for_subkey? DEFAULT_STD_SUBKEYUSE : DEFAULT_STD_KEYUSE; - nbits = for_subkey? DEFAULT_STD_SUBKEYSIZE : DEFAULT_STD_KEYSIZE; - curve = for_subkey? DEFAULT_STD_SUBCURVE : DEFAULT_STD_CURVE; - } - else if (!strcmp (algostr, "future-default")) - { - algo = for_subkey? FUTURE_STD_SUBALGO : FUTURE_STD_ALGO; - use = for_subkey? FUTURE_STD_SUBKEYUSE : FUTURE_STD_KEYUSE; - nbits = for_subkey? FUTURE_STD_SUBKEYSIZE : FUTURE_STD_KEYSIZE; - curve = for_subkey? FUTURE_STD_SUBCURVE : FUTURE_STD_CURVE; - } - else if (*algostr == '&' && strlen (algostr) == 41) + if (algostr && *algostr == '&' && strlen (algostr) == 41) { /* Take algo from existing key. */ algo = check_keygrip (ctrl, algostr+1); /* FIXME: We need the curve name as well. */ return gpg_error (GPG_ERR_NOT_IMPLEMENTED); } - else if (!strncmp (algostr, "rsa", 3)) - { - algo = PUBKEY_ALGO_RSA; - use = for_subkey? DEFAULT_STD_SUBKEYUSE : DEFAULT_STD_KEYUSE; - if (algostr[3]) - nbits = atoi (algostr + 3); - } - else if (!strncmp (algostr, "elg", 3)) - { - algo = PUBKEY_ALGO_ELGAMAL_E; - use = PUBKEY_USAGE_ENC; - if (algostr[3]) - nbits = atoi (algostr + 3); - } - else if (!strncmp (algostr, "dsa", 3)) - { - algo = PUBKEY_ALGO_DSA; - use = PUBKEY_USAGE_SIG; - if (algostr[3]) - nbits = atoi (algostr + 3); - } - else if ((curve = openpgp_is_curve_supported (algostr, &algo))) - { - if (!algo) - { - algo = PUBKEY_ALGO_ECDH; /* Default ECC algorithm. */ - eccalgo = 1; /* Remember - we may need to fix it up. */ - } - if (algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_EDDSA) - use = PUBKEY_USAGE_SIG; - else - use = PUBKEY_USAGE_ENC; - } - else - return gpg_error (GPG_ERR_UNKNOWN_CURVE); + err = parse_key_parameter_string (algostr, for_subkey? 1 : 0, + &algo, &nbits, &use, &curve, + NULL, NULL, NULL, NULL); + if (err) + return err; /* Parse the usage string. */ if (!usagestr || !*usagestr || !strcmp (usagestr, "default") || !strcmp (usagestr, "-")) - ; /* Keep default usage */ + ; /* Keep usage from parse_key_parameter_string. */ else if ((wantuse = parse_usagestr (usagestr)) != -1) - { - use = wantuse; - if (eccalgo && !(use & PUBKEY_USAGE_ENC)) - algo = PUBKEY_ALGO_ECDSA; /* Switch from ECDH to ECDSA. */ - } + use = wantuse; else return gpg_error (GPG_ERR_INV_VALUE); @@ -4567,7 +4829,9 @@ parse_algo_usage_expire (ctrl_t ctrl, int for_subkey, if (!for_subkey) use |= PUBKEY_USAGE_CERT; - /* Check that usage is possible. */ + /* Check that usage is possible. NB: We have the same check in + * parse_key_parameter_string but need it here again in case the + * separate usage value has been given. */ if (/**/((use & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_AUTH|PUBKEY_USAGE_CERT)) && !pubkey_get_nsig (algo)) || ((use & PUBKEY_USAGE_ENC) @@ -4580,17 +4844,6 @@ parse_algo_usage_expire (ctrl_t ctrl, int for_subkey, if (expire == (u32)-1 ) return gpg_error (GPG_ERR_INV_VALUE); - /* Make sure the keysize is in the allowed range. */ - get_keysize_range (algo, &min, &def, &max); - if (!nbits) - nbits = def; - else if (nbits < min) - nbits = min; - else if (nbits > max) - nbits = max; - - nbits = fixup_keysize (nbits, algo, 1); - if (curve) { *r_curve = xtrystrdup (curve); diff --git a/g10/options.h b/g10/options.h index 8ed2cdbf7..2449042f5 100644 --- a/g10/options.h +++ b/g10/options.h @@ -120,6 +120,8 @@ struct const char *agent_program; const char *dirmngr_program; + const char *def_new_key_algo; + /* Options to be passed to the gpg-agent */ session_env_t session_env; char *lc_ctype; |