aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/gpg.texi9
-rw-r--r--g10/keygen.c319
2 files changed, 270 insertions, 58 deletions
diff --git a/doc/gpg.texi b/doc/gpg.texi
index 212defe0c..5a2d8768a 100644
--- a/doc/gpg.texi
+++ b/doc/gpg.texi
@@ -683,6 +683,15 @@ supplied passphrase is used for the new key and the agent does not ask
for it. To create a key without any protection @code{--passphrase ''}
may be used.
+To create an OpenPGP key from the keys available on the currently
+inserted smartcard, the special string ``card'' can be used for
+@var{algo}. If the card features an encryption and a signing key, gpg
+will figure them out and creates an OpenPGP key consisting of the
+usual primary key and one subkey. This works only with certain
+smartcards. Note that the interactive @option{--full-gen-key} command
+allows to do the same but with greater flexibility in the selection of
+the smartcard keys.
+
Note that it is possible to create a primary key and a subkey using
non-default algorithms by using ``default'' and changing the default
parameters using the option @option{--default-new-key-algo}.
diff --git a/g10/keygen.c b/g10/keygen.c
index bd02b631f..5be251e38 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -151,7 +151,8 @@ static gpg_error_t parse_algo_usage_expire (ctrl_t ctrl, int for_subkey,
const char *expirestr,
int *r_algo, unsigned int *r_usage,
u32 *r_expire, unsigned int *r_nbits,
- const char **r_curve, int *r_version);
+ const char **r_curve, int *r_version,
+ char **r_keygrip);
static void do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
struct output_control_s *outctrl, int card );
static int write_keyblock (iobuf_t out, kbnode_t node);
@@ -2303,6 +2304,10 @@ ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage,
&& algostr && !strncmp (algostr, "nistp", 5)
&& !(sl->flags & GCRY_PK_USAGE_ENCR))
sl->flags |= (PUBKEY_ALGO_ECDSA << 8);
+ else if (algoid == GCRY_PK_ECC
+ && algostr && !strcmp (algostr, "ed25519")
+ && !(sl->flags & GCRY_PK_USAGE_ENCR))
+ sl->flags = (PUBKEY_ALGO_EDDSA << 8);
else
sl->flags |= (map_pk_gcry_to_openpgp (algoid) << 8);
@@ -3226,11 +3231,14 @@ generate_user_id (KBNODE keyblock, const char *uidstr)
* the key; this is currently 4 but can be changed with the flag "v5"
* to create a v5 key. */
static gpg_error_t
-parse_key_parameter_part (char *string, int for_subkey, int clear_cert,
+parse_key_parameter_part (ctrl_t ctrl,
+ char *string, int for_subkey, int clear_cert,
int *r_algo, unsigned int *r_size,
unsigned int *r_keyuse,
- char const **r_curve, int *r_keyversion)
+ char const **r_curve, int *r_keyversion,
+ char **r_keygrip)
{
+ gpg_error_t err;
char *flags;
int algo;
char *endp;
@@ -3241,6 +3249,8 @@ parse_key_parameter_part (char *string, int for_subkey, int clear_cert,
int keyversion = 4;
int i;
const char *s;
+ int from_card = 0;
+ char *keygrip = NULL;
if (!string || !*string)
return 0; /* Success. */
@@ -3250,7 +3260,9 @@ parse_key_parameter_part (char *string, int for_subkey, int clear_cert,
*flags++ = 0;
algo = 0;
- if (strlen (string) >= 3 && (digitp (string+3) || !string[3]))
+ if (!ascii_strcasecmp (string, "card"))
+ from_card = 1;
+ else if (strlen (string) >= 3 && (digitp (string+3) || !string[3]))
{
if (!ascii_memcasecmp (string, "rsa", 3))
algo = PUBKEY_ALGO_RSA;
@@ -3259,7 +3271,10 @@ parse_key_parameter_part (char *string, int for_subkey, int clear_cert,
else if (!ascii_memcasecmp (string, "elg", 3))
algo = PUBKEY_ALGO_ELGAMAL_E;
}
- if (algo)
+
+ if (from_card)
+ ; /* We need the flags before we can figure out the key to use. */
+ else if (algo)
{
if (!string[3])
size = get_keysize_range (algo, NULL, NULL);
@@ -3304,7 +3319,7 @@ parse_key_parameter_part (char *string, int for_subkey, int clear_cert,
keyuse |= PUBKEY_USAGE_AUTH;
else if (!ascii_strcasecmp (s, "cert"))
keyuse |= PUBKEY_USAGE_CERT;
- else if (!ascii_strcasecmp (s, "ecdsa"))
+ else if (!ascii_strcasecmp (s, "ecdsa") && !from_card)
{
if (algo == PUBKEY_ALGO_ECDH || algo == PUBKEY_ALGO_ECDSA)
algo = PUBKEY_ALGO_ECDSA;
@@ -3315,7 +3330,7 @@ parse_key_parameter_part (char *string, int for_subkey, int clear_cert,
}
ecdh_or_ecdsa = 0;
}
- else if (!ascii_strcasecmp (s, "ecdh"))
+ else if (!ascii_strcasecmp (s, "ecdh") && !from_card)
{
if (algo == PUBKEY_ALGO_ECDH || algo == PUBKEY_ALGO_ECDSA)
algo = PUBKEY_ALGO_ECDH;
@@ -3326,7 +3341,7 @@ parse_key_parameter_part (char *string, int for_subkey, int clear_cert,
}
ecdh_or_ecdsa = 0;
}
- else if (!ascii_strcasecmp (s, "eddsa"))
+ else if (!ascii_strcasecmp (s, "eddsa") && !from_card)
{
/* Not required but we allow it for consistency. */
if (algo == PUBKEY_ALGO_EDDSA)
@@ -3354,8 +3369,115 @@ parse_key_parameter_part (char *string, int for_subkey, int clear_cert,
xfree (tokens);
}
- /* If not yet decided switch between ecdh and ecdsa. */
- if (ecdh_or_ecdsa && keyuse)
+ /* If not yet decided switch between ecdh and ecdsa unless we want
+ * to read the algo from the current card. */
+ if (from_card)
+ {
+ strlist_t keypairlist, sl;
+ char *reqkeyref;
+
+ if (!keyuse)
+ keyuse = (for_subkey? PUBKEY_USAGE_ENC
+ /* */ : (PUBKEY_USAGE_CERT|PUBKEY_USAGE_SIG));
+
+ /* Access the card to make sure we have one and to show the S/N. */
+ {
+ char *serialno;
+
+ err = agent_scd_serialno (&serialno, NULL);
+ if (err)
+ {
+ log_error (_("error reading the card: %s\n"), gpg_strerror (err));
+ return err;
+ }
+ if (!opt.quiet)
+ log_info (_("Serial number of the card: %s\n"), serialno);
+ xfree (serialno);
+ }
+
+ err = agent_scd_keypairinfo (ctrl, NULL, &keypairlist);
+ if (err)
+ {
+ log_error (_("error reading the card: %s\n"), gpg_strerror (err));
+ return err;
+ }
+ agent_scd_getattr_one ((keyuse & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_CERT))
+ ? "$SIGNKEYID":"$ENCRKEYID", &reqkeyref);
+
+ algo = 0; /* Should already be the case. */
+ for (sl=keypairlist; sl && !algo; sl = sl->next)
+ {
+ gcry_sexp_t s_pkey;
+ char *algostr = NULL;
+ enum gcry_pk_algos algoid = 0;
+ const char *keyref;
+
+ if (!reqkeyref)
+ continue; /* Card does not provide the info (skip all). */
+
+ keyref = strchr (sl->d, ' ');
+ if (!keyref)
+ continue; /* Ooops. */
+ keyref++;
+ if (strcmp (reqkeyref, keyref))
+ continue; /* This is not the requested keyref. */
+
+ if ((keyuse & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_CERT))
+ && (sl->flags & (GCRY_PK_USAGE_SIGN|GCRY_PK_USAGE_CERT)))
+ ; /* Okay */
+ else if ((keyuse & PUBKEY_USAGE_ENC)
+ && (sl->flags & GCRY_PK_USAGE_ENCR))
+ ; /* Okay */
+ else
+ continue; /* Not usable for us. */
+
+ if (agent_scd_readkey (keyref, &s_pkey))
+ continue; /* Could not read the key. */
+
+ algostr = pubkey_algo_string (s_pkey, &algoid);
+ gcry_sexp_release (s_pkey);
+
+
+ /* Map to OpenPGP algo number.
+ * We need to tweak the algo in case GCRY_PK_ECC is returned
+ * because pubkey_algo_string is not aware of the OpenPGP
+ * algo mapping. FIXME: This is an ugly hack. */
+ if (algoid == GCRY_PK_ECC
+ && algostr && !strncmp (algostr, "nistp", 5)
+ && !(sl->flags & GCRY_PK_USAGE_ENCR))
+ algo = PUBKEY_ALGO_ECDSA;
+ else if (algoid == GCRY_PK_ECC
+ && algostr && !strcmp (algostr, "ed25519")
+ && !(sl->flags & GCRY_PK_USAGE_ENCR))
+ algo = PUBKEY_ALGO_EDDSA;
+ else
+ algo = map_pk_gcry_to_openpgp (algoid);
+
+ xfree (algostr);
+ xfree (keygrip);
+ keygrip = xtrystrdup (sl->d);
+ if (!keygrip)
+ {
+ err = gpg_error_from_syserror ();
+ xfree (reqkeyref);
+ free_strlist (keypairlist);
+ return err;
+ }
+ if ((endp = strchr (keygrip, ' ')))
+ *endp = 0;
+ }
+
+ xfree (reqkeyref);
+ free_strlist (keypairlist);
+ if (!algo || !keygrip)
+ {
+ err = gpg_error (GPG_ERR_PUBKEY_ALGO);
+ log_error ("no usable key on the card: %s\n", gpg_strerror (err));
+ xfree (keygrip);
+ return err;
+ }
+ }
+ else 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;
@@ -3395,7 +3517,10 @@ parse_key_parameter_part (char *string, int for_subkey, int clear_cert,
|| ((keyuse & PUBKEY_USAGE_ENC)
&& !pubkey_get_nenc (algo))
|| (for_subkey && (keyuse & PUBKEY_USAGE_CERT)))
- return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
+ {
+ xfree (keygrip);
+ return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
+ }
/* Return values. */
if (r_algo)
@@ -3415,6 +3540,7 @@ parse_key_parameter_part (char *string, int for_subkey, int clear_cert,
*r_size = fixup_keysize (size, algo, 1);
}
+
if (r_keyuse)
*r_keyuse = keyuse;
if (r_curve)
@@ -3422,6 +3548,11 @@ parse_key_parameter_part (char *string, int for_subkey, int clear_cert,
if (r_keyversion)
*r_keyversion = keyversion;
+ if (r_keygrip)
+ *r_keygrip = keygrip;
+ else
+ xfree (keygrip);
+
return 0;
}
@@ -3443,7 +3574,7 @@ parse_key_parameter_part (char *string, int for_subkey, int clear_cert,
*
* 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
+ * is given to select whether ECDSA or ECDH is used; this can either
* be done using an algorithm keyword or usage keywords.
*
* FLAGS is a comma delimited string of keywords:
@@ -3470,16 +3601,19 @@ parse_key_parameter_part (char *string, int for_subkey, int clear_cert,
*
*/
gpg_error_t
-parse_key_parameter_string (const char *string, int part,
+parse_key_parameter_string (ctrl_t ctrl,
+ const char *string, int part,
unsigned int suggested_use,
int *r_algo, unsigned int *r_size,
unsigned int *r_keyuse,
char const **r_curve,
int *r_version,
+ char **r_keygrip,
int *r_subalgo, unsigned int *r_subsize,
unsigned int *r_subkeyuse,
char const **r_subcurve,
- int *r_subversion)
+ int *r_subversion,
+ char **r_subkeygrip)
{
gpg_error_t err = 0;
char *primary, *secondary;
@@ -3494,6 +3628,8 @@ parse_key_parameter_string (const char *string, int part,
*r_curve = NULL;
if (r_version)
*r_version = 4;
+ if (r_keygrip)
+ *r_keygrip = NULL;
if (r_subalgo)
*r_subalgo = 0;
if (r_subsize)
@@ -3504,6 +3640,8 @@ parse_key_parameter_string (const char *string, int part,
*r_subcurve = NULL;
if (r_subversion)
*r_subversion = 4;
+ if (r_subkeygrip)
+ *r_subkeygrip = NULL;
if (!string || !*string
|| !ascii_strcasecmp (string, "default") || !strcmp (string, "-"))
@@ -3511,6 +3649,8 @@ parse_key_parameter_string (const char *string, int part,
else if (!ascii_strcasecmp (string, "future-default")
|| !ascii_strcasecmp (string, "futuredefault"))
string = FUTURE_STD_KEY_PARAM;
+ else if (!ascii_strcasecmp (string, "card"))
+ string = "card/cert,sign+card/encr";
primary = xstrdup (string);
secondary = strchr (primary, '+');
@@ -3518,11 +3658,14 @@ parse_key_parameter_string (const char *string, int part,
*secondary++ = 0;
if (part == -1 || part == 0)
{
- err = parse_key_parameter_part (primary, 0, 0, r_algo, r_size,
- r_keyuse, r_curve, r_version);
+ err = parse_key_parameter_part (ctrl, primary,
+ 0, 0, r_algo, r_size,
+ r_keyuse, r_curve, r_version, r_keygrip);
if (!err && part == -1)
- err = parse_key_parameter_part (secondary, 1, 0, r_subalgo, r_subsize,
- r_subkeyuse, r_subcurve, r_subversion);
+ err = parse_key_parameter_part (ctrl, secondary,
+ 1, 0, r_subalgo, r_subsize,
+ r_subkeyuse, r_subcurve, r_subversion,
+ r_subkeygrip);
}
else if (part == 1)
{
@@ -3534,18 +3677,21 @@ parse_key_parameter_string (const char *string, int part,
* to force clearing the cert usage. */
if (secondary)
{
- err = parse_key_parameter_part (secondary, 1, 0,
+ err = parse_key_parameter_part (ctrl, secondary,
+ 1, 0,
r_algo, r_size, r_keyuse, r_curve,
- r_version);
+ r_version, r_keygrip);
if (!err && suggested_use && r_keyuse && !(suggested_use & *r_keyuse))
- err = parse_key_parameter_part (primary, 1, 1 /*(clear cert)*/,
+ err = parse_key_parameter_part (ctrl, primary,
+ 1, 1 /*(clear cert)*/,
r_algo, r_size, r_keyuse, r_curve,
- r_version);
+ r_version, r_keygrip);
}
else
- err = parse_key_parameter_part (primary, 1, 0,
+ err = parse_key_parameter_part (ctrl, primary,
+ 1, 0,
r_algo, r_size, r_keyuse, r_curve,
- r_version);
+ r_version, r_keygrip);
}
xfree (primary);
@@ -3610,7 +3756,7 @@ get_parameter_passphrase (struct para_data_s *para)
static int
-get_parameter_algo( struct para_data_s *para, enum para_name key,
+get_parameter_algo (ctrl_t ctrl, struct para_data_s *para, enum para_name key,
int *r_default)
{
int i;
@@ -3632,9 +3778,9 @@ get_parameter_algo( struct para_data_s *para, enum para_name key,
* 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, 0,
- &i, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL);
+ parse_key_parameter_string (ctrl, NULL, 0, 0,
+ &i, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL);
if (r_default)
*r_default = 1;
}
@@ -3831,7 +3977,7 @@ proc_parameter_file (ctrl_t ctrl, struct para_data_s *para, const char *fname,
r = get_parameter( para, pKEYTYPE );
if(r)
{
- algo = get_parameter_algo (para, pKEYTYPE, &is_default);
+ algo = get_parameter_algo (ctrl, para, pKEYTYPE, &is_default);
if (openpgp_pk_test_algo2 (algo, PUBKEY_USAGE_SIG))
{
log_error ("%s:%d: invalid algorithm\n", fname, r->lnr );
@@ -3873,7 +4019,7 @@ proc_parameter_file (ctrl_t ctrl, struct para_data_s *para, const char *fname,
r = get_parameter( para, pSUBKEYTYPE );
if(r)
{
- algo = get_parameter_algo (para, pSUBKEYTYPE, &is_default);
+ algo = get_parameter_algo (ctrl, para, pSUBKEYTYPE, &is_default);
if (openpgp_pk_test_algo (algo))
{
log_error ("%s:%d: invalid algorithm\n", fname, r->lnr );
@@ -4241,7 +4387,7 @@ read_parameter_file (ctrl_t ctrl, const char *fname )
static struct para_data_s *
quickgen_set_para (struct para_data_s *para, int for_subkey,
int algo, int nbits, const char *curve, unsigned int use,
- int version)
+ int version, const char *keygrip)
{
struct para_data_s *r;
@@ -4263,7 +4409,15 @@ quickgen_set_para (struct para_data_s *para, int for_subkey,
r->next = para;
para = r;
- if (curve)
+ if (keygrip)
+ {
+ r = xmalloc_clear (sizeof *r + strlen (keygrip));
+ r->key = for_subkey? pSUBKEYGRIP : pKEYGRIP;
+ strcpy (r->u.value, keygrip);
+ r->next = para;
+ para = r;
+ }
+ else if (curve)
{
r = xmalloc_clear (sizeof *r + strlen (curve));
r->key = for_subkey? pSUBKEYCURVE : pKEYCURVE;
@@ -4376,7 +4530,8 @@ quick_generate_keypair (ctrl_t ctrl, const char *uid, const char *algostr,
if ((!*algostr || !ascii_strcasecmp (algostr, "default")
|| !ascii_strcasecmp (algostr, "future-default")
- || !ascii_strcasecmp (algostr, "futuredefault"))
+ || !ascii_strcasecmp (algostr, "futuredefault")
+ || !ascii_strcasecmp (algostr, "card"))
&& (!*usagestr || !ascii_strcasecmp (usagestr, "default")
|| !strcmp (usagestr, "-")))
{
@@ -4385,23 +4540,25 @@ quick_generate_keypair (ctrl_t ctrl, const char *uid, const char *algostr,
unsigned int size, subsize;
unsigned int keyuse, subkeyuse;
const char *curve, *subcurve;
+ char *keygrip, *subkeygrip;
- err = parse_key_parameter_string (algostr, -1, 0,
+ err = parse_key_parameter_string (ctrl, algostr, -1, 0,
&algo, &size, &keyuse, &curve, &version,
+ &keygrip,
&subalgo, &subsize, &subkeyuse,
- &subcurve, &subversion);
+ &subcurve, &subversion, &subkeygrip);
if (err)
{
log_error (_("Key generation failed: %s\n"), gpg_strerror (err));
goto leave;
}
- para = quickgen_set_para (para, 0, algo, size, curve, keyuse, version);
+ para = quickgen_set_para (para, 0, algo, size, curve, keyuse, version,
+ keygrip);
if (subalgo)
para = quickgen_set_para (para, 1,
subalgo, subsize, subcurve, subkeyuse,
- subversion);
-
+ subversion, subkeygrip);
if (*expirestr)
{
u32 expire;
@@ -4419,6 +4576,9 @@ quick_generate_keypair (ctrl_t ctrl, const char *uid, const char *algostr,
r->next = para;
para = r;
}
+
+ xfree (keygrip);
+ xfree (subkeygrip);
}
else
{
@@ -4428,22 +4588,26 @@ quick_generate_keypair (ctrl_t ctrl, const char *uid, const char *algostr,
u32 expire;
unsigned int nbits;
const char *curve;
+ char *keygrip;
err = parse_algo_usage_expire (ctrl, 0, algostr, usagestr, expirestr,
&algo, &use, &expire, &nbits, &curve,
- &version);
+ &version, &keygrip);
if (err)
{
log_error (_("Key generation failed: %s\n"), gpg_strerror (err) );
goto leave;
}
- para = quickgen_set_para (para, 0, algo, nbits, curve, use, version);
+ para = quickgen_set_para (para, 0, algo, nbits, curve, use, version,
+ keygrip);
r = xmalloc_clear (sizeof *r + 20);
r->key = pKEYEXPIRE;
r->u.expire = expire;
r->next = para;
para = r;
+
+ xfree (keygrip);
}
/* If the pinentry loopback mode is not and we have a static
@@ -4756,6 +4920,7 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname,
unsigned int size, subsize;
unsigned int keyuse, subkeyuse;
const char *curve, *subcurve;
+ char *keygrip, *subkeygrip;
tty_printf ( _("Note: Use \"%s %s\""
" for a full featured key generation dialog.\n"),
@@ -4766,22 +4931,27 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname,
#endif
, "--full-generate-key" );
- err = parse_key_parameter_string (NULL, -1, 0,
+ err = parse_key_parameter_string (ctrl, NULL, -1, 0,
&algo, &size, &keyuse, &curve, &version,
+ &keygrip,
&subalgo, &subsize,
- &subkeyuse, &subcurve, &subversion);
+ &subkeyuse, &subcurve, &subversion,
+ &subkeygrip);
if (err)
{
log_error (_("Key generation failed: %s\n"), gpg_strerror (err));
return;
}
- para = quickgen_set_para (para, 0, algo, size, curve, keyuse, version);
+ para = quickgen_set_para (para, 0,
+ algo, size, curve, keyuse,
+ version, keygrip);
if (subalgo)
para = quickgen_set_para (para, 1,
subalgo, subsize, subcurve, subkeyuse,
- subversion);
-
+ subversion, subkeygrip);
+ xfree (keygrip);
+ xfree (subkeygrip);
}
@@ -5065,7 +5235,7 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
node of the subkey but that is more work than just to pass the
current timestamp. */
- algo = get_parameter_algo( para, pKEYTYPE, NULL );
+ algo = get_parameter_algo (ctrl, para, pKEYTYPE, NULL );
expire = get_parameter_u32( para, pKEYEXPIRE );
key_from_hexgrip = get_parameter_value (para, pKEYGRIP);
@@ -5128,7 +5298,8 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
if (!err && card && get_parameter (para, pAUTHKEYTYPE))
{
- err = gen_card_key (3, get_parameter_algo( para, pAUTHKEYTYPE, NULL ),
+ err = gen_card_key (3, get_parameter_algo (ctrl, para,
+ pAUTHKEYTYPE, NULL ),
0, pub_root, &timestamp, expire, keygen_flags);
if (!err)
err = write_keybinding (ctrl, pub_root, pri_psk, NULL,
@@ -5137,7 +5308,7 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
if (!err && get_parameter (para, pSUBKEYTYPE))
{
- int subkey_algo = get_parameter_algo (para, pSUBKEYTYPE, NULL);
+ int subkey_algo = get_parameter_algo (ctrl, para, pSUBKEYTYPE, NULL);
s = NULL;
key_from_hexgrip = get_parameter_value (para, pSUBKEYGRIP);
@@ -5232,7 +5403,7 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
int no_enc_rsa;
PKT_public_key *pk;
- no_enc_rsa = ((get_parameter_algo (para, pKEYTYPE, NULL)
+ no_enc_rsa = ((get_parameter_algo (ctrl, para, pKEYTYPE, NULL)
== PUBKEY_ALGO_RSA)
&& get_parameter_uint (para, pKEYUSAGE)
&& !((get_parameter_uint (para, pKEYUSAGE)
@@ -5265,7 +5436,8 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
if (!opt.batch
- && (get_parameter_algo (para, pKEYTYPE, NULL) == PUBKEY_ALGO_DSA
+ && (get_parameter_algo (ctrl, para,
+ pKEYTYPE, NULL) == PUBKEY_ALGO_DSA
|| no_enc_rsa )
&& !get_parameter (para, pSUBKEYTYPE) )
{
@@ -5305,7 +5477,7 @@ parse_algo_usage_expire (ctrl_t ctrl, int for_subkey,
const char *expirestr,
int *r_algo, unsigned int *r_usage, u32 *r_expire,
unsigned int *r_nbits, const char **r_curve,
- int *r_version)
+ int *r_version, char **r_keygrip)
{
gpg_error_t err;
int algo;
@@ -5316,6 +5488,8 @@ parse_algo_usage_expire (ctrl_t ctrl, int for_subkey,
const char *curve = NULL;
*r_curve = NULL;
+ if (r_keygrip)
+ *r_keygrip = NULL;
nbits = 0;
@@ -5328,12 +5502,20 @@ parse_algo_usage_expire (ctrl_t ctrl, int for_subkey,
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
}
- err = parse_key_parameter_string (algostr, for_subkey? 1 : 0,
+ err = parse_key_parameter_string (ctrl, algostr, for_subkey? 1 : 0,
usagestr? parse_usagestr (usagestr):0,
&algo, &nbits, &use, &curve, &version,
- NULL, NULL, NULL, NULL, NULL);
+ r_keygrip,
+ NULL, NULL, NULL, NULL, NULL, NULL);
if (err)
- return err;
+ {
+ if (r_keygrip)
+ {
+ xfree (*r_keygrip);
+ *r_keygrip = NULL;
+ }
+ return err;
+ }
/* Parse the usage string. */
if (!usagestr || !*usagestr
@@ -5342,7 +5524,14 @@ parse_algo_usage_expire (ctrl_t ctrl, int for_subkey,
else if ((wantuse = parse_usagestr (usagestr)) != -1)
use = wantuse;
else
- return gpg_error (GPG_ERR_INV_VALUE);
+ {
+ if (r_keygrip)
+ {
+ xfree (*r_keygrip);
+ *r_keygrip = NULL;
+ }
+ return gpg_error (GPG_ERR_INV_VALUE);
+ }
/* Make sure a primary key has the CERT usage. */
if (!for_subkey)
@@ -5356,12 +5545,26 @@ parse_algo_usage_expire (ctrl_t ctrl, int for_subkey,
|| ((use & PUBKEY_USAGE_ENC)
&& !pubkey_get_nenc (algo))
|| (for_subkey && (use & PUBKEY_USAGE_CERT)))
- return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
+ {
+ if (r_keygrip)
+ {
+ xfree (*r_keygrip);
+ *r_keygrip = NULL;
+ }
+ return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
+ }
/* Parse the expire string. */
expire = parse_expire_string (expirestr);
if (expire == (u32)-1 )
- return gpg_error (GPG_ERR_INV_VALUE);
+ {
+ if (r_keygrip)
+ {
+ xfree (*r_keygrip);
+ *r_keygrip = NULL;
+ }
+ return gpg_error (GPG_ERR_INV_VALUE);
+ }
if (curve)
*r_curve = curve;
@@ -5483,7 +5686,7 @@ generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock, const char *algostr,
err = parse_algo_usage_expire (ctrl, 1, algostr, usagestr, expirestr,
&algo, &use, &expire, &nbits, &curve,
- &version);
+ &version, &key_from_hexgrip);
if (err)
goto leave;