summaryrefslogtreecommitdiffstats
path: root/agent
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2019-05-03 15:54:54 +0200
committerWerner Koch <wk@gnupg.org>2019-05-03 15:54:54 +0200
commitbdf252e76ada0056bec2ee7940255f32552328c5 (patch)
treecb239466bff0ed49319cb223058af18b6bb88466 /agent
parentcommon: In private key mode write "Key:" always last in name-value. (diff)
downloadgnupg2-bdf252e76ada0056bec2ee7940255f32552328c5.tar.xz
gnupg2-bdf252e76ada0056bec2ee7940255f32552328c5.zip
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>
Diffstat (limited to 'agent')
-rw-r--r--agent/agent.h3
-rw-r--r--agent/command-ssh.c2
-rw-r--r--agent/command.c5
-rw-r--r--agent/cvt-openpgp.c5
-rw-r--r--agent/findkey.c62
-rw-r--r--agent/genkey.c2
-rw-r--r--agent/keyformat.txt66
-rw-r--r--agent/protect-tool.c5
-rw-r--r--agent/protect.c3
9 files changed, 121 insertions, 32 deletions
diff --git a/agent/agent.h b/agent/agent.h
index 0f804cd8b..b7eacf471 100644
--- a/agent/agent.h
+++ b/agent/agent.h
@@ -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,
diff --git a/agent/command-ssh.c b/agent/command-ssh.c
index ebd28ab5a..727bb9b94 100644
--- a/agent/command-ssh.c
+++ b/agent/command-ssh.c
@@ -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;
diff --git a/agent/command.c b/agent/command.c
index 082ed4144..9bb6fa306 100644
--- a/agent/command.c
+++ b/agent/command.c
@@ -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);
diff --git a/agent/cvt-openpgp.c b/agent/cvt-openpgp.c
index 06cd1c840..42052d48e 100644
--- a/agent/cvt-openpgp.c
+++ b/agent/cvt-openpgp.c
@@ -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);
}
}
diff --git a/agent/findkey.c b/agent/findkey.c
index 89a18fa9e..157870e17 100644
--- a/agent/findkey.c
+++ b/agent/findkey.c
@@ -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));
diff --git a/agent/genkey.c b/agent/genkey.c
index d5c80d0aa..84342f9ea 100644
--- a/agent/genkey.c
+++ b/agent/genkey.c
@@ -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;
}
diff --git a/agent/keyformat.txt b/agent/keyformat.txt
index c7426db9d..058fb0143 100644
--- a/agent/keyformat.txt
+++ b/agent/keyformat.txt
@@ -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
diff --git a/agent/protect-tool.c b/agent/protect-tool.c
index ec7b47695..30d78cd43 100644
--- a/agent/protect-tool.c
+++ b/agent/protect-tool.c
@@ -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");
diff --git a/agent/protect.c b/agent/protect.c
index 61fb8f45d..c7fb773e1 100644
--- a/agent/protect.c
+++ b/agent/protect.c
@@ -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)