summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2024-06-05 17:04:33 +0200
committerWerner Koch <wk@gnupg.org>2024-06-05 17:04:33 +0200
commit77afc9ee1c75a28083edf6d98888f9b472c3e39d (patch)
treef1178f2db721cc404602110cf9227deaaa037a98
parentgpg: Do not show RENC if no key capabilities are found for a key. (diff)
downloadgnupg2-77afc9ee1c75a28083edf6d98888f9b472c3e39d.tar.xz
gnupg2-77afc9ee1c75a28083edf6d98888f9b472c3e39d.zip
gpg: Add magic parameter "default" to --quick-add-adsk.
* g10/getkey.c (has_key_with_fingerprint): New. * g10/keyedit.c (menu_addadsk): Replace code by new function. (keyedit_quick_addadsk): Handle magic arg "default". * g10/keygen.c (append_all_default_adsks): New. -- GnuPG-bug-id: 6882
-rw-r--r--doc/gpg.texi4
-rw-r--r--g10/getkey.c27
-rw-r--r--g10/keydb.h4
-rw-r--r--g10/keyedit.c29
-rw-r--r--g10/keygen.c41
-rw-r--r--g10/main.h1
6 files changed, 88 insertions, 18 deletions
diff --git a/doc/gpg.texi b/doc/gpg.texi
index af87064e5..203f3339f 100644
--- a/doc/gpg.texi
+++ b/doc/gpg.texi
@@ -779,7 +779,9 @@ the fingerprint @var{fpr}. @var{adskfpr} is the fingerprint of
another key's encryption subkey. A subkey is commonly used here
because by default a primary key has no encryption capability. Use
the option @option{--with-subkey-fingerprint} with a list command to
-display the subkey fingerprints.
+display the subkey fingerprints. If the string "default" is used for
+@var{adskfpr} all missing ADSKs configured with
+@option{--default-new-key-adsk} are added.
@item --generate-key
@opindex generate-key
diff --git a/g10/getkey.c b/g10/getkey.c
index 49ffe0adb..d97690a83 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -4588,3 +4588,30 @@ have_secret_key_with_kid (ctrl_t ctrl, u32 *keyid)
keydb_release (kdbhd);
return result;
}
+
+
+/* Return an error if KEYBLOCK has a primary or subkey with the given
+ * fingerprint (FPR,FPRLEN). */
+gpg_error_t
+has_key_with_fingerprint (kbnode_t keyblock, const byte *fpr, size_t fprlen)
+{
+ kbnode_t node;
+ PKT_public_key *pk;
+ byte pkfpr[MAX_FINGERPRINT_LEN];
+ size_t pkfprlen;
+
+ for (node = keyblock; node; node = node->next)
+ {
+ if (node->pkt->pkttype == PKT_PUBLIC_KEY
+ || node->pkt->pkttype == PKT_PUBLIC_SUBKEY
+ || node->pkt->pkttype == PKT_SECRET_KEY
+ || node->pkt->pkttype == PKT_SECRET_SUBKEY)
+ {
+ pk = node->pkt->pkt.public_key;
+ fingerprint_from_pk (pk, pkfpr, &pkfprlen);
+ if (pkfprlen == fprlen && !memcmp (pkfpr, fpr, fprlen))
+ return gpg_error (GPG_ERR_DUP_KEY);
+ }
+ }
+ return 0;
+}
diff --git a/g10/keydb.h b/g10/keydb.h
index 9cb63cf73..d96debeb7 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -485,6 +485,10 @@ int parse_auto_key_locate(const char *options);
int parse_key_origin (char *string);
const char *key_origin_string (int origin);
+/* Return an error if KEYBLOCK has a primary or subkey with the fpr. */
+gpg_error_t has_key_with_fingerprint (kbnode_t keyblock,
+ const byte *fpr, size_t fprlen);
+
/*-- keyid.c --*/
int pubkey_letter( int algo );
char *pubkey_string (PKT_public_key *pk, char *buffer, size_t bufsize);
diff --git a/g10/keyedit.c b/g10/keyedit.c
index 7a33c9ef3..0fb19645d 100644
--- a/g10/keyedit.c
+++ b/g10/keyedit.c
@@ -3389,7 +3389,15 @@ keyedit_quick_addadsk (ctrl_t ctrl, const char *fpr, const char *adskfpr)
/* Locate and add the ADSK. Note that the called function already
* prints error messages. */
- if (menu_addadsk (ctrl, keyblock, adskfpr))
+ if (adskfpr && !ascii_strcasecmp (adskfpr, "default"))
+ {
+ err = append_all_default_adsks (ctrl, keyblock);
+ if (!err)
+ modified = 1;
+ else if (gpg_err_code (err) == GPG_ERR_FALSE)
+ err = 0;
+ }
+ else if (menu_addadsk (ctrl, keyblock, adskfpr))
modified = 1;
else
log_inc_errorcount (); /* (We use log_info in menu_adsk) */
@@ -4971,7 +4979,6 @@ append_adsk_to_key (ctrl_t ctrl, kbnode_t keyblock, PKT_public_key *adsk)
}
-
/*
* Ask for a new additional decryption subkey and add it to the key
* block. Returns true if the keyblock was changed and false
@@ -4989,7 +4996,7 @@ menu_addadsk (ctrl_t ctrl, kbnode_t pub_keyblock, const char *adskfpr)
KEYDB_SEARCH_DESC desc;
byte fpr[MAX_FINGERPRINT_LEN];
size_t fprlen;
- kbnode_t node, node2;
+ kbnode_t node;
log_assert (pub_keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
@@ -5073,22 +5080,10 @@ menu_addadsk (ctrl_t ctrl, kbnode_t pub_keyblock, const char *adskfpr)
}
/* Check that the selected subkey is not yet on our keyblock. */
- for (node2 = pub_keyblock; node2; node2 = node2->next)
- {
- if (node2->pkt->pkttype == PKT_PUBLIC_KEY
- || node2->pkt->pkttype == PKT_PUBLIC_SUBKEY)
- {
- pk = node2->pkt->pkt.public_key;
- fingerprint_from_pk (pk, fpr, &fprlen);
- if (fprlen == desc.fprlen
- && !memcmp (fpr, desc.u.fpr, fprlen))
- break;
- }
- }
- if (node2)
+ err = has_key_with_fingerprint (pub_keyblock, desc.u.fpr, desc.fprlen);
+ if (err)
{
log_info (_("key \"%s\" is already on this keyblock\n"), answer);
- err = gpg_error (GPG_ERR_DUP_KEY);
if (adskfpr)
goto leave;
continue;
diff --git a/g10/keygen.c b/g10/keygen.c
index f512f640d..66fe681de 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -174,6 +174,8 @@ static int mdc_available;
static int ks_modify;
static int aead_available;
+static void release_parameter_list (struct para_data_s *r);
+static struct para_data_s *prepare_adsk (ctrl_t ctrl, const char *name);
static gpg_error_t parse_algo_usage_expire (ctrl_t ctrl, int for_subkey,
const char *algostr, const char *usagestr,
const char *expirestr,
@@ -1210,6 +1212,45 @@ keygen_prepare_new_key_adsks (void)
}
+/* Append all default ADSKs to the KEYBLOCK but ignore those which are
+ * already on that keyblock. Returns 0 if any key has been added;
+ * GPG_ERR_FALSE if no key was added or any other error code. */
+gpg_error_t
+append_all_default_adsks (ctrl_t ctrl, kbnode_t keyblock)
+{
+ gpg_error_t err = 0;
+ int any_done = 0;
+ strlist_t sl;
+ struct para_data_s *para;
+ byte adskfpr[MAX_FINGERPRINT_LEN];
+ size_t adskfprlen;
+
+ keygen_prepare_new_key_adsks ();
+ for (sl = opt.def_new_key_adsks; sl && !err; sl = sl->next)
+ {
+ if (!*sl->d)
+ continue;
+ para = prepare_adsk (ctrl, sl->d);
+ if (para)
+ {
+ fingerprint_from_pk (para->u.adsk, adskfpr, &adskfprlen);
+ if (!has_key_with_fingerprint (keyblock, adskfpr, adskfprlen))
+ {
+ err = append_adsk_to_key (ctrl, keyblock, para->u.adsk);
+ if (!err)
+ any_done = 1;
+ }
+ release_parameter_list (para);
+ }
+ }
+
+ if (!err && !any_done)
+ err = gpg_error (GPG_ERR_FALSE);
+
+ return err;
+}
+
+
/* Write a direct key signature to the first key in ROOT using the key
PSK. REVKEY is describes the direct key signature and TIMESTAMP is
the timestamp to set on the signature. */
diff --git a/g10/main.h b/g10/main.h
index 5a84acaba..1c93c96e6 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -328,6 +328,7 @@ gpg_error_t make_backsig (ctrl_t ctrl,
PKT_public_key *sub_pk, PKT_public_key *sub_psk,
u32 timestamp, const char *cache_nonce);
void keygen_prepare_new_key_adsks (void);
+gpg_error_t append_all_default_adsks (ctrl_t ctrl, kbnode_t pub_root);
gpg_error_t generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock,
const char *algostr,
const char *usagestr,