1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

Merge branch 'STABLE-BRANCH-2-4'

--
Fixed conflicts:
	NEWS
	configure.ac
	doc/gpg.texi
This commit is contained in:
Werner Koch 2024-01-26 09:41:00 +01:00
commit dfa60c09f5
No known key found for this signature in database
GPG key ID: E3FDFF218E45B72B
88 changed files with 2655 additions and 1419 deletions

View file

@ -2227,7 +2227,14 @@ keyinfo_status_cb (void *opaque, const char *line)
/* Ask the agent whether a secret key for the given public key is
available. Returns 0 if not available. Bigger value is preferred. */
* available. Returns 0 if not available. Bigger value is preferred.
* Will never return a value less than 0. Defined return values are:
* 0 := No key or error
* 1 := Key available
* 2 := Key available on a smartcard
* 3 := Key available and passphrase cached
* 4 := Key available on current smartcard
*/
int
agent_probe_secret_key (ctrl_t ctrl, PKT_public_key *pk)
{
@ -2241,11 +2248,11 @@ agent_probe_secret_key (ctrl_t ctrl, PKT_public_key *pk)
err = start_agent (ctrl, 0);
if (err)
return err;
return 0;
err = hexkeygrip_from_pk (pk, &hexgrip);
if (err)
return err;
return 0;
snprintf (line, sizeof line, "KEYINFO %s", hexgrip);
xfree (hexgrip);
@ -3237,6 +3244,45 @@ agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc, int verify,
}
/* Enable or disable the ephemeral mode. In ephemeral mode keys are
* created,searched and used in a per-session key store and not in the
* on-disk file. Set ENABLE to 1 to enable this mode, to 0 to disable
* this mode and to -1 to only query the current mode. If R_PREVIOUS
* is given the previously used state of the ephemeral mode is stored
* at that address. */
gpg_error_t
agent_set_ephemeral_mode (ctrl_t ctrl, int enable, int *r_previous)
{
gpg_error_t err;
err = start_agent (ctrl, 0);
if (err)
goto leave;
if (r_previous)
{
err = assuan_transact (agent_ctx, "GETINFO ephemeral",
NULL, NULL, NULL, NULL, NULL, NULL);
if (!err)
*r_previous = 1;
else if (gpg_err_code (err) == GPG_ERR_FALSE)
*r_previous = 0;
else
goto leave;
}
/* Skip setting if we are only querying or if the mode is already set. */
if (enable == -1 || (r_previous && !!*r_previous == !!enable))
err = 0;
else
err = assuan_transact (agent_ctx,
enable? "OPTION ephemeral=1" : "OPTION ephemeral=0",
NULL, NULL, NULL, NULL, NULL, NULL);
leave:
return err;
}
/* Return the version reported by gpg-agent. */
gpg_error_t
agent_get_version (ctrl_t ctrl, char **r_version)

View file

@ -247,6 +247,10 @@ gpg_error_t agent_delete_key (ctrl_t ctrl, const char *hexkeygrip,
gpg_error_t agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
int verify,
char **cache_nonce_addr, char **passwd_nonce_addr);
/* Set or get the ephemeral mode. */
gpg_error_t agent_set_ephemeral_mode (ctrl_t ctrl, int enable, int *r_previous);
/* Get the version reported by gpg-agent. */
gpg_error_t agent_get_version (ctrl_t ctrl, char **r_version);

View file

