diff options
author | Werner Koch <[email protected]> | 2012-12-12 17:47:21 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2012-12-12 17:47:21 +0000 |
commit | 649b31c663b8674bc874b4ef283d714a13dc8cfe (patch) | |
tree | 54c390283b48af81c4941dccfd5b3a67bd290ec5 /agent/protect.c | |
parent | ssh: Rewrite a function for better maintainability (diff) | |
download | gnupg-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.c | 34 |
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. */ |