1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

agent: Create and use Token entries to track the display s/n.

* agent/findkey.c (agent_write_private_key): Add arg dispserialno and
update the token.
(agent_write_shadow_key): Add arg dispserialno and adjust all callers.
--

GnuPG-bug-id: 6135

Note that this has been forward ported from 2.2
This commit is contained in:
Werner Koch 2023-05-26 11:59:46 +02:00
parent a048a93ed2
commit 13013ec1c0
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
10 changed files with 102 additions and 29 deletions

View File

@ -452,10 +452,12 @@ void start_command_handler_ssh (ctrl_t, gnupg_fd_t);
/*-- findkey.c --*/ /*-- findkey.c --*/
gpg_error_t agent_modify_description (const char *in, const char *comment, gpg_error_t agent_modify_description (const char *in, const char *comment,
const gcry_sexp_t key, char **result); const gcry_sexp_t key, char **result);
int agent_write_private_key (const unsigned char *grip, gpg_error_t agent_write_private_key (const unsigned char *grip,
const void *buffer, size_t length, int force, const void *buffer, size_t length,
const char *serialno, const char *keyref, int force,
time_t timestamp); const char *serialno, const char *keyref,
const char *dispserialno,
time_t timestamp);
gpg_error_t agent_key_from_file (ctrl_t ctrl, gpg_error_t agent_key_from_file (ctrl_t ctrl,
const char *cache_nonce, const char *cache_nonce,
const char *desc_text, const char *desc_text,
@ -587,7 +589,8 @@ gpg_error_t s2k_hash_passphrase (const char *passphrase, int hashalgo,
unsigned char *key, size_t keylen); unsigned char *key, size_t keylen);
gpg_error_t agent_write_shadow_key (const unsigned char *grip, gpg_error_t agent_write_shadow_key (const unsigned char *grip,
const char *serialno, const char *keyid, const char *serialno, const char *keyid,
const unsigned char *pkbuf, int force); const unsigned char *pkbuf, int force,
const char *dispserialno);
/*-- trustlist.c --*/ /*-- trustlist.c --*/

View File

@ -2432,9 +2432,14 @@ card_key_available (ctrl_t ctrl, const struct card_key_info_s *keyinfo,
hex2bin (keyinfo->keygrip, grip, sizeof (grip)); hex2bin (keyinfo->keygrip, grip, sizeof (grip));
if ( agent_key_available (grip) ) if ( agent_key_available (grip) )
{ {
char *dispserialno;
/* (Shadow)-key is not available in our key storage. */ /* (Shadow)-key is not available in our key storage. */
agent_card_getattr (ctrl, "$DISPSERIALNO", &dispserialno,
keyinfo->keygrip);
err = agent_write_shadow_key (grip, keyinfo->serialno, err = agent_write_shadow_key (grip, keyinfo->serialno,
keyinfo->idstr, pkbuf, 0); keyinfo->idstr, pkbuf, 0, dispserialno);
xfree (dispserialno);
if (err) if (err)
{ {
xfree (pkbuf); xfree (pkbuf);
@ -3282,7 +3287,7 @@ ssh_identity_register (ctrl_t ctrl, ssh_key_type_spec_t *spec,
/* Store this key to our key storage. We do not store a creation /* Store this key to our key storage. We do not store a creation
* timestamp because we simply do not know. */ * timestamp because we simply do not know. */
err = agent_write_private_key (key_grip_raw, buffer, buffer_n, 0, err = agent_write_private_key (key_grip_raw, buffer, buffer_n, 0,
NULL, NULL, 0); NULL, NULL, NULL, 0);
if (err) if (err)
goto out; goto out;

View File

@ -1359,7 +1359,14 @@ cmd_readkey (assuan_context_t ctx, char *line)
if (agent_key_available (grip)) if (agent_key_available (grip))
{ {
/* (Shadow)-key is not available in our key storage. */ /* (Shadow)-key is not available in our key storage. */
rc = agent_write_shadow_key (grip, serialno, keyid, pkbuf, 0); char *dispserialno;
char hexgrip[40+1];
bin2hex (grip, 20, hexgrip);
agent_card_getattr (ctrl, "$DISPSERIALNO", &dispserialno, hexgrip);
rc = agent_write_shadow_key (grip, serialno, keyid, pkbuf, 0,
dispserialno);
xfree (dispserialno);
if (rc) if (rc)
goto leave; goto leave;
} }
@ -2916,11 +2923,11 @@ cmd_import_key (assuan_context_t ctx, char *line)
ctrl->s2k_count); ctrl->s2k_count);
if (!err) if (!err)
err = agent_write_private_key (grip, finalkey, finalkeylen, force, err = agent_write_private_key (grip, finalkey, finalkeylen, force,
NULL, NULL, opt_timestamp); NULL, NULL, NULL, opt_timestamp);
} }
else else
err = agent_write_private_key (grip, key, realkeylen, force, NULL, NULL, err = agent_write_private_key (grip, key, realkeylen, force,
opt_timestamp); NULL, NULL, NULL, opt_timestamp);
leave: leave:
gcry_sexp_release (openpgp_sexp); gcry_sexp_release (openpgp_sexp);

View File

@ -1148,7 +1148,7 @@ convert_from_openpgp_native (ctrl_t ctrl,
&protectedkey, &protectedkeylen, &protectedkey, &protectedkeylen,
ctrl->s2k_count)) ctrl->s2k_count))
agent_write_private_key (grip, protectedkey, protectedkeylen, 1, agent_write_private_key (grip, protectedkey, protectedkeylen, 1,
NULL, NULL, 0); NULL, NULL, NULL, 0);
xfree (protectedkey); xfree (protectedkey);
} }
else else
@ -1157,7 +1157,7 @@ convert_from_openpgp_native (ctrl_t ctrl,
agent_write_private_key (grip, agent_write_private_key (grip,
*r_key, *r_key,
gcry_sexp_canon_len (*r_key, 0, NULL,NULL), gcry_sexp_canon_len (*r_key, 0, NULL,NULL),
1, NULL, NULL, 0); 1, NULL, NULL, NULL, 0);
} }
} }