@ -2009,8 +2009,9 @@ parse_def_secret_key (ctrl_t ctrl)
{
gpg_error_t err;
KEYDB_SEARCH_DESC desc;
KBNODE kb;
KBNODE node;
kbnode_t kb;
kbnode_t node;
int any_revoked, any_expired, any_disabled;
err = classify_user_id (t->d, &desc, 1);
if (err)
@ -2053,6 +2054,7 @@ parse_def_secret_key (ctrl_t ctrl)
merge_selfsigs (ctrl, kb);
any_revoked = any_expired = any_disabled = 0;
err = gpg_error (GPG_ERR_NO_SECKEY);
node = kb;
do
@ -2062,6 +2064,7 @@ parse_def_secret_key (ctrl_t ctrl)
/* Check if the key is valid. */
if (pk->flags.revoked)
{
any_revoked = 1;
if (DBG_LOOKUP)
log_debug ("not using %s as default key, %s",
keystr_from_pk (pk), "revoked");
@ -2069,6 +2072,7 @@ parse_def_secret_key (ctrl_t ctrl)
}
if (pk->has_expired)
{
any_expired = 1;
if (DBG_LOOKUP)
log_debug ("not using %s as default key, %s",
keystr_from_pk (pk), "expired");
@ -2076,6 +2080,7 @@ parse_def_secret_key (ctrl_t ctrl)
}
if (pk_is_disabled (pk))
{
any_disabled = 1;
if (DBG_LOOKUP)
log_debug ("not using %s as default key, %s",
keystr_from_pk (pk), "disabled");
@ -2096,9 +2101,22 @@ parse_def_secret_key (ctrl_t ctrl)
{
if (! warned && ! opt.quiet)
{
gpg_err_code_t ec;
/* Try to get a better error than no secret key if we
* only know that the public key is not usable. */
if (any_revoked)
ec = GPG_ERR_CERT_REVOKED;
else if (any_expired)
ec = GPG_ERR_KEY_EXPIRED;
else if (any_disabled)
ec = GPG_ERR_KEY_DISABLED;
else
ec = GPG_ERR_NO_SECKEY;
log_info (_("Warning: not using '%s' as default key: %s\n"),
t->d, gpg_strerror (GPG_ERR_NO_SECKEY));
print_reported_error (err, GPG_ERR_NO_SECKEY);
t->d, gpg_strerror (ec));
print_reported_error (err, ec);
}
}
else
@ -3772,6 +3790,13 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact,
continue;
}
if (secret_key_avail < last_secret_key_avail)
{
if (DBG_LOOKUP)
log_debug ("\tskipping secret key with lower avail\n");
continue;
}
if (secret_key_avail > last_secret_key_avail)
{
/* Use this key. */

View file

@ -209,6 +209,9 @@ parse_import_options(char *str,unsigned int *options,int noisy)
{"repair-keys", IMPORT_REPAIR_KEYS, NULL,
N_("repair keys on import")},
/* New options. Right now, without description string. */
{"ignore-attributes", IMPORT_IGNORE_ATTRIBUTES, NULL, NULL},
/* Hidden options which are enabled by default and are provided
* in case of problems with the respective implementation. */
{"collapse-uids", IMPORT_COLLAPSE_UIDS, NULL, NULL},
@ -1008,6 +1011,15 @@ read_block( IOBUF a, unsigned int options,
init_packet(pkt);
continue;
}
else if ((opt.import_options & IMPORT_IGNORE_ATTRIBUTES)
&& (pkt->pkttype == PKT_USER_ID || pkt->pkttype == PKT_ATTRIBUTE)
&& pkt->pkt.user_id->attrib_data)
{
skip_sigs = 1;
free_packet (pkt, &parsectx);
init_packet (pkt);
continue;
}
if (skip_sigs)
{

View file

@ -746,28 +746,30 @@ keydb_add_resource (const char *url, unsigned int flags)
err = gpg_error (GPG_ERR_RESOURCE_LIMIT);
else
{
KEYBOX_HANDLE kbxhd;
if ((flags & KEYDB_RESOURCE_FLAG_PRIMARY))
primary_keydb = token;
all_resources[used_resources].type = rt;
all_resources[used_resources].u.kb = NULL; /* Not used here */
all_resources[used_resources].token = token;
/* Do a compress run if needed and no other user is
* currently using the keybox. */
kbxhd = keybox_new_openpgp (token, 0);
if (kbxhd)
if (!(flags & KEYDB_RESOURCE_FLAG_READONLY))
{
if (!keybox_lock (kbxhd, 1, 0))
KEYBOX_HANDLE kbxhd;
/* Do a compress run if needed and no other user is
* currently using the keybox. */
kbxhd = keybox_new_openpgp (token, 0);
if (kbxhd)
{
keybox_compress (kbxhd);
keybox_lock (kbxhd, 0, 0);
if (!keybox_lock (kbxhd, 1, 0))
{
keybox_compress (kbxhd);
keybox_lock (kbxhd, 0, 0);
}
keybox_release (kbxhd);
}
keybox_release (kbxhd);
}
used_resources++;
}
}

View file

@ -1905,6 +1905,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
PACKET *pkt;
IOBUF a;
struct parse_packet_ctx_s parsectx;
int lastmode;
if (!*arg_string)
{
@ -1959,17 +1960,28 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
xfree (fname);
node = new_kbnode (pkt);
/* Transfer it to gpg-agent which handles secret keys. */
err = transfer_secret_keys (ctrl, NULL, node, 1, 1, 0);
/* Treat the pkt as a public key. */
pkt->pkttype = PKT_PUBLIC_KEY;
/* Ask gpg-agent to store the secret key to card. */
if (card_store_subkey (node, 0, NULL))
err = agent_set_ephemeral_mode (ctrl, 1, &lastmode);
if (err)
log_error ("error switching to ephemeral mode: %s\n",
gpg_strerror (err));
else
{
redisplay = 1;
sec_shadowing = 1;
/* Transfer it to gpg-agent which handles secret keys. */
err = transfer_secret_keys (ctrl, NULL, node, 1, 1, 0);
if (!err)
{
/* Treat the pkt as a public key. */
pkt->pkttype = PKT_PUBLIC_KEY;
/* Ask gpg-agent to store the secret key to card. */
if (card_store_subkey (node, 0, NULL))
{
redisplay = 1;
sec_shadowing = 1;
}
}
if (!lastmode && agent_set_ephemeral_mode (ctrl, 0, NULL))
log_error ("error clearing the ephemeral mode\n");
}
release_kbnode (node);
}
@ -3212,7 +3224,7 @@ keyedit_quick_addkey (ctrl_t ctrl, const char *fpr, const char *algostr,
/* We require a fingerprint because only this uniquely identifies a
* key and may thus be used to select a key for unattended subkey
* creation. */
if (find_by_primary_fpr (ctrl, fpr, &keyblock, &kdbhd))
if ((err=find_by_primary_fpr (ctrl, fpr, &keyblock, &kdbhd)))
goto leave;
if (fix_keyblock (ctrl, &keyblock))
@ -3224,6 +3236,7 @@ keyedit_quick_addkey (ctrl_t ctrl, const char *fpr, const char *algostr,
if (!opt.verbose)
show_key_with_all_names (ctrl, es_stdout, keyblock, 0, 0, 0, 0, 0, 1);
log_error ("%s%s", _("Key is revoked."), "\n");
err = gpg_error (GPG_ERR_CERT_REVOKED);
goto leave;
}
@ -3247,6 +3260,8 @@ keyedit_quick_addkey (ctrl_t ctrl, const char *fpr, const char *algostr,
log_info (_("Key not changed so no update needed.\n"));
leave:
if (err)
write_status_error ("keyedit.addkey", err);
release_kbnode (keyblock);
keydb_release (kdbhd);
}
@ -3274,7 +3289,7 @@ keyedit_quick_addadsk (ctrl_t ctrl, const char *fpr, const char *adskfpr)
/* We require a fingerprint because only this uniquely identifies a
* key and may thus be used to select a key for unattended adsk
* adding. */
if (find_by_primary_fpr (ctrl, fpr, &keyblock, &kdbhd))
if ((err = find_by_primary_fpr (ctrl, fpr, &keyblock, &kdbhd)))
goto leave;
if (fix_keyblock (ctrl, &keyblock))
@ -3286,6 +3301,7 @@ keyedit_quick_addadsk (ctrl_t ctrl, const char *fpr, const char *adskfpr)
if (!opt.verbose)
show_key_with_all_names (ctrl, es_stdout, keyblock, 0, 0, 0, 0, 0, 1);
log_error ("%s%s", _("Key is revoked."), "\n");
err = gpg_error (GPG_ERR_CERT_REVOKED);
goto leave;
}
@ -3310,6 +3326,8 @@ keyedit_quick_addadsk (ctrl_t ctrl, const char *fpr, const char *adskfpr)
}
leave:
if (err)
write_status_error ("keyedit.addadsk", err);
release_kbnode (keyblock);
keydb_release (kdbhd);
}
@ -3318,7 +3336,7 @@ keyedit_quick_addadsk (ctrl_t ctrl, const char *fpr, const char *adskfpr)
/* Unattended expiration setting function for the main key. If
* SUBKEYFPRS is not NULL and SUBKEYSFPRS[0] is neither NULL, it is
* expected to be an array of fingerprints for subkeys to change. It
* may also be an array which just one item "*" to indicate that all
* may also be an array with only the item "*" to indicate that all
* keys shall be set to that expiration date.
*/
void

