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/sysutils.h" /* (gnupg_fd_t) */
|
||||||
#include "../common/session-env.h"
|
#include "../common/session-env.h"
|
||||||
#include "../common/shareddefs.h"
|
#include "../common/shareddefs.h"
|
||||||
|
#include "../common/name-value.h"
|
||||||
|
|
||||||
/* To convey some special hash algorithms we use algorithm numbers
|
/* To convey some special hash algorithms we use algorithm numbers
|
||||||
reserved for application use. */
|
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);
|
const gcry_sexp_t key, char **result);
|
||||||
int agent_write_private_key (const unsigned char *grip,
|
int agent_write_private_key (const unsigned char *grip,
|
||||||
const void *buffer, size_t length, int force,
|
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,
|
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,
|
||||||
@ -441,6 +444,8 @@ gpg_error_t agent_key_from_file (ctrl_t ctrl,
|
|||||||
char **r_passphrase);
|
char **r_passphrase);
|
||||||
gpg_error_t agent_raw_key_from_file (ctrl_t ctrl, const unsigned char *grip,
|
gpg_error_t agent_raw_key_from_file (ctrl_t ctrl, const unsigned char *grip,
|
||||||
gcry_sexp_t *result);
|
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,
|
gpg_error_t agent_public_key_from_file (ctrl_t ctrl,
|
||||||
const unsigned char *grip,
|
const unsigned char *grip,
|
||||||
gcry_sexp_t *result);
|
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);
|
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 --*/
|
||||||
|
@ -2495,8 +2495,13 @@ card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn)
|
|||||||
|
|
||||||
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. */
|
||||||
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)
|
if (err)
|
||||||
{
|
{
|
||||||
xfree (pkbuf);
|
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
|
/* 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, 0);
|
err = agent_write_private_key (key_grip_raw, buffer, buffer_n, 0, 0,
|
||||||
|
NULL, NULL, NULL);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -1040,7 +1040,12 @@ 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;
|
||||||
|
|
||||||
|
agent_card_getattr (ctrl, "$DISPSERIALNO", &dispserialno);
|
||||||
|
rc = agent_write_shadow_key (grip, serialno, keyid, pkbuf, 0,
|
||||||
|
dispserialno);
|
||||||
|
xfree (dispserialno);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
@ -2425,11 +2430,11 @@ cmd_import_key (assuan_context_t ctx, char *line)
|
|||||||
ctrl->s2k_count, -1);
|
ctrl->s2k_count, -1);
|
||||||
if (!err)
|
if (!err)
|
||||||
err = agent_write_private_key (grip, finalkey, finalkeylen, force,
|
err = agent_write_private_key (grip, finalkey, finalkeylen, force,
|
||||||
opt_timestamp);
|
opt_timestamp, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
err = agent_write_private_key (grip, key, realkeylen, force,
|
err = agent_write_private_key (grip, key, realkeylen, force,
|
||||||
opt_timestamp);
|
opt_timestamp, NULL, NULL, NULL);
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
gcry_sexp_release (openpgp_sexp);
|
gcry_sexp_release (openpgp_sexp);
|
||||||
|
@ -1069,7 +1069,8 @@ convert_from_openpgp_native (ctrl_t ctrl,
|
|||||||
if (!agent_protect (*r_key, passphrase,
|
if (!agent_protect (*r_key, passphrase,
|
||||||
&protectedkey, &protectedkeylen,
|
&protectedkey, &protectedkeylen,
|
||||||
ctrl->s2k_count, -1))
|
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);
|
xfree (protectedkey);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1078,7 +1079,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, 0);
|
1, 0, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,16 +31,51 @@
|
|||||||
#include "../common/i18n.h"
|
#include "../common/i18n.h"
|
||||||
#include "../common/sexp-parse.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
|
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;
|
int rc, i;
|
||||||
char *serialno;
|
char *serialno;
|
||||||
int no_card = 0;
|
int no_card = 0;
|
||||||
char *desc;
|
char *desc;
|
||||||
char *want_sn, *want_kid, *want_sn_disp;
|
char *want_sn, *want_kid, *want_sn_disp;
|
||||||
|
int got_sn_disp_from_meta = 0;
|
||||||
int len;
|
int len;
|
||||||
|
char *comment = NULL;
|
||||||
|
|
||||||
*r_kid = 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 ();
|
rc = gpg_error_from_syserror ();
|
||||||
xfree (want_sn);
|
xfree (want_sn);
|
||||||
xfree (want_kid);
|
xfree (want_kid);
|
||||||
|
xfree (comment);
|
||||||
return rc;
|
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);
|
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 */
|
/* This is an OpenPGP card - reformat */
|
||||||
memmove (want_sn_disp, want_sn_disp+16, 4);
|
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_disp);
|
||||||
xfree (want_sn);
|
xfree (want_sn);
|
||||||
|
xfree (comment);
|
||||||
*r_kid = want_kid;
|
*r_kid = want_kid;
|
||||||
return 0; /* yes, we have the correct card */
|
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,
|
if (asprintf (&desc,
|
||||||
"%s:%%0A%%0A"
|
"%s:%%0A%%0A"
|
||||||
|
" %s%%0A"
|
||||||
" %s",
|
" %s",
|
||||||
no_card
|
no_card
|
||||||
? L_("Please insert the card with serial number")
|
? L_("Please insert the card with serial number")
|
||||||
: L_("Please remove the current card and "
|
: L_("Please remove the current card and "
|
||||||
"insert the one with serial number"),
|
"insert the one with serial number"),
|
||||||
want_sn_disp) < 0)
|
want_sn_disp, comment? comment:"") < 0)
|
||||||
{
|
{
|
||||||
rc = out_of_core ();
|
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_disp);
|
||||||
xfree (want_sn);
|
xfree (want_sn);
|
||||||
xfree (want_kid);
|
xfree (want_kid);
|
||||||
|
xfree (comment);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -447,7 +536,7 @@ divert_pksign (ctrl_t ctrl, const char *desc_text,
|
|||||||
|
|
||||||
(void)desc_text;
|
(void)desc_text;
|
||||||
|
|
||||||
rc = ask_for_card (ctrl, shadow_info, &kid);
|
rc = ask_for_card (ctrl, shadow_info, grip, &kid);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -599,7 +688,7 @@ divert_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
|||||||
ciphertext = s;
|
ciphertext = s;
|
||||||
ciphertextlen = n;
|
ciphertextlen = n;
|
||||||
|
|
||||||
rc = ask_for_card (ctrl, shadow_info, &kid);
|
rc = ask_for_card (ctrl, shadow_info, grip, &kid);
|
||||||
if (rc)
|
if (rc)
|
||||||
return 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. */
|
/* Note: Ownership of FNAME and FP are moved to this function. */
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
write_extended_private_key (char *fname, estream_t fp, int update, int newkey,
|
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;
|
gpg_error_t err;
|
||||||
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;
|
||||||
|
|
||||||
if (update)
|
if (update)
|
||||||
{
|
{
|
||||||
@ -106,6 +110,59 @@ write_extended_private_key (char *fname, estream_t fp, int update, int newkey,
|
|||||||
goto leave;
|
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);
|
err = es_fseek (fp, 0, SEEK_SET);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
@ -145,6 +202,8 @@ write_extended_private_key (char *fname, estream_t fp, int update, int newkey,
|
|||||||
if (remove)
|
if (remove)
|
||||||
gnupg_remove (fname);
|
gnupg_remove (fname);
|
||||||
xfree (fname);
|
xfree (fname);
|
||||||
|
xfree (token);
|
||||||
|
xfree (token0);
|
||||||
gcry_sexp_release (key);
|
gcry_sexp_release (key);
|
||||||
nvc_release (pk);
|
nvc_release (pk);
|
||||||
return err;
|
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
|
/* Write an S-expression formatted key to our key storage. With FORCE
|
||||||
* passed as true an existing key with the given GRIP will get
|
* passed as true an existing key with the given GRIP will get
|
||||||
* overwritten. If TIMESTAMP is not zero and the key does not yet
|
* 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
|
int
|
||||||
agent_write_private_key (const unsigned char *grip,
|
agent_write_private_key (const unsigned char *grip,
|
||||||
const void *buffer, size_t length,
|
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;
|
char *fname;
|
||||||
estream_t fp;
|
estream_t fp;
|
||||||
@ -226,19 +288,22 @@ agent_write_private_key (const unsigned char *grip,
|
|||||||
{
|
{
|
||||||
/* Key is already in the extended format. */
|
/* Key is already in the extended format. */
|
||||||
return write_extended_private_key (fname, fp, 1, 0, buffer, length,
|
return write_extended_private_key (fname, fp, 1, 0, buffer, length,
|
||||||
timestamp);
|
timestamp, serialno, keyref,
|
||||||
|
dispserialno);
|
||||||
}
|
}
|
||||||
if (first == '(' && opt.enable_extended_key_format)
|
if (first == '(' && opt.enable_extended_key_format)
|
||||||
{
|
{
|
||||||
/* Key is in the old format - but we want the extended format. */
|
/* Key is in the old format - but we want the extended format. */
|
||||||
return write_extended_private_key (fname, fp, 0, 0, buffer, length,
|
return write_extended_private_key (fname, fp, 0, 0, buffer, length,
|
||||||
timestamp);
|
timestamp, serialno, keyref,
|
||||||
|
dispserialno);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt.enable_extended_key_format)
|
if (opt.enable_extended_key_format)
|
||||||
return write_extended_private_key (fname, fp, 0, 1, buffer, length,
|
return write_extended_private_key (fname, fp, 0, 1, buffer, length,
|
||||||
timestamp);
|
timestamp, serialno, keyref,
|
||||||
|
dispserialno);
|
||||||
|
|
||||||
if (es_fwrite (buffer, length, 1, fp) != 1)
|
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
|
/* Read the key identified by GRIP from the private key directory and
|
||||||
return it as an gcrypt S-expression object in RESULT. On failure
|
* return it as an gcrypt S-expression object in RESULT. If R_KEYMETA
|
||||||
returns an error code and stores NULL at RESULT. */
|
* 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
|
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;
|
gpg_error_t err;
|
||||||
char *fname;
|
char *fname;
|
||||||
@ -731,6 +798,8 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result)
|
|||||||
char first;
|
char first;
|
||||||
|
|
||||||
*result = NULL;
|
*result = NULL;
|
||||||
|
if (r_keymeta)
|
||||||
|
*r_keymeta = NULL;
|
||||||
|
|
||||||
bin2hex (grip, 20, hexgrip);
|
bin2hex (grip, 20, hexgrip);
|
||||||
strcpy (hexgrip+40, ".key");
|
strcpy (hexgrip+40, ".key");
|
||||||
@ -781,12 +850,17 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
err = nvc_get_private_key (pk, result);
|
err = nvc_get_private_key (pk, result);
|
||||||
nvc_release (pk);
|
|
||||||
if (err)
|
if (err)
|
||||||
log_error ("error getting private key from '%s': %s\n",
|
log_error ("error getting private key from '%s': %s\n",
|
||||||
fname, gpg_strerror (err));
|
fname, gpg_strerror (err));
|
||||||
|
else
|
||||||
|
nvc_delete_named (pk, "Key:");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!err && r_keymeta)
|
||||||
|
*r_keymeta = pk;
|
||||||
|
else
|
||||||
|
nvc_release (pk);
|
||||||
xfree (fname);
|
xfree (fname);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -893,7 +967,7 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
|
|||||||
if (r_passphrase)
|
if (r_passphrase)
|
||||||
*r_passphrase = NULL;
|
*r_passphrase = NULL;
|
||||||
|
|
||||||
err = read_key_file (grip, &s_skey);
|
err = read_key_file (grip, &s_skey, NULL);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
if (gpg_err_code (err) == GPG_ERR_ENOENT)
|
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;
|
*result = NULL;
|
||||||
|
|
||||||
err = read_key_file (grip, &s_skey);
|
err = read_key_file (grip, &s_skey, NULL);
|
||||||
if (!err)
|
if (!err)
|
||||||
*result = s_skey;
|
*result = s_skey;
|
||||||
return err;
|
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
|
/* Return the public key for the keygrip GRIP. The result is stored
|
||||||
at RESULT. This function extracts the public key from the private
|
at RESULT. This function extracts the public key from the private
|
||||||
key database. On failure an error code is returned and NULL stored
|
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;
|
*result = NULL;
|
||||||
|
|
||||||
err = read_key_file (grip, &s_skey);
|
err = read_key_file (grip, &s_skey, NULL);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -1409,7 +1498,7 @@ agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip,
|
|||||||
{
|
{
|
||||||
gcry_sexp_t sexp;
|
gcry_sexp_t sexp;
|
||||||
|
|
||||||
err = read_key_file (grip, &sexp);
|
err = read_key_file (grip, &sexp, NULL);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
if (gpg_err_code (err) == GPG_ERR_ENOENT)
|
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;
|
char *default_desc = NULL;
|
||||||
int key_type;
|
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)
|
if (gpg_err_code (err) == GPG_ERR_ENOENT)
|
||||||
err = gpg_error (GPG_ERR_NO_SECKEY);
|
err = gpg_error (GPG_ERR_NO_SECKEY);
|
||||||
if (err)
|
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.
|
/* Write an S-expression formatted shadow key to our key storage.
|
||||||
Shadow key is created by an S-expression public key in PKBUF and
|
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
|
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
|
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;
|
||||||
unsigned char *shdkey;
|
unsigned char *shdkey;
|
||||||
size_t len;
|
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);
|
shadow_info = make_shadow_info (serialno, keyid);
|
||||||
if (!shadow_info)
|
if (!shadow_info)
|
||||||
return gpg_error_from_syserror ();
|
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);
|
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);
|
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));
|
||||||
|
@ -69,7 +69,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, timestamp);
|
rc = agent_write_private_key (grip, buf, len, force, timestamp,
|
||||||
|
NULL, NULL, NULL);
|
||||||
xfree (buf);
|
xfree (buf);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ of a continuation line encodes a newline.
|
|||||||
Lines containing only whitespace, and lines starting with whitespace
|
Lines containing only whitespace, and lines starting with whitespace
|
||||||
followed by '#' are considered to be comments and are ignored.
|
followed by '#' are considered to be comments and are ignored.
|
||||||
|
|
||||||
** Well defined names
|
** Well known names
|
||||||
|
|
||||||
*** Description
|
*** Description
|
||||||
This is a human readable string describing the key.
|
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
|
key file can be easily edited with a standard editor. Several of such
|
||||||
items can be used.
|
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
|
*** Use-for-ssh
|
||||||
If given and the value is "yes" or "1" the key is allowed for use by
|
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
|
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;
|
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);
|
xfree (pubkey);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
@ -810,13 +810,18 @@ agent_askpin (ctrl_t ctrl,
|
|||||||
int
|
int
|
||||||
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,
|
||||||
time_t timestamp)
|
time_t timestamp,
|
||||||
|
const char *serialno, const char *keyref,
|
||||||
|
const char *dispserialno)
|
||||||
{
|
{
|
||||||
char hexgrip[40+4+1];
|
char hexgrip[40+4+1];
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
(void)force;
|
(void)force;
|
||||||
(void)timestamp;
|
(void)timestamp;
|
||||||
|
(void)serialno;
|
||||||
|
(void)keyref;
|
||||||
|
(void)dispserialno;
|
||||||
|
|
||||||
bin2hex (grip, 20, hexgrip);
|
bin2hex (grip, 20, hexgrip);
|
||||||
strcpy (hexgrip+40, ".key");
|
strcpy (hexgrip+40, ".key");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user