mirror of
git://git.gnupg.org/gnupg.git
synced 2025-02-01 16:33:02 +01:00
agent: Create and use Token entries to track the display s/n.
* agent/divert-scd.c (linefeed_to_percent0A): New. (ask_for_card): Add arg grip. Read Token and Label items and use them. (divert_pksign, divert_pkdecrypt): Pass down grip. * agent/findkey.c (write_extended_private_key): Add args serialno, keyref, and dispserialno. Writen Token item. (agent_write_private_key): Add args serialno, keyref, and dispserialno. (read_key_file): Add arg r_keymeta. (agent_keymeta_from_file): New. (agent_write_shadow_key): Remove leading spaces from serialno and keyid. * agent/protect-tool.c (agent_write_private_key): Ditto. * agent/learncard.c (agent_handle_learn): Get DISPSERIALNO and pass to agent_write_shadow_key. * agent/command-ssh.c (card_key_available): Ditto. -- GnuPG-bug-id: 6135 This patch backports some changes from master but also adds the Display-S/N tracking.
This commit is contained in:
parent
706adf6691
commit
dc9b242628
@ -36,6 +36,7 @@
|
||||
#include "../common/sysutils.h" /* (gnupg_fd_t) */
|
||||
#include "../common/session-env.h"
|
||||
#include "../common/shareddefs.h"
|
||||
#include "../common/name-value.h"
|
||||
|
||||
/* To convey some special hash algorithms we use algorithm numbers
|
||||
reserved for application use. */
|
||||
@ -429,7 +430,9 @@ gpg_error_t agent_modify_description (const char *in, const char *comment,
|
||||
const gcry_sexp_t key, char **result);
|
||||
int agent_write_private_key (const unsigned char *grip,
|
||||
const void *buffer, size_t length, int force,
|
||||
time_t timestamp);
|
||||
time_t timestamp,
|
||||
const char *serialno, const char *keyref,
|
||||
const char *dispserialno);
|
||||
gpg_error_t agent_key_from_file (ctrl_t ctrl,
|
||||
const char *cache_nonce,
|
||||
const char *desc_text,
|
||||
@ -441,6 +444,8 @@ gpg_error_t agent_key_from_file (ctrl_t ctrl,
|
||||
char **r_passphrase);
|
||||
gpg_error_t agent_raw_key_from_file (ctrl_t ctrl, const unsigned char *grip,
|
||||
gcry_sexp_t *result);
|
||||
gpg_error_t agent_keymeta_from_file (ctrl_t ctrl, const unsigned char *grip,
|
||||
nvc_t *r_keymeta);
|
||||
gpg_error_t agent_public_key_from_file (ctrl_t ctrl,
|
||||
const unsigned char *grip,
|
||||
gcry_sexp_t *result);
|
||||
@ -549,7 +554,8 @@ gpg_error_t s2k_hash_passphrase (const char *passphrase, int hashalgo,
|
||||
unsigned char *key, size_t keylen);
|
||||
gpg_error_t agent_write_shadow_key (const unsigned char *grip,
|
||||
const char *serialno, const char *keyid,
|
||||
const unsigned char *pkbuf, int force);
|
||||
const unsigned char *pkbuf, int force,
|
||||
const char *dispserialno);
|
||||
|
||||
|
||||
/*-- trustlist.c --*/
|
||||
|
@ -2495,8 +2495,13 @@ card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn)
|
||||
|
||||
if ( agent_key_available (grip) )
|
||||
{
|
||||
char *dispserialno;
|
||||
|
||||
/* (Shadow)-key is not available in our key storage. */
|
||||
err = agent_write_shadow_key (grip, serialno, authkeyid, pkbuf, 0);
|
||||
agent_card_getattr (ctrl, "$DISPSERIALNO", &dispserialno);
|
||||
err = agent_write_shadow_key (grip, serialno, authkeyid, pkbuf, 0,
|
||||
dispserialno);
|
||||
xfree (dispserialno);
|
||||
if (err)
|
||||
{
|
||||
xfree (pkbuf);
|
||||
@ -3154,7 +3159,8 @@ 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
|
||||
* timestamp because we simply do not know. */
|
||||
err = agent_write_private_key (key_grip_raw, buffer, buffer_n, 0, 0);
|
||||
err = agent_write_private_key (key_grip_raw, buffer, buffer_n, 0, 0,
|
||||
NULL, NULL, NULL);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
@ -1040,7 +1040,12 @@ cmd_readkey (assuan_context_t ctx, char *line)
|
||||
if (agent_key_available (grip))
|
||||
{
|
||||
/* (Shadow)-key is not available in our key storage. */
|
||||
rc = agent_write_shadow_key (grip, serialno, keyid, pkbuf, 0);
|
||||
char *dispserialno;
|
||||
|
||||
agent_card_getattr (ctrl, "$DISPSERIALNO", &dispserialno);
|
||||
rc = agent_write_shadow_key (grip, serialno, keyid, pkbuf, 0,
|
||||
dispserialno);
|
||||
xfree (dispserialno);
|
||||
if (rc)
|
||||
goto leave;
|
||||
}
|
||||
@ -2425,11 +2430,11 @@ cmd_import_key (assuan_context_t ctx, char *line)
|
||||
ctrl->s2k_count, -1);
|
||||
if (!err)
|
||||
err = agent_write_private_key (grip, finalkey, finalkeylen, force,
|
||||
opt_timestamp);
|
||||
opt_timestamp, NULL, NULL, NULL);
|
||||
}
|
||||
else
|
||||
err = agent_write_private_key (grip, key, realkeylen, force,
|
||||
opt_timestamp);
|
||||
opt_timestamp, NULL, NULL, NULL);
|
||||
|
||||
leave:
|
||||
gcry_sexp_release (openpgp_sexp);
|
||||
|
@ -1069,7 +1069,8 @@ convert_from_openpgp_native (ctrl_t ctrl,
|
||||
if (!agent_protect (*r_key, passphrase,
|
||||
&protectedkey, &protectedkeylen,
|
||||
ctrl->s2k_count, -1))
|
||||
agent_write_private_key (grip, protectedkey, protectedkeylen, 1, 0);
|
||||
agent_write_private_key (grip, protectedkey, protectedkeylen,
|
||||
1, 0, NULL, NULL, NULL);
|
||||
xfree (protectedkey);
|
||||
}
|
||||
else
|
||||
@ -1078,7 +1079,7 @@ convert_from_openpgp_native (ctrl_t ctrl,
|
||||
agent_write_private_key (grip,
|
||||
*r_key,
|
||||
gcry_sexp_canon_len (*r_key, 0, NULL,NULL),
|
||||
1, 0);
|
||||
1, 0, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,16 +31,51 @@
|
||||
#include "../common/i18n.h"
|
||||
#include "../common/sexp-parse.h"
|
||||
|
||||
/* Replace all linefeeds in STRING by "%0A" and return a new malloced
|
||||
* string. May return NULL on memory error. */
|
||||
static char *
|
||||
linefeed_to_percent0A (const char *string)
|
||||
{
|
||||
const char *s;
|
||||
size_t n;
|
||||
char *buf, *p;
|
||||
|
||||
for (n=0, s=string; *s; s++)
|
||||
if (*s == '\n')
|
||||
n += 3;
|
||||
else
|
||||
n++;
|
||||
p = buf = xtrymalloc (n+1);
|
||||
if (!buf)
|
||||
return NULL;
|
||||
for (s=string; *s; s++)
|
||||
if (*s == '\n')
|
||||
{
|
||||
memcpy (p, "%0A", 3);
|
||||
p += 3;
|
||||
}
|
||||
else
|
||||
*p++ = *s;
|
||||
*p = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
/* Ask for the card using SHADOW_INFO. If GRIP is not NULL, the
|
||||
* function also tries to find additional information from the shadow
|
||||
* key file. */
|
||||
static int
|
||||
ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info, char **r_kid)
|
||||
ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info,
|
||||
const unsigned char *grip, char **r_kid)
|
||||
{
|
||||
int rc, i;
|
||||
char *serialno;
|
||||
int no_card = 0;
|
||||
char *desc;
|
||||
char *want_sn, *want_kid, *want_sn_disp;
|
||||
int got_sn_disp_from_meta = 0;
|
||||
int len;
|
||||
char *comment = NULL;
|
||||
|
||||
*r_kid = NULL;
|
||||
|
||||
@ -53,11 +88,62 @@ ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info, char **r_kid)
|
||||
rc = gpg_error_from_syserror ();
|
||||
xfree (want_sn);
|
||||
xfree (want_kid);
|
||||
xfree (comment);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (grip)
|
||||
{
|
||||
nvc_t keymeta;
|
||||
const char *s;
|
||||
size_t snlen;
|
||||
nve_t item;
|
||||
char **tokenfields = NULL;
|
||||
|
||||
rc = agent_keymeta_from_file (ctrl, grip, &keymeta);
|
||||
if (!rc)
|
||||
{
|
||||
snlen = strlen (want_sn);
|
||||
s = NULL;
|
||||
for (item = nvc_lookup (keymeta, "Token:");
|
||||
item;
|
||||
item = nve_next_value (item, "Token:"))
|
||||
if ((s = nve_value (item)) && !strncmp (s, want_sn, snlen))
|
||||
break;
|
||||
if (s && (tokenfields = strtokenize (s, " \t\n")))
|
||||
{
|
||||
if (tokenfields[0] && tokenfields[1] && tokenfields[2]
|
||||
&& tokenfields[3] && strlen (tokenfields[3]) > 1)
|
||||
{
|
||||
xfree (want_sn_disp);
|
||||
want_sn_disp = percent_plus_unescape (tokenfields[3], 0xff);
|
||||
if (!want_sn_disp)
|
||||
{
|
||||
rc = gpg_error_from_syserror ();
|
||||
xfree (tokenfields);
|
||||
nvc_release (keymeta);
|
||||
xfree (want_sn);
|
||||
xfree (want_kid);
|
||||
xfree (comment);
|
||||
return rc;
|
||||
}
|
||||
got_sn_disp_from_meta = 1;
|
||||
}
|
||||
|
||||
xfree (tokenfields);
|
||||
}
|
||||
|
||||
if ((s = nvc_get_string (keymeta, "Label:")))
|
||||
comment = linefeed_to_percent0A (s);
|
||||
|
||||
nvc_release (keymeta);
|
||||
}
|
||||
}
|
||||
|
||||
len = strlen (want_sn_disp);
|
||||
if (len == 32 && !strncmp (want_sn_disp, "D27600012401", 12))
|
||||
if (got_sn_disp_from_meta)
|
||||
; /* We got the the display S/N from the key file. */
|
||||
else if (len == 32 && !strncmp (want_sn_disp, "D27600012401", 12))
|
||||
{
|
||||
/* This is an OpenPGP card - reformat */
|
||||
memmove (want_sn_disp, want_sn_disp+16, 4);
|
||||
@ -87,6 +173,7 @@ ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info, char **r_kid)
|
||||
{
|
||||
xfree (want_sn_disp);
|
||||
xfree (want_sn);
|
||||
xfree (comment);
|
||||
*r_kid = want_kid;
|
||||
return 0; /* yes, we have the correct card */
|
||||
}
|
||||
@ -112,12 +199,13 @@ ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info, char **r_kid)
|
||||
{
|
||||
if (asprintf (&desc,
|
||||
"%s:%%0A%%0A"
|
||||
" %s%%0A"
|
||||
" %s",
|
||||
no_card
|
||||
? L_("Please insert the card with serial number")
|
||||
: L_("Please remove the current card and "
|
||||
"insert the one with serial number"),
|
||||
want_sn_disp) < 0)
|
||||
want_sn_disp, comment? comment:"") < 0)
|
||||
{
|
||||
rc = out_of_core ();
|
||||
}
|
||||
@ -136,6 +224,7 @@ ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info, char **r_kid)
|
||||
xfree (want_sn_disp);
|
||||
xfree (want_sn);
|
||||
xfree (want_kid);
|
||||
xfree (comment);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
@ -447,7 +536,7 @@ divert_pksign (ctrl_t ctrl, const char *desc_text,
|
||||
|
||||
(void)desc_text;
|
||||
|
||||
rc = ask_for_card (ctrl, shadow_info, &kid);
|
||||
rc = ask_for_card (ctrl, shadow_info, grip, &kid);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -599,7 +688,7 @@ divert_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
||||
ciphertext = s;
|
||||
ciphertextlen = n;
|
||||
|
||||
rc = ask_for_card (ctrl, shadow_info, &kid);
|
||||
rc = ask_for_card (ctrl, shadow_info, grip, &kid);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
136
agent/findkey.c
136
agent/findkey.c
@ -55,12 +55,16 @@ struct try_unprotect_arg_s
|
||||
/* Note: Ownership of FNAME and FP are moved to this function. */
|
||||
static gpg_error_t
|
||||
write_extended_private_key (char *fname, estream_t fp, int update, int newkey,
|
||||
const void *buf, size_t len, time_t timestamp)
|
||||
const void *buf, size_t len, time_t timestamp,
|
||||
const char *serialno, const char *keyref,
|
||||
const char *dispserialno)
|
||||
{
|
||||
gpg_error_t err;
|
||||
nvc_t pk = NULL;
|
||||
gcry_sexp_t key = NULL;
|
||||
int remove = 0;
|
||||
char *token0 = NULL;
|
||||
char *token = NULL;
|
||||
|
||||
if (update)
|
||||
{
|
||||
@ -106,6 +110,59 @@ write_extended_private_key (char *fname, estream_t fp, int update, int newkey,
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* If requested write a Token line. */
|
||||
if (serialno && keyref)
|
||||
{
|
||||
nve_t item;
|
||||
const char *s;
|
||||
size_t token0len;
|
||||
char *tmpdistsn = NULL;
|
||||
|
||||
if (dispserialno)
|
||||
{
|
||||
tmpdistsn = percent_plus_escape (dispserialno);
|
||||
if (!tmpdistsn)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
token0 = strconcat (serialno, " ", keyref, NULL);
|
||||
if (token0)
|
||||
token = strconcat (token0, " - ", tmpdistsn? tmpdistsn:"-", NULL);
|
||||
xfree (tmpdistsn);
|
||||
if (!token0 || !token)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
|
||||
token0len = strlen (token0);
|
||||
for (item = nvc_lookup (pk, "Token:");
|
||||
item;
|
||||
item = nve_next_value (item, "Token:"))
|
||||
if ((s = nve_value (item)) && !strncmp (s, token0, token0len))
|
||||
break;
|
||||
if (!item)
|
||||
{
|
||||
/* No token or no token with that value exists. Add a new
|
||||
* one so that keys which have been stored on several cards
|
||||
* are well supported. */
|
||||
err = nvc_add (pk, "Token:", token);
|
||||
if (err)
|
||||
goto leave;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Token exists: Update the display s/n. It may have
|
||||
* changed due to changes in a newer software version. */
|
||||
err = nve_set (item, token);
|
||||
if (err)
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
err = es_fseek (fp, 0, SEEK_SET);
|
||||
if (err)
|
||||
goto leave;
|
||||
@ -145,6 +202,8 @@ write_extended_private_key (char *fname, estream_t fp, int update, int newkey,
|
||||
if (remove)
|
||||
gnupg_remove (fname);
|
||||
xfree (fname);
|
||||
xfree (token);
|
||||
xfree (token0);
|
||||
gcry_sexp_release (key);
|
||||
nvc_release (pk);
|
||||
return err;
|
||||
@ -153,11 +212,14 @@ write_extended_private_key (char *fname, estream_t fp, int update, int newkey,
|
||||
/* Write an S-expression formatted key to our key storage. With FORCE
|
||||
* passed as true an existing key with the given GRIP will get
|
||||
* overwritten. If TIMESTAMP is not zero and the key does not yet
|
||||
* exists it will be recorded as creation date. */
|
||||
* exists it will be recorded as creation date. If SERIALNO, KEYREF,
|
||||
* of DISPSERIALNO are not NULL they will be recorded as well. */
|
||||
int
|
||||
agent_write_private_key (const unsigned char *grip,
|
||||
const void *buffer, size_t length,
|
||||
int force, time_t timestamp)
|
||||
int force, time_t timestamp,
|
||||
const char *serialno, const char *keyref,
|
||||
const char *dispserialno)
|
||||
{
|
||||
char *fname;
|
||||
estream_t fp;
|
||||
@ -226,19 +288,22 @@ agent_write_private_key (const unsigned char *grip,
|
||||
{
|
||||
/* Key is already in the extended format. */
|
||||
return write_extended_private_key (fname, fp, 1, 0, buffer, length,
|
||||
timestamp);
|
||||
timestamp, serialno, keyref,
|
||||
dispserialno);
|
||||
}
|
||||
if (first == '(' && opt.enable_extended_key_format)
|
||||
{
|
||||
/* Key is in the old format - but we want the extended format. */
|
||||
return write_extended_private_key (fname, fp, 0, 0, buffer, length,
|
||||
timestamp);
|
||||
timestamp, serialno, keyref,
|
||||
dispserialno);
|
||||
}
|
||||
}
|
||||
|
||||
if (opt.enable_extended_key_format)
|
||||
return write_extended_private_key (fname, fp, 0, 1, buffer, length,
|
||||
timestamp);
|
||||
timestamp, serialno, keyref,
|
||||
dispserialno);
|
||||
|
||||
if (es_fwrite (buffer, length, 1, fp) != 1)
|
||||
{
|
||||
@ -715,10 +780,12 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
|
||||
|
||||
|
||||
/* Read the key identified by GRIP from the private key directory and
|
||||
return it as an gcrypt S-expression object in RESULT. On failure
|
||||
returns an error code and stores NULL at RESULT. */
|
||||
* return it as an gcrypt S-expression object in RESULT. If R_KEYMETA
|
||||
* is not NULl and the extended key format is used, the meta data
|
||||
* items are stored there. However the "Key:" item is removed from
|
||||
* it. On failure returns an error code and stores NULL at RESULT. */
|
||||
static gpg_error_t
|
||||
read_key_file (const unsigned char *grip, gcry_sexp_t *result)
|
||||
read_key_file (const unsigned char *grip, gcry_sexp_t *result, nvc_t *r_keymeta)
|
||||
{
|
||||
gpg_error_t err;
|
||||
char *fname;
|
||||
@ -731,6 +798,8 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result)
|
||||
char first;
|
||||
|
||||
*result = NULL;
|
||||
if (r_keymeta)
|
||||
*r_keymeta = NULL;
|
||||
|
||||
bin2hex (grip, 20, hexgrip);
|
||||
strcpy (hexgrip+40, ".key");
|
||||
@ -781,12 +850,17 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result)
|
||||
else
|
||||
{
|
||||
err = nvc_get_private_key (pk, result);
|
||||
nvc_release (pk);
|
||||
if (err)
|
||||
log_error ("error getting private key from '%s': %s\n",
|
||||
fname, gpg_strerror (err));
|
||||
else
|
||||
nvc_delete_named (pk, "Key:");
|
||||
}
|
||||
|
||||
if (!err && r_keymeta)
|
||||
*r_keymeta = pk;
|
||||
else
|
||||
nvc_release (pk);
|
||||
xfree (fname);
|
||||
return err;
|
||||
}
|
||||
@ -893,7 +967,7 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
|
||||
if (r_passphrase)
|
||||
*r_passphrase = NULL;
|
||||
|
||||
err = read_key_file (grip, &s_skey);
|
||||
err = read_key_file (grip, &s_skey, NULL);
|
||||
if (err)
|
||||
{
|
||||
if (gpg_err_code (err) == GPG_ERR_ENOENT)
|
||||
@ -1223,13 +1297,28 @@ agent_raw_key_from_file (ctrl_t ctrl, const unsigned char *grip,
|
||||
|
||||
*result = NULL;
|
||||
|
||||
err = read_key_file (grip, &s_skey);
|
||||
err = read_key_file (grip, &s_skey, NULL);
|
||||
if (!err)
|
||||
*result = s_skey;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
gpg_error_t
|
||||
agent_keymeta_from_file (ctrl_t ctrl, const unsigned char *grip,
|
||||
nvc_t *r_keymeta)
|
||||
{
|
||||
gpg_error_t err;
|
||||
gcry_sexp_t s_skey;
|
||||
|
||||
(void)ctrl;
|
||||
|
||||
err = read_key_file (grip, &s_skey, r_keymeta);
|
||||
gcry_sexp_release (s_skey);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Return the public key for the keygrip GRIP. The result is stored
|
||||
at RESULT. This function extracts the public key from the private
|
||||
key database. On failure an error code is returned and NULL stored
|
||||
@ -1262,7 +1351,7 @@ agent_public_key_from_file (ctrl_t ctrl,
|
||||
|
||||
*result = NULL;
|
||||
|
||||
err = read_key_file (grip, &s_skey);
|
||||
err = read_key_file (grip, &s_skey, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@ -1409,7 +1498,7 @@ agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip,
|
||||
{
|
||||
gcry_sexp_t sexp;
|
||||
|
||||
err = read_key_file (grip, &sexp);
|
||||
err = read_key_file (grip, &sexp, NULL);
|
||||
if (err)
|
||||
{
|
||||
if (gpg_err_code (err) == GPG_ERR_ENOENT)
|
||||
@ -1493,7 +1582,7 @@ agent_delete_key (ctrl_t ctrl, const char *desc_text,
|
||||
char *default_desc = NULL;
|
||||
int key_type;
|
||||
|
||||
err = read_key_file (grip, &s_skey);
|
||||
err = read_key_file (grip, &s_skey, NULL);
|
||||
if (gpg_err_code (err) == GPG_ERR_ENOENT)
|
||||
err = gpg_error (GPG_ERR_NO_SECKEY);
|
||||
if (err)
|
||||
@ -1592,17 +1681,27 @@ agent_delete_key (ctrl_t ctrl, const char *desc_text,
|
||||
/* Write an S-expression formatted shadow key to our key storage.
|
||||
Shadow key is created by an S-expression public key in PKBUF and
|
||||
card's SERIALNO and the IDSTRING. With FORCE passed as true an
|
||||
existing key with the given GRIP will get overwritten. */
|
||||
existing key with the given GRIP will get overwritten. If
|
||||
DISPSERIALNO is not NULL the human readable s/n will also be
|
||||
recorded in the key file. */
|
||||
gpg_error_t
|
||||
agent_write_shadow_key (const unsigned char *grip,
|
||||
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;
|
||||
unsigned char *shadow_info;
|
||||
unsigned char *shdkey;
|
||||
size_t len;
|
||||
|
||||
/* Just in case some caller did not parse the stuff correctly, skip
|
||||
* leading spaces. */
|
||||
while (spacep (serialno))
|
||||
serialno++;
|
||||
while (spacep (keyid))
|
||||
keyid++;
|
||||
|
||||
shadow_info = make_shadow_info (serialno, keyid);
|
||||
if (!shadow_info)
|
||||
return gpg_error_from_syserror ();
|
||||
@ -1616,7 +1715,8 @@ agent_write_shadow_key (const unsigned char *grip,
|
||||
}
|
||||
|
||||
len = gcry_sexp_canon_len (shdkey, 0, NULL, NULL);
|
||||
err = agent_write_private_key (grip, shdkey, len, force, 0);
|
||||
err = agent_write_private_key (grip, shdkey, len, force, 0,
|
||||
serialno, keyid, dispserialno);
|
||||
xfree (shdkey);
|
||||
if (err)
|
||||
log_error ("error writing key: %s\n", gpg_strerror (err));
|
||||
|
@ -69,7 +69,8 @@ store_key (gcry_sexp_t private, const char *passphrase, int force,
|
||||
buf = p;
|
||||
}
|
||||
|
||||
rc = agent_write_private_key (grip, buf, len, force, timestamp);
|
||||
rc = agent_write_private_key (grip, buf, len, force, timestamp,
|
||||
NULL, NULL, NULL);
|
||||
xfree (buf);
|
||||
return rc;
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ of a continuation line encodes a newline.
|
||||
Lines containing only whitespace, and lines starting with whitespace
|
||||
followed by '#' are considered to be comments and are ignored.
|
||||
|
||||
** Well defined names
|
||||
** Well known names
|
||||
|
||||
*** Description
|
||||
This is a human readable string describing the key.
|
||||
@ -108,6 +108,22 @@ This takes a base64 encoded string wrapped so that this
|
||||
key file can be easily edited with a standard editor. Several of such
|
||||
items can be used.
|
||||
|
||||
*** Token
|
||||
If such an item exists it overrides the info given by the "shadow"
|
||||
parameter in the S-expression. Using this item makes it possible to
|
||||
describe a key which is stored on several tokens and also makes it
|
||||
easy to update this info using a standard editor. The syntax is
|
||||
similar to the "shadow" parameter:
|
||||
|
||||
- Serialnumber of the token.
|
||||
- Key reference from the token in full format (e.g. "OpenPGP.2").
|
||||
- An optional fixed length of the PIN or "-".
|
||||
- The human readable serial number of a card. This is usually what is
|
||||
printed on the actual card. This value is taken directly from the
|
||||
card but when asking to insert a card it is useful to have this
|
||||
value available. GnuPG takes care of creating and possibly updating
|
||||
this entry. This is percent-plus-escaped.
|
||||
|
||||
*** Use-for-ssh
|
||||
If given and the value is "yes" or "1" the key is allowed for use by
|
||||
gpg-agent's ssh-agent implementation. This is thus the same as
|
||||
|
@ -409,7 +409,14 @@ agent_handle_learn (ctrl_t ctrl, int send, void *assuan_context, int force)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
rc = agent_write_shadow_key (grip, serialno, item->id, pubkey, force);
|
||||
{
|
||||
char *dispserialno;
|
||||
|
||||
agent_card_getattr (ctrl, "$DISPSERIALNO", &dispserialno);
|
||||
rc = agent_write_shadow_key (grip, serialno, item->id, pubkey, force,
|
||||
dispserialno);
|
||||
xfree (dispserialno);
|
||||
}
|
||||
xfree (pubkey);
|
||||
if (rc)
|
||||
goto leave;
|
||||
|
@ -810,13 +810,18 @@ agent_askpin (ctrl_t ctrl,
|
||||
int
|
||||
agent_write_private_key (const unsigned char *grip,
|
||||
const void *buffer, size_t length, int force,
|
||||
time_t timestamp)
|
||||
time_t timestamp,
|
||||
const char *serialno, const char *keyref,
|
||||
const char *dispserialno)
|
||||
{
|
||||
char hexgrip[40+4+1];
|
||||
char *p;
|
||||
|
||||
(void)force;
|
||||
(void)timestamp;
|
||||
(void)serialno;
|
||||
(void)keyref;
|
||||
(void)dispserialno;
|
||||
|
||||
bin2hex (grip, 20, hexgrip);
|
||||
strcpy (hexgrip+40, ".key");
|
||||
|
Loading…
x
Reference in New Issue
Block a user