mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
agent: Put Token lines into the key files.
* agent/findkey.c (write_extended_private_key): Add args serialno and keyref. Write a Token line if that does not yet exist. (agent_write_private_key): Add args serialno and keyref and change all callers. (agent_write_shadow_key): Skip leading spaces. * agent/keyformat.txt: Improve extended key format docs. -- Noet that the extended key forma is the defaqult in 2.3. This patch is a first step to better handle tokens which carray the same key. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
c9fa28bfad
commit
bdf252e76a
@ -414,7 +414,8 @@ void start_command_handler_ssh (ctrl_t, gnupg_fd_t);
|
||||
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);
|
||||
const void *buffer, size_t length, int force,
|
||||
const char *serialno, const char *keyref);
|
||||
gpg_error_t agent_key_from_file (ctrl_t ctrl,
|
||||
const char *cache_nonce,
|
||||
const char *desc_text,
|
||||
|
@ -3142,7 +3142,7 @@ ssh_identity_register (ctrl_t ctrl, ssh_key_type_spec_t *spec,
|
||||
goto out;
|
||||
|
||||
/* Store this key to our key storage. */
|
||||
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);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
@ -2255,10 +2255,11 @@ cmd_import_key (assuan_context_t ctx, char *line)
|
||||
err = agent_protect (key, passphrase, &finalkey, &finalkeylen,
|
||||
ctrl->s2k_count, -1);
|
||||
if (!err)
|
||||
err = agent_write_private_key (grip, finalkey, finalkeylen, force);
|
||||
err = agent_write_private_key (grip, finalkey, finalkeylen, force,
|
||||
NULL, NULL);
|
||||
}
|
||||
else
|
||||
err = agent_write_private_key (grip, key, realkeylen, force);
|
||||
err = agent_write_private_key (grip, key, realkeylen, force, NULL, NULL);
|
||||
|
||||
leave:
|
||||
gcry_sexp_release (openpgp_sexp);
|
||||
|
@ -1067,7 +1067,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);
|
||||
agent_write_private_key (grip, protectedkey, protectedkeylen, 1,
|
||||
NULL, NULL);
|
||||
xfree (protectedkey);
|
||||
}
|
||||
else
|
||||
@ -1076,7 +1077,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);
|
||||
1, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,12 +55,14 @@ 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,
|
||||
const void *buf, size_t len)
|
||||
const void *buf, size_t len,
|
||||
const char *serialno, const char *keyref)
|
||||
{
|
||||
gpg_error_t err;
|
||||
nvc_t pk = NULL;
|
||||
gcry_sexp_t key = NULL;
|
||||
int remove = 0;
|
||||
char *token = NULL;
|
||||
|
||||
if (update)
|
||||
{
|
||||
@ -93,6 +95,37 @@ write_extended_private_key (char *fname, estream_t fp, int update,
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
/* If requested write a Token line. */
|
||||
if (serialno && keyref)
|
||||
{
|
||||
nve_t item;
|
||||
const char *s;
|
||||
|
||||
token = strconcat (serialno, " ", keyref, NULL);
|
||||
if (!token)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* fixme: the strcmp should compare only the first two strings. */
|
||||
for (item = nvc_lookup (pk, "Token:");
|
||||
item;
|
||||
item = nve_next_value (item, "Token:"))
|
||||
if ((s = nve_value (item)) && !strcmp (s, token))
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
err = es_fseek (fp, 0, SEEK_SET);
|
||||
if (err)
|
||||
goto leave;
|
||||
@ -132,15 +165,18 @@ write_extended_private_key (char *fname, estream_t fp, int update,
|
||||
xfree (fname);
|
||||
gcry_sexp_release (key);
|
||||
nvc_release (pk);
|
||||
xfree (token);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
* passed as true an existing key with the given GRIP will get
|
||||
* overwritten. If SERIALNO and KEYREF are give an a Token line is added to
|
||||
* th key if the extended format ist used. */
|
||||
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,
|
||||
const char *serialno, const char *keyref)
|
||||
{
|
||||
char *fname;
|
||||
estream_t fp;
|
||||
@ -208,17 +244,20 @@ agent_write_private_key (const unsigned char *grip,
|
||||
if (first != '(')
|
||||
{
|
||||
/* Key is already in the extended format. */
|
||||
return write_extended_private_key (fname, fp, 1, buffer, length);
|
||||
return write_extended_private_key (fname, fp, 1, buffer, length,
|
||||
serialno, keyref);
|
||||
}
|
||||
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, buffer, length);
|
||||
return write_extended_private_key (fname, fp, 0, buffer, length,
|
||||
serialno, keyref);
|
||||
}
|
||||
}
|
||||
|
||||
if (opt.enable_extended_key_format)
|
||||
return write_extended_private_key (fname, fp, 0, buffer, length);
|
||||
return write_extended_private_key (fname, fp, 0, buffer, length,
|
||||
serialno, keyref);
|
||||
|
||||
if (es_fwrite (buffer, length, 1, fp) != 1)
|
||||
{
|
||||
@ -1580,6 +1619,13 @@ agent_write_shadow_key (const unsigned char *grip,
|
||||
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 ();
|
||||
@ -1593,7 +1639,7 @@ 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);
|
||||
err = agent_write_private_key (grip, shdkey, len, force, serialno, keyid);
|
||||
xfree (shdkey);
|
||||
if (err)
|
||||
log_error ("error writing key: %s\n", gpg_strerror (err));
|
||||
|
@ -68,7 +68,7 @@ store_key (gcry_sexp_t private, const char *passphrase, int force,
|
||||
buf = p;
|
||||
}
|
||||
|
||||
rc = agent_write_private_key (grip, buf, len, force);
|
||||
rc = agent_write_private_key (grip, buf, len, force, NULL, NULL);
|
||||
xfree (buf);
|
||||
return rc;
|
||||
}
|
||||
|
@ -18,7 +18,8 @@ hexadecimal representation of the keygrip[2] and suffixed with ".key".
|
||||
|
||||
* Extended Private Key Format
|
||||
|
||||
GnuPG 2.3+ will use a new format to store private keys that is both
|
||||
** Overview
|
||||
GnuPG 2.3+ uses a new format to store private keys that is both
|
||||
more flexible and easier to read and edit by human beings. The new
|
||||
format stores name,value-pairs using the common mail and http header
|
||||
convention. Example (here indented with two spaces):
|
||||
@ -28,6 +29,8 @@ convention. Example (here indented with two spaces):
|
||||
Use-for-ssh: yes
|
||||
OpenSSH-cert: long base64 encoded string wrapped so that this
|
||||
key file can be easily edited with a standard editor.
|
||||
Token: D2760001240102000005000011730000 OPENPGP.1
|
||||
Token: FF020001008A77C1 PIV.9C
|
||||
Key: (shadowed-private-key
|
||||
(rsa
|
||||
(n #00AA1AD2A55FD8C8FDE9E1941772D9CC903FA43B268CB1B5A1BAFDC900
|
||||
@ -52,33 +55,66 @@ Keys in the extended format can be recognized by looking at the first
|
||||
byte of the file. If it starts with a '(' it is a naked S-expression,
|
||||
otherwise it is a key in extended format.
|
||||
|
||||
** Names
|
||||
|
||||
*** Names
|
||||
A name must start with a letter and end with a colon. Valid
|
||||
characters are all ASCII letters, numbers and the hyphen. Comparison
|
||||
of names is done case insensitively. Names may be used several times
|
||||
to represent an array of values.
|
||||
|
||||
The name "Key:" is special in that it may occur only once and the
|
||||
associated value holds the actual S-expression with the cryptographic
|
||||
key. The S-expression is formatted using the 'Advanced Format'
|
||||
(GCRYSEXP_FMT_ADVANCED) that avoids non-printable characters so that
|
||||
the file can be easily inspected and edited. See section 'Private Key
|
||||
Format' below for details.
|
||||
|
||||
** Values
|
||||
to represent an array of values. Note that the name "Key" is special
|
||||
in that it is madandory must occur only once.
|
||||
|
||||
*** Values
|
||||
Values are UTF-8 encoded strings. Values can be wrapped at any point,
|
||||
and continued in the next line indicated by leading whitespace. A
|
||||
continuation line with one leading space does not introduce a blank so
|
||||
that the lines can be effectively concatenated. A blank line as part
|
||||
of a continuation line encodes a newline.
|
||||
|
||||
** Comments
|
||||
|
||||
*** Comments
|
||||
Lines containing only whitespace, and lines starting with whitespace
|
||||
followed by '#' are considered to be comments and are ignored.
|
||||
|
||||
** Well defined names
|
||||
|
||||
*** Description
|
||||
This is a human readable string describing the key.
|
||||
|
||||
*** Key
|
||||
The name "Key" is special in that it is mandatory and must occur only
|
||||
once. The associated value holds the actual S-expression with the
|
||||
cryptographic key. The S-expression is formatted using the 'Advanced
|
||||
Format' (GCRYSEXP_FMT_ADVANCED) that avoids non-printable characters
|
||||
so that the file can be easily inspected and edited. See section
|
||||
'Private Key Format' below for details.
|
||||
|
||||
*** Label
|
||||
This is a short human readable description for the key which can be
|
||||
used by the software to describe the key in a user interface. For
|
||||
example as part of the description in a prompt for a PIN or
|
||||
passphrase. It is often used instead of a comment element preent in
|
||||
the S-expression of the "Key" item.
|
||||
|
||||
*** OpenSSH-cert
|
||||
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 the
|
||||
same as with 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.
|
||||
|
||||
*** 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
|
||||
putting the keygrip into the 'sshcontrol' file. Only one such item
|
||||
should exist.
|
||||
|
||||
* Private Key Format
|
||||
** Unprotected Private Key Format
|
||||
|
||||
|
@ -799,12 +799,15 @@ agent_askpin (ctrl_t ctrl,
|
||||
* to stdout. */
|
||||
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,
|
||||
const char *serialno, const char *keyref)
|
||||
{
|
||||
char hexgrip[40+4+1];
|
||||
char *p;
|
||||
|
||||
(void)force;
|
||||
(void)serialno;
|
||||
(void)keyref;
|
||||
|
||||
bin2hex (grip, 20, hexgrip);
|
||||
strcpy (hexgrip+40, ".key");
|
||||
|
@ -1667,7 +1667,8 @@ agent_get_shadow_info (const unsigned char *shadowkey,
|
||||
R_HEXSN and the Id string as a malloced string at R_IDSTR. On
|
||||
error an error code is returned and NULL is stored at the result
|
||||
parameters addresses. If the serial number or the ID string is not
|
||||
required, NULL may be passed for them. */
|
||||
required, NULL may be passed for them. Note that R_PINLEN is
|
||||
currently not used by any caller. */
|
||||
gpg_error_t
|
||||
parse_shadow_info (const unsigned char *shadow_info,
|
||||
char **r_hexsn, char **r_idstr, int *r_pinlen)
|
||||
|
Loading…
x
Reference in New Issue
Block a user