mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-02 22:46:30 +02:00
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.
(cherry picked from commit 649b31c663
)
Solved conflicts:
agent/protect.c
agent/t-protect.c
common/ssh-utils.c (different variabale name)
This commit is contained in:
parent
4b4df62eaf
commit
b4cb20cfc3
4 changed files with 389 additions and 109 deletions
|
@ -51,10 +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, 1 },
|
||||
{ "ecdh", "pabgnqd", 6, 6, 1 },
|
||||
{ "ecc", "pabgnqd", 6, 6, 1 },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
@ -401,6 +405,8 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
|
|||
unsigned char **result, size_t *resultlen)
|
||||
{
|
||||
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;
|
||||
|
@ -445,10 +451,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);
|
||||
|
@ -458,7 +467,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)
|
||||
|
@ -467,7 +489,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++;
|
||||
}
|
||||
|
@ -484,7 +506,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. */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue