From 3738b0a99a45c09fa5f66e80110dbdff185bbf7c Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Fri, 7 Feb 2025 11:10:09 +0100 Subject: [PATCH] gpg: Store Link attributes for composite keys. * g10/call-agent.c (agent_crosslink_keys): New. * g10/keygen.c (common_gen): Store the Link attribute. -- The Link attribute may be useful to quickly find the other part of a composite private key. GnuPG-bug-id: 6638 --- g10/call-agent.c | 24 ++++++++++++++++++++++++ g10/call-agent.h | 4 ++++ g10/keygen.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/g10/call-agent.c b/g10/call-agent.c index 54d8f62f1..bdde9b053 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -2673,6 +2673,30 @@ agent_genkey (ctrl_t ctrl, char **cache_nonce_addr, char **passwd_nonce_addr, } +/* Add the Link attribute to both given keys. */ +gpg_error_t +agent_crosslink_keys (ctrl_t ctrl, const char *hexgrip1, const char *hexgrip2) +{ + gpg_error_t err; + char line[ASSUAN_LINELENGTH]; + + err = start_agent (ctrl, 0); + if (err) + goto leave; + + snprintf (line, sizeof line, "KEYATTR %s Link: %s", hexgrip1, hexgrip2); + err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (err) + goto leave; + + snprintf (line, sizeof line, "KEYATTR %s Link: %s", hexgrip2, hexgrip1); + err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + + leave: + return err; +} + + /* Call the agent to read the public key part for a given keygrip. * Values from FROMCARD: diff --git a/g10/call-agent.h b/g10/call-agent.h index 1e72dc03f..282ba066b 100644 --- a/g10/call-agent.h +++ b/g10/call-agent.h @@ -202,6 +202,10 @@ gpg_error_t agent_genkey (ctrl_t ctrl, const char *passphrase, time_t timestamp, gcry_sexp_t *r_pubkey); +/* Apply the Link attributes. */ +gpg_error_t agent_crosslink_keys (ctrl_t ctrl, + const char *hexgrip1, const char *hexgrip2); + /* Read a public key. FROMCARD may be 0, 1, or 2. */ gpg_error_t agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip, unsigned char **r_pubkey); diff --git a/g10/keygen.c b/g10/keygen.c index df6540273..33bdb64c0 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -1859,6 +1859,10 @@ common_gen (const char *keyparms, const char *keyparms2, if (keyparms2) { + unsigned char tmpgrip[KEYGRIP_LEN]; + char hexgrip1[2*KEYGRIP_LEN+1]; + char hexgrip2[2*KEYGRIP_LEN+1]; + err = agent_genkey (NULL, NULL, NULL, keyparms2, 1 /* No protection */, NULL, timestamp, @@ -1870,6 +1874,31 @@ common_gen (const char *keyparms, const char *keyparms2, gcry_sexp_release (s_key); return err; } + + if (!gcry_pk_get_keygrip (s_key, tmpgrip)) + { + log_error ("error computing keygrip for generated key\n"); + gcry_sexp_release (s_key); + gcry_sexp_release (s_key2); + return gpg_error (GPG_ERR_GENERAL); + } + bin2hex (tmpgrip, KEYGRIP_LEN, hexgrip1); + if (!gcry_pk_get_keygrip (s_key2, tmpgrip)) + { + log_error ("error computing keygrip for generated key\n"); + gcry_sexp_release (s_key); + gcry_sexp_release (s_key2); + return gpg_error (GPG_ERR_GENERAL); + } + bin2hex (tmpgrip, KEYGRIP_LEN, hexgrip2); + err = agent_crosslink_keys (NULL, hexgrip1, hexgrip2); + if (err) + { + log_error ("error setting link attributes for generated keys\n"); + gcry_sexp_release (s_key); + gcry_sexp_release (s_key2); + return gpg_error (GPG_ERR_GENERAL); + } } if (common_gen_cb && common_gen_cb_parm)