View file

@ -131,6 +131,18 @@ struct output_control_s
};
/* An object to help communicating with the actual key generation
* code. */
struct common_gen_cb_parm_s
{
/* This variable set to the result of agent_genkey. The callback
* may take a copy of this so that the result can be used after we
* are back from the deep key generation call stack. */
gcry_sexp_t genkey_result;
};
typedef struct common_gen_cb_parm_s *common_gen_cb_parm_t;
/* FIXME: These globals vars are ugly. And using MAX_PREFS even for
* aeads is useless, given that we don't expects more than a very few
* algorithms. */
@ -159,7 +171,7 @@ static void do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
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, int keygen_flags);
u32 expireval, int *keygen_flags);
static unsigned int get_keysize_range (int algo,
unsigned int *min, unsigned int *max);
@ -1266,6 +1278,39 @@ write_keybinding (ctrl_t ctrl, kbnode_t root,
}
/* Returns true if SEXP specified the curve ED448 or X448. */
static int
curve_is_448 (gcry_sexp_t sexp)
{
gcry_sexp_t list, l2;
char *curve;
int result;
list = gcry_sexp_find_token (sexp, "public-key", 0);
if (!list)
return 0; /* Not a public key. */
l2 = gcry_sexp_cadr (list);
gcry_sexp_release (list);
list = l2;
if (!list)
return 0; /* Bad public key. */
l2 = gcry_sexp_find_token (list, "curve", 0);
gcry_sexp_release (list);
if (!l2)
return 0; /* No curve parameter. */
curve = gcry_sexp_nth_string (l2, 1);
gcry_sexp_release (l2);
if (!curve)
return 0; /* Bad curve parameter. */
result = (!ascii_strcasecmp (curve, "X448")
|| !ascii_strcasecmp (curve, "Ed448")
|| !ascii_strcasecmp (curve, "cv448"));
xfree (curve);
return result;
}
static gpg_error_t
ecckey_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp, int algo)
{
@ -1404,7 +1449,7 @@ static int
do_create_from_keygrip (ctrl_t ctrl, int algo,
const char *hexkeygrip, int cardkey,
kbnode_t pub_root, u32 timestamp, u32 expireval,
int is_subkey, int keygen_flags)
int is_subkey, int *keygen_flags)
{
int err;
PACKET *pkt;
@ -1448,6 +1493,10 @@ do_create_from_keygrip (ctrl_t ctrl, int algo,
return err;
}
/* For X448 we force the use of v5 packets. */
if (curve_is_448 (s_key))
*keygen_flags |= KEYGEN_FLAG_CREATE_V5_KEY;
/* Build a public key packet. */
pk = xtrycalloc (1, sizeof *pk);
if (!pk)
@ -1458,7 +1507,7 @@ do_create_from_keygrip (ctrl_t ctrl, int algo,
}
pk->timestamp = timestamp;
pk->version = (keygen_flags & KEYGEN_FLAG_CREATE_V5_KEY)? 5 : 4;
pk->version = (*keygen_flags & KEYGEN_FLAG_CREATE_V5_KEY)? 5 : 4;
if (expireval)
pk->expiredate = pk->timestamp + expireval;
pk->pubkey_algo = algo;
@ -1494,12 +1543,17 @@ do_create_from_keygrip (ctrl_t ctrl, int algo,
}
/* Common code for the key generation function gen_xxx. */
/* Common code for the key generation function gen_xxx. The optinal
* (COMMON_GEN_CB,COMMON_GEN_CB_PARM) can be used as communication
* object.
*/
static int
common_gen (const char *keyparms, int algo, const char *algoelem,
kbnode_t pub_root, u32 timestamp, u32 expireval, int is_subkey,
int keygen_flags, const char *passphrase,
char **cache_nonce_addr, char **passwd_nonce_addr)
char **cache_nonce_addr, char **passwd_nonce_addr,
gpg_error_t (*common_gen_cb)(common_gen_cb_parm_t),
common_gen_cb_parm_t common_gen_cb_parm)
{
int err;
PACKET *pkt;
@ -1516,6 +1570,18 @@ common_gen (const char *keyparms, int algo, const char *algoelem,
return err;
}
if (common_gen_cb && common_gen_cb_parm)
{
common_gen_cb_parm->genkey_result = s_key;
err = common_gen_cb (common_gen_cb_parm);
common_gen_cb_parm->genkey_result = NULL;
if (err)
{
gcry_sexp_release (s_key);
return err;
}
}
pk = xtrycalloc (1, sizeof *pk);
if (!pk)
{
@ -1568,7 +1634,9 @@ static int
gen_elg (int algo, unsigned int nbits, KBNODE pub_root,
u32 timestamp, u32 expireval, int is_subkey,
int keygen_flags, const char *passphrase,
char **cache_nonce_addr, char **passwd_nonce_addr)
char **cache_nonce_addr, char **passwd_nonce_addr,
gpg_error_t (*common_gen_cb)(common_gen_cb_parm_t),
common_gen_cb_parm_t common_gen_cb_parm)
{
int err;
char *keyparms;
@ -1610,7 +1678,8 @@ gen_elg (int algo, unsigned int nbits, KBNODE pub_root,
err = common_gen (keyparms, algo, "pgy",
pub_root, timestamp, expireval, is_subkey,
keygen_flags, passphrase,
cache_nonce_addr, passwd_nonce_addr);
cache_nonce_addr, passwd_nonce_addr,
common_gen_cb, common_gen_cb_parm);
xfree (keyparms);
}
@ -1625,7 +1694,9 @@ static gpg_error_t
gen_dsa (unsigned int nbits, KBNODE pub_root,
u32 timestamp, u32 expireval, int is_subkey,
int keygen_flags, const char *passphrase,
char **cache_nonce_addr, char **passwd_nonce_addr)
char **cache_nonce_addr, char **passwd_nonce_addr,
gpg_error_t (*common_gen_cb)(common_gen_cb_parm_t),
common_gen_cb_parm_t common_gen_cb_parm)
{
int err;
unsigned int qbits;
@ -1699,7 +1770,8 @@ gen_dsa (unsigned int nbits, KBNODE pub_root,
err = common_gen (keyparms, PUBKEY_ALGO_DSA, "pqgy",
pub_root, timestamp, expireval, is_subkey,
keygen_flags, passphrase,
cache_nonce_addr, passwd_nonce_addr);
cache_nonce_addr, passwd_nonce_addr,
common_gen_cb, common_gen_cb_parm);
xfree (keyparms);
}
@ -1709,13 +1781,17 @@ gen_dsa (unsigned int nbits, KBNODE pub_root,
/*
* Generate an ECC key
* Generate an ECC key.
* Note that KEYGEN_FLAGS might be updated by this function to
* indicate the forced creation of a v5 key.
*/
static gpg_error_t
gen_ecc (int algo, const char *curve, kbnode_t pub_root,
u32 timestamp, u32 expireval, int is_subkey,
int keygen_flags, const char *passphrase,
char **cache_nonce_addr, char **passwd_nonce_addr)
int *keygen_flags, const char *passphrase,
char **cache_nonce_addr, char **passwd_nonce_addr,
gpg_error_t (*common_gen_cb)(common_gen_cb_parm_t),
common_gen_cb_parm_t common_gen_cb_parm)
{
gpg_error_t err;
char *keyparms;
@ -1741,40 +1817,52 @@ gen_ecc (int algo, const char *curve, kbnode_t pub_root,
/* Note that we use the "comp" flag with EdDSA to request the use of
a 0x40 compression prefix octet. */
if (algo == PUBKEY_ALGO_EDDSA && !strcmp (curve, "Ed25519"))
keyparms = xtryasprintf
("(genkey(ecc(curve %zu:%s)(flags eddsa comp%s)))",
strlen (curve), curve,
(((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
&& (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
" transient-key" : ""));
{
keyparms = xtryasprintf
("(genkey(ecc(curve %zu:%s)(flags eddsa comp%s)))",
strlen (curve), curve,
(((*keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
&& (*keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
" transient-key" : ""));
}
else if (algo == PUBKEY_ALGO_EDDSA && !strcmp (curve, "Ed448"))
keyparms = xtryasprintf
("(genkey(ecc(curve %zu:%s)(flags comp%s)))",
strlen (curve), curve,
(((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
&& (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
" transient-key" : ""));
{
*keygen_flags |= KEYGEN_FLAG_CREATE_V5_KEY;
keyparms = xtryasprintf
("(genkey(ecc(curve %zu:%s)(flags comp%s)))",
strlen (curve), curve,
(((*keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
&& (*keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
" transient-key" : ""));
}
else if (algo == PUBKEY_ALGO_ECDH && !strcmp (curve, "Curve25519"))
keyparms = xtryasprintf
("(genkey(ecc(curve %zu:%s)(flags djb-tweak comp%s)))",
{
keyparms = xtryasprintf
("(genkey(ecc(curve %zu:%s)(flags djb-tweak comp%s)))",
strlen (curve), curve,
(((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
&& (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
" transient-key" : ""));
(((*keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
&& (*keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
" transient-key" : ""));
}
else if (algo == PUBKEY_ALGO_ECDH && !strcmp (curve, "X448"))
keyparms = xtryasprintf
("(genkey(ecc(curve %zu:%s)(flags comp%s)))",
strlen (curve), curve,
(((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
&& (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
" transient-key" : ""));
{
*keygen_flags |= KEYGEN_FLAG_CREATE_V5_KEY;
keyparms = xtryasprintf
("(genkey(ecc(curve %zu:%s)(flags comp%s)))",
strlen (curve), curve,
(((*keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
&& (*keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
" transient-key" : ""));
}
else
keyparms = xtryasprintf
("(genkey(ecc(curve %zu:%s)(flags nocomp%s)))",
strlen (curve), curve,
(((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
&& (keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
" transient-key" : ""));
{
keyparms = xtryasprintf
("(genkey(ecc(curve %zu:%s)(flags nocomp%s)))",
strlen (curve), curve,
(((*keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY)
&& (*keygen_flags & KEYGEN_FLAG_NO_PROTECTION))?
" transient-key" : ""));
}
if (!keyparms)
err = gpg_error_from_syserror ();
@ -1782,8 +1870,9 @@ gen_ecc (int algo, const char *curve, kbnode_t pub_root,
{
err = common_gen (keyparms, algo, "",
pub_root, timestamp, expireval, is_subkey,
keygen_flags, passphrase,
cache_nonce_addr, passwd_nonce_addr);
*keygen_flags, passphrase,
cache_nonce_addr, passwd_nonce_addr,
common_gen_cb, common_gen_cb_parm);
xfree (keyparms);
}
@ -1798,7 +1887,9 @@ static int
gen_rsa (int algo, unsigned int nbits, KBNODE pub_root,
u32 timestamp, u32 expireval, int is_subkey,
int keygen_flags, const char *passphrase,
char **cache_nonce_addr, char **passwd_nonce_addr)
char **cache_nonce_addr, char **passwd_nonce_addr,
gpg_error_t (*common_gen_cb)(common_gen_cb_parm_t),
common_gen_cb_parm_t common_gen_cb_parm)
{
int err;
char *keyparms;
@ -1840,7 +1931,8 @@ gen_rsa (int algo, unsigned int nbits, KBNODE pub_root,
err = common_gen (keyparms, algo, "ne",
pub_root, timestamp, expireval, is_subkey,
keygen_flags, passphrase,
cache_nonce_addr, passwd_nonce_addr);
cache_nonce_addr, passwd_nonce_addr,
common_gen_cb, common_gen_cb_parm);
xfree (keyparms);
}
@ -3200,12 +3292,15 @@ ask_user_id (int mode, int full, KBNODE keyblock)
/* Basic key generation. Here we divert to the actual generation
routines based on the requested algorithm. */
* routines based on the requested algorithm. KEYGEN_FLAGS might be
* updated by this function. */
static int
do_create (int algo, unsigned int nbits, const char *curve, kbnode_t pub_root,
u32 timestamp, u32 expiredate, int is_subkey,
int keygen_flags, const char *passphrase,
char **cache_nonce_addr, char **passwd_nonce_addr)
int *keygen_flags, const char *passphrase,
char **cache_nonce_addr, char **passwd_nonce_addr,
gpg_error_t (*common_gen_cb)(common_gen_cb_parm_t),
common_gen_cb_parm_t common_gen_cb_parm)
{
gpg_error_t err;
@ -3220,22 +3315,26 @@ do_create (int algo, unsigned int nbits, const char *curve, kbnode_t pub_root,
if (algo == PUBKEY_ALGO_ELGAMAL_E)
err = gen_elg (algo, nbits, pub_root, timestamp, expiredate, is_subkey,
keygen_flags, passphrase,
cache_nonce_addr, passwd_nonce_addr);
*keygen_flags, passphrase,
cache_nonce_addr, passwd_nonce_addr,
common_gen_cb, common_gen_cb_parm);
else if (algo == PUBKEY_ALGO_DSA)
err = gen_dsa (nbits, pub_root, timestamp, expiredate, is_subkey,
keygen_flags, passphrase,
cache_nonce_addr, passwd_nonce_addr);
*keygen_flags, passphrase,
cache_nonce_addr, passwd_nonce_addr,
common_gen_cb, common_gen_cb_parm);
else if (algo == PUBKEY_ALGO_ECDSA
|| algo == PUBKEY_ALGO_EDDSA
|| algo == PUBKEY_ALGO_ECDH)
err = gen_ecc (algo, curve, pub_root, timestamp, expiredate, is_subkey,
keygen_flags, passphrase,
cache_nonce_addr, passwd_nonce_addr);
cache_nonce_addr, passwd_nonce_addr,
common_gen_cb, common_gen_cb_parm);
else if (algo == PUBKEY_ALGO_RSA)
err = gen_rsa (algo, nbits, pub_root, timestamp, expiredate, is_subkey,
keygen_flags, passphrase,
cache_nonce_addr, passwd_nonce_addr);
*keygen_flags, passphrase,
cache_nonce_addr, passwd_nonce_addr,
common_gen_cb, common_gen_cb_parm);
else
BUG();
@ -4106,7 +4205,7 @@ parse_revocation_key (const char *fname,
pn++;
for(i=0;i<MAX_FINGERPRINT_LEN && *pn;i++,pn+=2)
for(i=0;i<MAX_FINGERPRINT_LEN && *pn && !spacep (pn);i++,pn+=2)
{
int c=hextobyte(pn);
if(c==-1)
@ -4247,12 +4346,13 @@ proc_parameter_file (ctrl_t ctrl, struct para_data_s *para, const char *fname,
if (!err)
{
/* Default to algo capabilities if subkey-usage is not
provided */
provided. Take care not to include RENC. */
r = xmalloc_clear (sizeof(*r));
r->key = pSUBKEYUSAGE;
r->u.usage = (is_default
? PUBKEY_USAGE_ENC
: openpgp_pk_algo_usage (algo));
: (openpgp_pk_algo_usage (algo)
& ~PUBKEY_USAGE_RENC) );
append_to_parameter (para, r);
}
else if (err == -1)
@ -5100,7 +5200,7 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname,
strcpy (r->u.value, curve);
r->next = para;
para = r;
if (!strcmp (curve, "Ed448"))
if (!strcmp (curve, "X448") || !strcmp (curve, "Ed448"))
{
r = xmalloc_clear (sizeof *r + 20);
r->key = pVERSION;
@ -5182,7 +5282,7 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname,
strcpy (r->u.value, curve);
r->next = para;
para = r;
if (!strcmp (curve, "Ed448"))
if (!strcmp (curve, "X448") || !strcmp (curve, "Ed448"))
{
r = xmalloc_clear (sizeof *r + 20);
r->key = pVERSION;
@ -5613,7 +5713,7 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
err = do_create_from_keygrip (ctrl, algo, key_from_hexgrip, cardkey,
pub_root,
keytimestamp,
expire, 0, keygen_flags);
expire, 0, &keygen_flags);
else if (!card)
err = do_create (algo,
get_parameter_uint( para, pKEYLENGTH ),
@ -5621,13 +5721,14 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
pub_root,
keytimestamp,
expire, 0,
keygen_flags,
&keygen_flags,
get_parameter_passphrase (para),
&cache_nonce, NULL);
&cache_nonce, NULL,
NULL, NULL);
else
err = gen_card_key (1, algo,
1, pub_root, &keytimestamp,
expire, keygen_flags);
expire, &keygen_flags);
/* Get the pointer to the generated public key packet. */
if (!err)
@ -5671,7 +5772,8 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
{
err = gen_card_key (3, get_parameter_algo (ctrl, para,
pAUTHKEYTYPE, NULL ),
0, pub_root, &authkeytimestamp, expire, keygen_flags);
0, pub_root, &authkeytimestamp, expire,
&keygen_flags);
if (!err)
err = write_keybinding (ctrl, pub_root, pri_psk, NULL,
PUBKEY_USAGE_AUTH, signtimestamp, cache_nonce);
@ -5681,7 +5783,6 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
{
int subkey_algo = get_parameter_algo (ctrl, para, pSUBKEYTYPE, NULL);
s = NULL;
key_from_hexgrip = get_parameter_value (para, pSUBKEYGRIP);
keygen_flags = outctrl->keygen_flags;
@ -5693,8 +5794,47 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
key_from_hexgrip, cardkey,
pub_root, subkeytimestamp,
get_parameter_u32 (para, pSUBKEYEXPIRE),
1, keygen_flags);
else if (!card || (s = get_parameter_value (para, pCARDBACKUPKEY)))
1, &keygen_flags);
else if (get_parameter_value (para, pCARDBACKUPKEY))
{
int lastmode;
unsigned int mykeygenflags = KEYGEN_FLAG_NO_PROTECTION;
err = agent_set_ephemeral_mode (ctrl, 1, &lastmode);
if (err)
log_error ("error switching to ephemeral mode: %s\n",
gpg_strerror (err));
else
{
err = do_create (subkey_algo,
get_parameter_uint (para, pSUBKEYLENGTH),
get_parameter_value (para, pSUBKEYCURVE),
pub_root,
subkeytimestamp,
get_parameter_u32 (para, pSUBKEYEXPIRE), 1,
&mykeygenflags,
get_parameter_passphrase (para),
&cache_nonce, NULL,
NULL, NULL);
/* Get the pointer to the generated public subkey packet. */
if (!err)
{
kbnode_t node;
for (node = pub_root; node; node = node->next)
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
sub_psk = node->pkt->pkt.public_key;
log_assert (sub_psk);
err = card_store_key_with_backup (ctrl,
sub_psk, gnupg_homedir ());
}
/* Reset the ephemeral mode as needed. */
if (!lastmode && agent_set_ephemeral_mode (ctrl, 0, NULL))
log_error ("error clearing the ephemeral mode\n");
}
}
else if (!card)
{
err = do_create (subkey_algo,
get_parameter_uint (para, pSUBKEYLENGTH),
@ -5702,10 +5842,10 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
pub_root,
subkeytimestamp,
get_parameter_u32 (para, pSUBKEYEXPIRE), 1,
s? KEYGEN_FLAG_NO_PROTECTION : keygen_flags,
&keygen_flags,
get_parameter_passphrase (para),
&cache_nonce, NULL);
/* Get the pointer to the generated public subkey packet. */
&cache_nonce, NULL,
NULL, NULL);
if (!err)
{
kbnode_t node;
@ -5714,16 +5854,12 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para,
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
sub_psk = node->pkt->pkt.public_key;
log_assert (sub_psk);
if (s)
err = card_store_key_with_backup (ctrl,
sub_psk, gnupg_homedir ());
}
}
else
{
err = gen_card_key (2, subkey_algo, 0, pub_root,
&subkeytimestamp, expire, keygen_flags);
&subkeytimestamp, expire, &keygen_flags);
}
if (!err)
@ -6097,7 +6233,7 @@ generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock, const char *algostr,
keyblock,
keytime? keytime : cur_time,
expire, 1,
keygen_flags);
&keygen_flags);
}
else
{
@ -6113,8 +6249,8 @@ generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock, const char *algostr,
passwd = NULL;
err = do_create (algo, nbits, curve,
keyblock, cur_time, expire, 1, keygen_flags,
passwd, &cache_nonce, &passwd_nonce);
keyblock, cur_time, expire, 1, &keygen_flags,
passwd, &cache_nonce, &passwd_nonce, NULL, NULL);
}
if (err)
goto leave;
@ -6237,7 +6373,7 @@ generate_card_subkeypair (ctrl_t ctrl, kbnode_t pub_keyblock,
/* Note, that depending on the backend, the card key generation may
update CUR_TIME. */
err = gen_card_key (keyno, algo, 0, pub_keyblock, &cur_time, expire,
keygen_flags);
&keygen_flags);
/* Get the pointer to the generated public subkey packet. */
if (!err)
{
@ -6283,11 +6419,10 @@ write_keyblock( IOBUF out, KBNODE node )
}
/* Note that timestamp is an in/out arg.
* FIXME: Does not yet support v5 keys. */
/* Note that timestamp is an in/out arg. */
static gpg_error_t
gen_card_key (int keyno, int algo, int is_primary, kbnode_t pub_root,
u32 *timestamp, u32 expireval, int keygen_flags)
u32 *timestamp, u32 expireval, int *keygen_flags)
{
#ifdef ENABLE_CARD_SUPPORT
gpg_error_t err;
@ -6351,6 +6486,10 @@ gen_card_key (int keyno, int algo, int is_primary, kbnode_t pub_root,
return err;
}
/* Force creation of v5 keys for X448. */
if (curve_is_448 (s_key))
*keygen_flags |= KEYGEN_FLAG_CREATE_V5_KEY;
if (algo == PUBKEY_ALGO_RSA)
err = key_from_sexp (pk->pkey, s_key, "public-key", "ne");
else if (algo == PUBKEY_ALGO_ECDSA
@ -6369,7 +6508,7 @@ gen_card_key (int keyno, int algo, int is_primary, kbnode_t pub_root,
}
pk->timestamp = *timestamp;
pk->version = (keygen_flags & KEYGEN_FLAG_CREATE_V5_KEY)? 5 : 4;
pk->version = (*keygen_flags & KEYGEN_FLAG_CREATE_V5_KEY)? 5 : 4;
if (expireval)
pk->expiredate = pk->timestamp + expireval;
pk->pubkey_algo = algo;

View file

@ -408,6 +408,7 @@ EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode;
#define IMPORT_COLLAPSE_UIDS (1<<15)
#define IMPORT_COLLAPSE_SUBKEYS (1<<16)
#define IMPORT_BULK (1<<17)
#define IMPORT_IGNORE_ATTRIBUTES (1<<18)
#define EXPORT_LOCAL_SIGS (1<<0)
#define EXPORT_ATTRIBUTES (1<<1)

View file

@ -2765,7 +2765,16 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
{
ski->is_protected = 1;
ski->s2k.count = 0;
if (ski->algo == 254 || ski->algo == 255)
if (ski->algo == 253)
{
if (list_mode)
es_fprintf (listfp,
"\tS2K pseudo algo %d is not yet supported\n",
ski->algo);
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
goto leave;
}
else if (ski->algo == 254 || ski->algo == 255)
{
if (pktlen < 3)
{

View file

@ -444,8 +444,9 @@ do_sign (ctrl_t ctrl, PKT_public_key *pksk, PKT_signature *sig,
goto leave;
}
/* Check compliance. */
if (! gnupg_digest_is_allowed (opt.compliance, 1, mdalgo))
/* Check compliance but always allow for key revocations. */
if (!IS_KEY_REV (sig)
&& ! gnupg_digest_is_allowed (opt.compliance, 1, mdalgo))
{
log_error (_("digest algorithm '%s' may not be used in %s mode\n"),
gcry_md_algo_name (mdalgo),
@ -454,9 +455,10 @@ do_sign (ctrl_t ctrl, PKT_public_key *pksk, PKT_signature *sig,
goto leave;
}
if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_SIGNING,
pksk->pubkey_algo, 0,
pksk->pkey, nbits_from_pk (pksk), NULL))
if (!IS_KEY_REV (sig)
&& ! gnupg_pk_is_allowed (opt.compliance, PK_USE_SIGNING,
pksk->pubkey_algo, 0,
pksk->pkey, nbits_from_pk (pksk), NULL))
{
log_error (_("key %s may not be used for signing in %s mode\n"),
keystr_from_pk (pksk),