aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--agent/findkey.c103
-rw-r--r--agent/keyformat.txt4
2 files changed, 82 insertions, 25 deletions
diff --git a/agent/findkey.c b/agent/findkey.c
index 157870e17..5699a215e 100644
--- a/agent/findkey.c
+++ b/agent/findkey.c
@@ -1,7 +1,7 @@
/* findkey.c - Locate the secret key
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007,
* 2010, 2011 Free Software Foundation, Inc.
- * Copyright (C) 2014 Werner Koch
+ * Copyright (C) 2014, 2019 Werner Koch
*
* This file is part of GnuPG.
*
@@ -52,6 +52,36 @@ struct try_unprotect_arg_s
};
+/* Repalce 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;
+}
+
+
/* 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,
@@ -734,10 +764,13 @@ 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 and
+ * R_KEYMETA. */
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;
@@ -750,6 +783,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");
@@ -788,7 +823,7 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result)
if (first != '(')
{
/* Key is in extended format. */
- nvc_t pk;
+ nvc_t pk = NULL;
int line;
err = nvc_parse_private_key (&pk, &line, fp);
@@ -800,12 +835,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;
}
@@ -905,6 +945,7 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
unsigned char *buf;
size_t len, buflen, erroff;
gcry_sexp_t s_skey;
+ nvc_t keymeta = NULL;
*result = NULL;
if (shadow_info)
@@ -912,7 +953,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, &keymeta);
if (err)
{
if (gpg_err_code (err) == GPG_ERR_ENOENT)
@@ -925,7 +966,10 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
now. */
err = make_canon_sexp (s_skey, &buf, &len);
if (err)
- return err;
+ {
+ nvc_release (keymeta);
+ return err;
+ }
switch (agent_private_key_type (buf))
{
@@ -950,25 +994,35 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
case PRIVATE_KEY_PROTECTED:
{
char *desc_text_final;
- char *comment = NULL;
+ char *comment_buffer = NULL;
+ const char *comment = NULL;
/* Note, that we will take the comment as a C string for
- display purposes; i.e. all stuff beyond a Nul character is
- ignored. */
- {
- gcry_sexp_t comment_sexp;
+ * display purposes; i.e. all stuff beyond a Nul character is
+ * ignored. If a "Label" entry is available in the meta data
+ * this is used instead of the s-ecpression comment. */
+ if (keymeta && (comment = nvc_get_string (keymeta, "Label:")))
+ {
+ if (strchr (comment, '\n')
+ && (comment_buffer = linefeed_to_percent0A (comment)))
+ comment = comment_buffer;
+ }
+ else
+ {
+ gcry_sexp_t comment_sexp;
- comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
- if (comment_sexp)
- comment = gcry_sexp_nth_string (comment_sexp, 1);
- gcry_sexp_release (comment_sexp);
- }
+ comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
+ if (comment_sexp)
+ comment_buffer = gcry_sexp_nth_string (comment_sexp, 1);
+ gcry_sexp_release (comment_sexp);
+ comment = comment_buffer;
+ }
desc_text_final = NULL;
if (desc_text)
err = agent_modify_description (desc_text, comment, s_skey,
&desc_text_final);
- gcry_free (comment);
+ gcry_free (comment_buffer);
if (!err)
{
@@ -1023,6 +1077,7 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
xfree (*r_passphrase);
*r_passphrase = NULL;
}
+ nvc_release (keymeta);
return err;
}
@@ -1039,10 +1094,12 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
xfree (*r_passphrase);
*r_passphrase = NULL;
}
+ nvc_release (keymeta);
return err;
}
*result = s_skey;
+ nvc_release (keymeta);
return 0;
}
@@ -1242,7 +1299,7 @@ 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;
@@ -1280,7 +1337,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;
@@ -1425,7 +1482,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)
@@ -1509,7 +1566,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)
diff --git a/agent/keyformat.txt b/agent/keyformat.txt
index 058fb0143..e2ca05c84 100644
--- a/agent/keyformat.txt
+++ b/agent/keyformat.txt
@@ -90,8 +90,8 @@ so that the file can be easily inspected and edited. See section
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.
+passphrase. It is often used instead of a comment element as present
+in the S-expression of the "Key" item.
*** OpenSSH-cert
This takes a base64 encoded string wrapped so that this