From 649b31c663b8674bc874b4ef283d714a13dc8cfe Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 12 Dec 2012 18:47:21 +0100 Subject: 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. --- agent/protect.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) (limited to 'agent/protect.c') 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. */ -- cgit v1.2.3