diff options
author | Werner Koch <[email protected]> | 2024-06-03 16:52:06 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2024-06-03 16:52:06 +0000 |
commit | ed118e2ed521d82c1be7765a0a19d5b4f19afe10 (patch) | |
tree | 61c2a3b3cdff0907f6b1546a6b74ba5f1bcf660d /g10/keyedit.c | |
parent | common: New function tokenize_to_strlist. (diff) | |
download | gnupg-ed118e2ed521d82c1be7765a0a19d5b4f19afe10.tar.gz gnupg-ed118e2ed521d82c1be7765a0a19d5b4f19afe10.zip |
gpg: New option --default-new-key-adsk.
* g10/options.h (opt): Add field def_new_key_adsks.
* g10/gpg.c (oDefaultNewKeyADSK): New.
(opts): Add --default-new-key-adsk.
(main): Parse option.
* g10/keyedit.c (menu_addadsk): Factor some code out to ...
(append_adsk_to_key): new. Add compliance check.
* g10/keygen.c (pADSK): New.
(para_data_s): Add adsk to the union.
(release_parameter_list): Free the adsk.
(prepare_adsk): New.
(get_parameter_adsk): New.
(get_parameter_revkey): Remove unneeded arg key and change callers.
(proc_parameter_file): Prepare adsk parameter from the configured
fingerprints.
(do_generate_keypair): Create adsk.
--
GnuPG-bug-id: 6882
Diffstat (limited to 'g10/keyedit.c')
-rw-r--r-- | g10/keyedit.c | 119 |
1 files changed, 81 insertions, 38 deletions
diff --git a/g10/keyedit.c b/g10/keyedit.c index f41e53f6d..303309b79 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -4893,6 +4893,85 @@ fail: } +/* Core function to add an ADSK to the KEYBLOCK. Returns 0 on success + * or an error code. */ +gpg_error_t +append_adsk_to_key (ctrl_t ctrl, kbnode_t keyblock, PKT_public_key *adsk) +{ + gpg_error_t err; + PKT_public_key *main_pk; /* The primary key. */ + PKT_signature *sig = NULL; + kbnode_t adsknode = NULL; + PACKET *pkt; /* (temp. use; will be put into a kbnode_t) */ + + /* First get a copy. */ + adsk = copy_public_key_basics (NULL, adsk); + + /* Check compliance. */ + if (!gnupg_pk_is_compliant (opt.compliance, adsk->pubkey_algo, 0, + adsk->pkey, nbits_from_pk (adsk), NULL)) + { + char pkhex[MAX_FINGERPRINT_LEN*2+1]; + + hexfingerprint (adsk, pkhex, sizeof pkhex); + log_error (_("WARNING: key %s is not suitable for encryption" + " in %s mode\n"), + pkhex, gnupg_compliance_option_string (opt.compliance)); + err = gpg_error (GPG_ERR_FORBIDDEN); + goto leave; + } + + /* Get the primary key. */ + log_assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY); + main_pk = keyblock->pkt->pkt.public_key; + + /* Prepare and append the adsk. */ + keyid_from_pk (main_pk, adsk->main_keyid); /* Fixup main keyid. */ + log_assert ((adsk->pubkey_usage & PUBKEY_USAGE_ENC)); + adsk->pubkey_usage = PUBKEY_USAGE_RENC; /* 'e' -> 'r' */ + pkt = xtrycalloc (1, sizeof *pkt); + if (!pkt) + { + err = gpg_error_from_syserror (); + goto leave; + } + pkt->pkttype = PKT_PUBLIC_SUBKEY; /* Make sure it is a subkey. */ + pkt->pkt.public_key = adsk; + adsknode = new_kbnode (pkt); + + /* Make the signature. */ + err = make_keysig_packet (ctrl, &sig, main_pk, NULL, adsk, main_pk, 0x18, + adsk->timestamp, 0, + keygen_add_key_flags_and_expire, adsk, NULL); + adsk = NULL; /* (owned by adsknode - avoid double free.) */ + if (err) + { + write_status_error ("keysig", err); + log_error ("creating key binding failed: %s\n", gpg_strerror (err)); + goto leave; + } + + /* Append the subkey packet and the binding signature. */ + add_kbnode (keyblock, adsknode); + adsknode = NULL; + pkt = xtrycalloc (1, sizeof *pkt); + if (!pkt) + { + err = gpg_error_from_syserror (); + goto leave; + } + pkt->pkttype = PKT_SIGNATURE; + pkt->pkt.signature = sig; + add_kbnode (keyblock, new_kbnode (pkt)); + + leave: + release_kbnode (adsknode); + free_public_key (adsk); /* Release our copy. */ + return err; +} + + + /* * Ask for a new additional decryption subkey and add it to the key * block. Returns true if the keyblock was changed and false @@ -4903,22 +4982,16 @@ static int menu_addadsk (ctrl_t ctrl, kbnode_t pub_keyblock, const char *adskfpr) { PKT_public_key *pk; - PKT_public_key *sub_pk; - PKT_public_key *main_pk; PKT_public_key *adsk_pk = NULL; kbnode_t adsk_keyblock = NULL; - PKT_signature *sig = NULL; char *answer = NULL; gpg_error_t err; KEYDB_SEARCH_DESC desc; byte fpr[MAX_FINGERPRINT_LEN]; size_t fprlen; kbnode_t node, node2; - kbnode_t subkeynode = NULL; - PACKET *pkt; /* (temp. use; will be put into a kbnode_t) */ log_assert (pub_keyblock->pkt->pkttype == PKT_PUBLIC_KEY); - main_pk = pub_keyblock->pkt->pkt.public_key; for (;;) { @@ -5024,46 +5097,16 @@ menu_addadsk (ctrl_t ctrl, kbnode_t pub_keyblock, const char *adskfpr) break; } - /* Append the subkey. - * Note that we don't use the ADSK_PK directly because this is the - * primary key and in general we use a subkey to which NODE points. - * ADSK_PK has only been used to pass the requested key usage to - * get_pubkey_byname. SUB_PK will point to the actual adsk. */ + /* Append the subkey. */ log_assert (node->pkt->pkttype == PKT_PUBLIC_KEY || node->pkt->pkttype == PKT_PUBLIC_SUBKEY); - sub_pk = copy_public_key_basics (NULL, node->pkt->pkt.public_key); - keyid_from_pk (main_pk, sub_pk->main_keyid); /* Fixup main keyid. */ - log_assert ((sub_pk->pubkey_usage & PUBKEY_USAGE_ENC)); - sub_pk->pubkey_usage = PUBKEY_USAGE_RENC; /* 'e' -> 'r' */ - pkt = xcalloc (1, sizeof *pkt); - pkt->pkttype = PKT_PUBLIC_SUBKEY; /* Make sure it is a subkey. */ - pkt->pkt.public_key = sub_pk; - subkeynode = new_kbnode (pkt); - - /* Make the signature. */ - err = make_keysig_packet (ctrl, &sig, main_pk, NULL, sub_pk, main_pk, 0x18, - sub_pk->timestamp, 0, - keygen_add_key_flags_and_expire, sub_pk, NULL); - if (err) - { - write_status_error ("keysig", err); - log_error ("creating key binding failed: %s\n", gpg_strerror (err)); - goto leave; - } + err = append_adsk_to_key (ctrl, pub_keyblock, node->pkt->pkt.public_key); - /* Append the subkey packet and the binding signature. */ - add_kbnode (pub_keyblock, subkeynode); - subkeynode = NULL; - pkt = xcalloc (1, sizeof *pkt); - pkt->pkttype = PKT_SIGNATURE; - pkt->pkt.signature = sig; - add_kbnode (pub_keyblock, new_kbnode (pkt)); leave: xfree (answer); free_public_key (adsk_pk); release_kbnode (adsk_keyblock); - release_kbnode (subkeynode); if (!err) return 1; /* The keyblock was modified. */ else |