aboutsummaryrefslogtreecommitdiffstats
path: root/agent/protect.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2012-12-12 17:47:21 +0000
committerWerner Koch <[email protected]>2012-12-12 17:47:21 +0000
commit649b31c663b8674bc874b4ef283d714a13dc8cfe (patch)
tree54c390283b48af81c4941dccfd5b3a67bd290ec5 /agent/protect.c
parentssh: Rewrite a function for better maintainability (diff)
downloadgnupg-649b31c663b8674bc874b4ef283d714a13dc8cfe.tar.gz
gnupg-649b31c663b8674bc874b4ef283d714a13dc8cfe.zip
ssh: Support ECDSA keys.
* agent/command-ssh.c (SPEC_FLAG_IS_ECDSA): New. (struct ssh_key_type_spec): Add fields CURVE_NAME and HASH_ALGO. (ssh_key_types): Add types ecdsa-sha2-nistp{256,384,521}. (ssh_signature_encoder_t): Add arg spec and adjust all callers. (ssh_signature_encoder_ecdsa): New. (sexp_key_construct, sexp_key_extract, ssh_receive_key) (ssh_convert_key_to_blob): Support ecdsa. (ssh_identifier_from_curve_name): New. (ssh_send_key_public): Retrieve and pass the curve_name. (key_secret_to_public): Ditto. (data_sign): Add arg SPEC and change callers to pass it. (ssh_handler_sign_request): Get the hash algo from SPEC. * common/ssh-utils.c (get_fingerprint): Support ecdsa. * agent/protect.c (protect_info): Add flag ECC_HACK. (agent_protect): Allow the use of the "curve" parameter. * agent/t-protect.c (test_agent_protect): Add a test case for ecdsa. * agent/command-ssh.c (ssh_key_grip): Print a better error code. -- The 3 standard curves are now supported in gpg-agent's ssh-agent protocol implementation. I tested this with all 3 curves and keys generated by OpenSSH 5.9p1. Using existing non-ssh generated keys will likely fail for now. To fix this, the code should first undergo some more cleanup; then the fixes are pretty straightforward. And yes, the data structures are way too complicated.
Diffstat (limited to 'agent/protect.c')
-rw-r--r--agent/protect.c34
1 files changed, 26 insertions, 8 deletions
diff --git a/agent/protect.c b/agent/protect.c
index 68e1a049f..d26573d11 100644
--- a/agent/protect.c
+++ b/agent/protect.c
@@ -51,13 +51,14 @@ static struct {
const char *algo;
const char *parmlist;
int prot_from, prot_to;
+ int ecc_hack;
} protect_info[] = {
{ "rsa", "nedpqu", 2, 5 },
{ "dsa", "pqgyx", 4, 4 },
{ "elg", "pgyx", 3, 3 },
- { "ecdsa","pabgnqd", 6, 6 },
- { "ecdh", "pabgnqd", 6, 6 },
- { "ecc", "pabgnqd", 6, 6 },
+ { "ecdsa","pabgnqd", 6, 6, 1 },
+ { "ecdh", "pabgnqd", 6, 6, 1 },
+ { "ecc", "pabgnqd", 6, 6, 1 },
{ NULL }
};
@@ -450,6 +451,8 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
unsigned long s2k_count)
{
int rc;
+ const char *parmlist;
+ int prot_from_idx, prot_to_idx;
const unsigned char *s;
const unsigned char *hash_begin, *hash_end;
const unsigned char *prot_begin, *prot_end, *real_end;
@@ -494,10 +497,13 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
if (!protect_info[infidx].algo)
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
+ parmlist = protect_info[infidx].parmlist;
+ prot_from_idx = protect_info[infidx].prot_from;
+ prot_to_idx = protect_info[infidx].prot_to;
prot_begin = prot_end = NULL;
- for (i=0; (c=protect_info[infidx].parmlist[i]); i++)
+ for (i=0; (c=parmlist[i]); i++)
{
- if (i == protect_info[infidx].prot_from)
+ if (i == prot_from_idx)
prot_begin = s;
if (*s != '(')
return gpg_error (GPG_ERR_INV_SEXP);
@@ -507,7 +513,20 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
if (!n)
return gpg_error (GPG_ERR_INV_SEXP);
if (n != 1 || c != *s)
- return gpg_error (GPG_ERR_INV_SEXP);
+ {
+ if (n == 5 && !memcmp (s, "curve", 5)
+ && !i && protect_info[infidx].ecc_hack)
+ {
+ /* This is a private ECC key but the first parameter is
+ the name of the curve. We change the parameter list
+ here to the one we expect in this case. */
+ parmlist = "?qd";
+ prot_from_idx = 2;
+ prot_to_idx = 2;
+ }
+ else
+ return gpg_error (GPG_ERR_INV_SEXP);
+ }
s += n;
n = snext (&s);
if (!n)
@@ -516,7 +535,7 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
if (*s != ')')
return gpg_error (GPG_ERR_INV_SEXP);
depth--;
- if (i == protect_info[infidx].prot_to)
+ if (i == prot_to_idx)
prot_end = s;
s++;
}
@@ -533,7 +552,6 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
assert (!depth);
real_end = s-1;
-
/* Hash the stuff. Because the timestamp_exp won't get protected,
we can't simply hash a continuous buffer but need to use several
md_writes. */