View File

@ -50,7 +50,7 @@ agent_write_tpm2_shadow_key (ctrl_t ctrl, const unsigned char *grip,
len = gcry_sexp_canon_len (shdkey, 0, NULL, NULL); len = gcry_sexp_canon_len (shdkey, 0, NULL, NULL);
err = agent_write_private_key (grip, shdkey, len, 1 /*force*/, err = agent_write_private_key (grip, shdkey, len, 1 /*force*/,
NULL, NULL, 0); NULL, NULL, NULL, 0);
xfree (shdkey); xfree (shdkey);
if (err) if (err)
log_error ("error writing key: %s\n", gpg_strerror (err)); log_error ("error writing key: %s\n", gpg_strerror (err));

View File

@ -84,12 +84,13 @@ linefeed_to_percent0A (const char *string)
* storage. With FORCE passed as true an existing key with the given * storage. With FORCE passed as true an existing key with the given
* GRIP will get overwritten. If SERIALNO and KEYREF are given a * GRIP will get overwritten. If SERIALNO and KEYREF are given a
* Token line is added to the key if the extended format is used. If * Token line is added to the key if the extended format is used. If
* TIMESTAMP is not zero and the key doies not yet exists it will be * TIMESTAMP is not zero and the key does not yet exists it will be
* recorded as creation date. */ * recorded as creation date. */
int gpg_error_t
agent_write_private_key (const unsigned char *grip, agent_write_private_key (const unsigned char *grip,
const void *buffer, size_t length, int force, const void *buffer, size_t length, int force,
const char *serialno, const char *keyref, const char *serialno, const char *keyref,
const char *dispserialno,
time_t timestamp) time_t timestamp)
{ {
gpg_error_t err; gpg_error_t err;
@ -100,7 +101,10 @@ agent_write_private_key (const unsigned char *grip,
nvc_t pk = NULL; nvc_t pk = NULL;
gcry_sexp_t key = NULL; gcry_sexp_t key = NULL;
int remove = 0; int remove = 0;
char *token0 = NULL;
char *token = NULL; char *token = NULL;
char *dispserialno_buffer = NULL;
char **tokenfields = NULL;
bin2hex (grip, 20, hexgrip); bin2hex (grip, 20, hexgrip);
strcpy (hexgrip+40, ".key"); strcpy (hexgrip+40, ".key");
@ -225,19 +229,34 @@ agent_write_private_key (const unsigned char *grip,
{ {
nve_t item; nve_t item;
const char *s; const char *s;
size_t token0len;
token = strconcat (serialno, " ", keyref, NULL); if (dispserialno)
if (!token) {
/* Escape the DISPSERIALNO. */
dispserialno_buffer = percent_plus_escape (dispserialno);
if (!dispserialno_buffer)
{
err = gpg_error_from_syserror ();
goto leave;
}
dispserialno = dispserialno_buffer;
}
token0 = strconcat (serialno, " ", keyref, NULL);
if (token0)
token = strconcat (token0, " - ", dispserialno? dispserialno:"-", NULL);
if (!token0 || !token)
{ {
err = gpg_error_from_syserror (); err = gpg_error_from_syserror ();
goto leave; goto leave;
} }
/* fixme: the strcmp should compare only the first two strings. */ token0len = strlen (token0);
for (item = nvc_lookup (pk, "Token:"); for (item = nvc_lookup (pk, "Token:");
item; item;
item = nve_next_value (item, "Token:")) item = nve_next_value (item, "Token:"))
if ((s = nve_value (item)) && !strcmp (s, token)) if ((s = nve_value (item)) && !strncmp (s, token0, token0len))
break; break;
if (!item) if (!item)
{ {
@ -248,6 +267,23 @@ agent_write_private_key (const unsigned char *grip,
if (err) if (err)
goto leave; goto leave;
} }
else
{
/* Token exists: Update the display s/n. It may have
* changed due to changes in a newer software version. */
if (s && (tokenfields = strtokenize (s, " \t\n"))
&& tokenfields[0] && tokenfields[1] && tokenfields[2]
&& tokenfields[3]
&& !strcmp (tokenfields[3], dispserialno))
; /* No need to update Token entry. */
else
{
err = nve_set (item, token);
if (err)
goto leave;
}
}
} }
/* If a timestamp has been supplied and the key is new, write a /* If a timestamp has been supplied and the key is new, write a
@ -300,12 +336,15 @@ agent_write_private_key (const unsigned char *grip,
leave: leave:
es_fclose (fp); es_fclose (fp);
if (remove) if (remove && fname)
gnupg_remove (fname); gnupg_remove (fname);
xfree (fname); xfree (fname);
xfree (token);
xfree (token0);
xfree (dispserialno_buffer);
xfree (tokenfields);
gcry_sexp_release (key); gcry_sexp_release (key);
nvc_release (pk); nvc_release (pk);
xfree (token);
return err; return err;
} }
@ -1794,7 +1833,8 @@ agent_delete_key (ctrl_t ctrl, const char *desc_text,
gpg_error_t gpg_error_t
agent_write_shadow_key (const unsigned char *grip, agent_write_shadow_key (const unsigned char *grip,
const char *serialno, const char *keyid, const char *serialno, const char *keyid,
const unsigned char *pkbuf, int force) const unsigned char *pkbuf, int force,
const char *dispserialno)
{ {
gpg_error_t err; gpg_error_t err;
unsigned char *shadow_info; unsigned char *shadow_info;
@ -1821,7 +1861,8 @@ agent_write_shadow_key (const unsigned char *grip,
} }
len = gcry_sexp_canon_len (shdkey, 0, NULL, NULL); len = gcry_sexp_canon_len (shdkey, 0, NULL, NULL);
err = agent_write_private_key (grip, shdkey, len, force, serialno, keyid, 0); err = agent_write_private_key (grip, shdkey, len, force,
serialno, keyid, dispserialno, 0);
xfree (shdkey); xfree (shdkey);
if (err) if (err)
log_error ("error writing key: %s\n", gpg_strerror (err)); log_error ("error writing key: %s\n", gpg_strerror (err));

View File

@ -67,7 +67,8 @@ store_key (gcry_sexp_t private, const char *passphrase, int force,
buf = p; buf = p;
} }
rc = agent_write_private_key (grip, buf, len, force, NULL, NULL, timestamp); rc = agent_write_private_key (grip, buf, len, force,
NULL, NULL, NULL, timestamp);
xfree (buf); xfree (buf);
return rc; return rc;
} }

View File

@ -408,7 +408,15 @@ agent_handle_learn (ctrl_t ctrl, int send, void *assuan_context, int force)
goto leave; goto leave;
} }
rc = agent_write_shadow_key (grip, serialno, item->id, pubkey, force); {
char *dispserialno;
agent_card_getattr (ctrl, "$DISPSERIALNO", &dispserialno,
item->hexgrip);
rc = agent_write_shadow_key (grip, serialno, item->id, pubkey, force,
dispserialno);
xfree (dispserialno);
}
xfree (pubkey); xfree (pubkey);
if (rc) if (rc)
goto leave; goto leave;

View File

@ -372,8 +372,15 @@ agent_pksign_do (ctrl_t ctrl, const char *cache_nonce,
} }
if (keyref) if (keyref)
agent_write_shadow_key (ctrl->keygrip, serialno, keyref, pkbuf, 0); {
char *dispserialno;
agent_card_getattr (ctrl, "$DISPSERIALNO", &dispserialno,
hexgrip);
agent_write_shadow_key (ctrl->keygrip, serialno, keyref, pkbuf,
0, dispserialno);
xfree (dispserialno);
}
algo = get_pk_algo_from_key (s_pkey); algo = get_pk_algo_from_key (s_pkey);
xfree (serialno); xfree (serialno);

View File

@ -813,11 +813,11 @@ agent_askpin (ctrl_t ctrl,
/* Replacement for the function in findkey.c. Here we write the key /* Replacement for the function in findkey.c. Here we write the key
* to stdout. */ * to stdout. */
int gpg_error_t
agent_write_private_key (const unsigned char *grip, agent_write_private_key (const unsigned char *grip,
const void *buffer, size_t length, int force, const void *buffer, size_t length, int force,
const char *serialno, const char *keyref, const char *serialno, const char *keyref,
time_t timestamp) const char *dispserialno, time_t timestamp)
{ {
char hexgrip[40+4+1]; char hexgrip[40+4+1];
char *p; char *p;
@ -826,6 +826,7 @@ agent_write_private_key (const unsigned char *grip,
(void)serialno; (void)serialno;
(void)keyref; (void)keyref;
(void)timestamp; (void)timestamp;
(void)dispserialno;
bin2hex (grip, 20, hexgrip); bin2hex (grip, 20, hexgrip);
strcpy (hexgrip+40, ".key"); strcpy (hexgrip+40, ".key");