diff options
author | Tobias Brunner <tobias@strongswan.org> | 2013-04-01 19:47:23 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2013-05-07 17:08:31 +0200 |
commit | e07e489d5f4738b9c340b30ab8d83d3d2d59017c (patch) | |
tree | d32896d049a4cf7652d3f38cf25b206e03061d8d | |
parent | dd9e366814475f22bf22ef874cf68f8691e19c81 (diff) | |
download | strongswan-e07e489d5f4738b9c340b30ab8d83d3d2d59017c.tar.bz2 strongswan-e07e489d5f4738b9c340b30ab8d83d3d2d59017c.tar.xz |
agent: Use sshkey plugin to parse keys, adds support for ECDSA
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | src/charon-cmd/cmd/cmd_creds.c | 4 | ||||
-rw-r--r-- | src/libstrongswan/plugins/agent/agent_plugin.c | 2 | ||||
-rw-r--r-- | src/libstrongswan/plugins/agent/agent_private_key.c | 120 |
4 files changed, 70 insertions, 58 deletions
diff --git a/configure.in b/configure.in index 49a91647b..dd16633a7 100644 --- a/configure.in +++ b/configure.in @@ -968,7 +968,7 @@ ADD_PLUGIN([pkcs7], [s scepclient pki]) ADD_PLUGIN([pkcs8], [s charon openac scepclient pki scripts manager medsrv attest nm cmd]) ADD_PLUGIN([pgp], [s charon]) ADD_PLUGIN([dnskey], [s charon]) -ADD_PLUGIN([sshkey], [s charon]) +ADD_PLUGIN([sshkey], [s charon nm cmd]) ADD_PLUGIN([ipseckey], [c charon]) ADD_PLUGIN([pem], [s charon openac scepclient pki scripts manager medsrv attest nm cmd]) ADD_PLUGIN([padlock], [s charon]) diff --git a/src/charon-cmd/cmd/cmd_creds.c b/src/charon-cmd/cmd/cmd_creds.c index 178b77d49..31e578995 100644 --- a/src/charon-cmd/cmd/cmd_creds.c +++ b/src/charon-cmd/cmd/cmd_creds.c @@ -148,7 +148,7 @@ static void load_agent(private_cmd_creds_t *this) } privkey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, - KEY_RSA, BUILD_AGENT_SOCKET, agent, BUILD_END); + KEY_ANY, BUILD_AGENT_SOCKET, agent, BUILD_END); if (!privkey) { DBG1(DBG_CFG, "failed to load private key from ssh-agent"); @@ -200,6 +200,8 @@ METHOD(cmd_creds_t, handle, bool, if (this->agent && this->identity) { load_agent(this); + /* only do this once */ + this->agent = FALSE; } return TRUE; } diff --git a/src/libstrongswan/plugins/agent/agent_plugin.c b/src/libstrongswan/plugins/agent/agent_plugin.c index 980a140b9..322ded48c 100644 --- a/src/libstrongswan/plugins/agent/agent_plugin.c +++ b/src/libstrongswan/plugins/agent/agent_plugin.c @@ -42,7 +42,9 @@ METHOD(plugin_t, get_features, int, { static plugin_feature_t f[] = { PLUGIN_REGISTER(PRIVKEY, agent_private_key_open, FALSE), + PLUGIN_PROVIDE(PRIVKEY, KEY_ANY), PLUGIN_PROVIDE(PRIVKEY, KEY_RSA), + PLUGIN_PROVIDE(PRIVKEY, KEY_ECDSA), }; *features = f; return countof(f); diff --git a/src/libstrongswan/plugins/agent/agent_private_key.c b/src/libstrongswan/plugins/agent/agent_private_key.c index 42c78c172..8a3fb150a 100644 --- a/src/libstrongswan/plugins/agent/agent_private_key.c +++ b/src/libstrongswan/plugins/agent/agent_private_key.c @@ -49,11 +49,16 @@ struct private_agent_private_key_t { int socket; /** - * key identity blob in ssh format + * public key encoded in SSH format */ chunk_t key; /** + * public key + */ + public_key_t *pubkey; + + /** * keysize in bytes */ size_t key_size; @@ -163,7 +168,7 @@ static bool read_key(private_agent_private_key_t *this, public_key_t *pubkey) { int len; char buf[2048]; - chunk_t blob, key, type, n; + chunk_t blob, key; len = htonl(1); buf[0] = SSH_AGENT_ID_REQUEST; @@ -193,34 +198,40 @@ static bool read_key(private_agent_private_key_t *this, public_key_t *pubkey) { break; } - this->key = key; - type = read_string(&key); - if (!type.len || !strneq("ssh-rsa", type.ptr, type.len)) - { - break; - } - read_string(&key); - n = read_string(&key); - if (n.len <= 512/8) + this->pubkey = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY, + BUILD_BLOB_SSHKEY, key, BUILD_END); + if (!this->pubkey) { - break;; + continue; } if (pubkey && !private_key_belongs_to(&this->public.key, pubkey)) { + this->pubkey->destroy(this->pubkey); + this->pubkey = NULL; continue; } - this->key_size = n.len; - if (n.ptr[0] == 0) - { - this->key_size--; - } - this->key = chunk_clone(this->key); + this->key = chunk_clone(key); return TRUE; } - this->key = chunk_empty; return FALSE; } +static bool scheme_supported(private_agent_private_key_t *this, + signature_scheme_t scheme) +{ + switch (this->pubkey->get_type(this->pubkey)) + { + case KEY_RSA: + return scheme == SIGN_RSA_EMSA_PKCS1_SHA1; + case KEY_ECDSA: + return scheme == SIGN_ECDSA_256 || + scheme == SIGN_ECDSA_384 || + scheme == SIGN_ECDSA_521; + default: + return FALSE; + } +} + METHOD(private_key_t, sign, bool, private_agent_private_key_t *this, signature_scheme_t scheme, chunk_t data, chunk_t *signature) @@ -229,7 +240,7 @@ METHOD(private_key_t, sign, bool, char buf[2048]; chunk_t blob; - if (scheme != SIGN_RSA_EMSA_PKCS1_SHA1) + if (!scheme_supported(this, scheme)) { DBG1(DBG_LIB, "signature scheme %N not supported by ssh-agent", signature_scheme_names, scheme); @@ -279,23 +290,40 @@ METHOD(private_key_t, sign, bool, } /* parse length */ blob = read_string(&blob); - /* skip sig type */ - read_string(&blob); - /* parse length */ - blob = read_string(&blob); - if (!blob.len) - { - DBG1(DBG_LIB, "received invalid ssh-agent signature response"); - return FALSE; + /* check sig type */ + if (chunk_equals(read_string(&blob), chunk_from_str("ssh-rsa"))) + { /* for RSA the signature has no special encoding */ + blob = read_string(&blob); + if (blob.len) + { + *signature = chunk_clone(blob); + return TRUE; + } + } + else + { /* anything else is treated as ECSDA for now */ + blob = read_string(&blob); + if (blob.len) + { + chunk_t r, s; + + r = read_string(&blob); + s = read_string(&blob); + if (r.len && s.len) + { + *signature = chunk_cat("cc", r, s); + return TRUE; + } + } } - *signature = chunk_clone(blob); - return TRUE; + DBG1(DBG_LIB, "received invalid ssh-agent signature response"); + return FALSE; } METHOD(private_key_t, get_type, key_type_t, private_agent_private_key_t *this) { - return KEY_RSA; + return this->pubkey->get_type(this->pubkey); } METHOD(private_key_t, decrypt, bool, @@ -309,21 +337,13 @@ METHOD(private_key_t, decrypt, bool, METHOD(private_key_t, get_keysize, int, private_agent_private_key_t *this) { - return this->key_size * 8; + return this->pubkey->get_keysize(this->pubkey); } METHOD(private_key_t, get_public_key, public_key_t*, private_agent_private_key_t *this) { - chunk_t key, n, e; - - key = this->key; - read_string(&key); - e = read_string(&key); - n = read_string(&key); - - return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, - BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, BUILD_END); + return this->pubkey->get_ref(this->pubkey); } METHOD(private_key_t, get_encoding, bool, @@ -336,19 +356,7 @@ METHOD(private_key_t, get_encoding, bool, METHOD(private_key_t, get_fingerprint, bool, private_agent_private_key_t *this, cred_encoding_type_t type, chunk_t *fp) { - chunk_t n, e, key; - - if (lib->encoding->get_cache(lib->encoding, type, this, fp)) - { - return TRUE; - } - key = this->key; - read_string(&key); - e = read_string(&key); - n = read_string(&key); - - return lib->encoding->encode(lib->encoding, type, this, fp, - CRED_PART_RSA_MODULUS, n, CRED_PART_RSA_PUB_EXP, e, CRED_PART_END); + return this->pubkey->get_fingerprint(this->pubkey, type, fp); } METHOD(private_key_t, get_ref, private_key_t*, @@ -364,8 +372,8 @@ METHOD(private_key_t, destroy, void, if (ref_put(&this->ref)) { close(this->socket); - free(this->key.ptr); - lib->encoding->clear_cache(lib->encoding, this); + chunk_free(&this->key); + DESTROY_IF(this->pubkey); free(this); } } |