aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Schneider <asn@cryptomilk.org>2011-12-28 18:21:47 +0100
committerAndreas Schneider <asn@cryptomilk.org>2012-02-04 18:37:04 +0100
commitf35c284761359b4b71c0f8228126fa920430ad66 (patch)
treedaf2aa48e326644b673352045effdd14d9369c7e
parentfa37965ab08ce66875be15f340e54f4c283075d9 (diff)
downloadlibssh-f35c284761359b4b71c0f8228126fa920430ad66.tar.gz
libssh-f35c284761359b4b71c0f8228126fa920430ad66.tar.xz
libssh-f35c284761359b4b71c0f8228126fa920430ad66.zip
pki: Add support to import ecdsa pubkeys.
-rw-r--r--include/libssh/pki_priv.h3
-rw-r--r--src/pki.c39
-rw-r--r--src/pki_crypto.c52
3 files changed, 93 insertions, 1 deletions
diff --git a/include/libssh/pki_priv.h b/include/libssh/pki_priv.h
index 7f85b87..7963984 100644
--- a/include/libssh/pki_priv.h
+++ b/include/libssh/pki_priv.h
@@ -34,6 +34,8 @@
void _ssh_pki_log(const char *function,
const char *format, ...) PRINTF_ATTRIBUTE(2, 3);
+int pki_key_ecdsa_nid_from_name(const char *name);
+
/* SSH Key Functions */
ssh_key pki_key_dup(const ssh_key key, int demote);
int pki_key_generate_rsa(ssh_key key, int parameter);
@@ -58,6 +60,7 @@ int pki_pubkey_build_dss(ssh_key key,
int pki_pubkey_build_rsa(ssh_key key,
ssh_string e,
ssh_string n);
+int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e);
ssh_string pki_publickey_to_blob(const ssh_key key);
int pki_export_pubkey_rsa1(const ssh_key key,
const char *host,
diff --git a/src/pki.c b/src/pki.c
index 00bca82..0d17050 100644
--- a/src/pki.c
+++ b/src/pki.c
@@ -625,6 +625,35 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
}
break;
case SSH_KEYTYPE_ECDSA:
+#ifdef HAVE_ECC
+ {
+ ssh_string e;
+ ssh_string i;
+ int nid;
+
+ i = buffer_get_ssh_string(buffer);
+ if (i == NULL) {
+ goto fail;
+ }
+ nid = pki_key_ecdsa_nid_from_name(ssh_string_get_char(i));
+ ssh_string_free(i);
+ if (nid == -1) {
+ goto fail;
+ }
+
+
+ e = buffer_get_ssh_string(buffer);
+ if (e == NULL) {
+ goto fail;
+ }
+
+ rc = pki_pubkey_build_ecdsa(key, nid, e);
+
+ ssh_string_burn(e);
+ ssh_string_free(e);
+ }
+ break;
+#endif
case SSH_KEYTYPE_UNKNOWN:
ssh_pki_log("Unknown public key protocol %d", type);
goto fail;
@@ -701,6 +730,7 @@ int ssh_pki_import_pubkey_blob(const ssh_string key_blob,
ssh_buffer buffer;
ssh_string type_s = NULL;
enum ssh_keytypes_e type;
+ int nid;
int rc;
if (key_blob == NULL || pkey == NULL) {
@@ -727,11 +757,18 @@ int ssh_pki_import_pubkey_blob(const ssh_string key_blob,
}
type = ssh_key_type_from_name(ssh_string_get_char(type_s));
- ssh_string_free(type_s);
if (type == SSH_KEYTYPE_UNKNOWN) {
ssh_pki_log("Unknown key type found!");
goto fail;
}
+ if (type == SSH_KEYTYPE_ECDSA) {
+ nid = pki_key_ecdsa_nid_from_name(ssh_string_get_char(type_s));
+ if (nid == -1) {
+ ssh_pki_log("Unknown nid found!");
+ goto fail;
+ }
+ }
+ ssh_string_free(type_s);
rc = pki_import_pubkey_buffer(buffer, type, pkey);
diff --git a/src/pki_crypto.c b/src/pki_crypto.c
index 4f6db1c..6c5f104 100644
--- a/src/pki_crypto.c
+++ b/src/pki_crypto.c
@@ -121,6 +121,19 @@ static const char *pki_key_ecdsa_nid_to_char(int nid)
return "unknown";
}
+int pki_key_ecdsa_nid_from_name(const char *name)
+{
+ if (strcmp(name, "nistp256") == 0) {
+ return NID_X9_62_prime256v1;
+ } else if (strcmp(name, "nistp384") == 0) {
+ return NID_secp384r1;
+ } else if (strcmp(name, "nistp521") == 0) {
+ return NID_secp521r1;
+ }
+
+ return -1;
+}
+
static ssh_string make_ecpoint_string(const EC_GROUP *g,
const EC_POINT *p)
{
@@ -155,6 +168,45 @@ static ssh_string make_ecpoint_string(const EC_GROUP *g,
return s;
}
+
+int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e)
+{
+ EC_POINT *p;
+ const EC_GROUP *g;
+ int ok;
+
+ key->ecdsa_nid = nid;
+ key->type_c = pki_key_ecdsa_nid_to_name(nid);
+
+ key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid);
+ if (key->ecdsa == NULL) {
+ return -1;
+ }
+
+ g = EC_KEY_get0_group(key->ecdsa);
+
+ p = EC_POINT_new(g);
+ if (p == NULL) {
+ return -1;
+ }
+
+ ok = EC_POINT_oct2point(g,
+ p,
+ ssh_string_data(e),
+ ssh_string_len(e),
+ NULL);
+ if (!ok) {
+ EC_POINT_free(p);
+ return -1;
+ }
+
+ ok = EC_KEY_set_public_key(key->ecdsa, p);
+ if (!ok) {
+ EC_POINT_free(p);
+ }
+
+ return 0;
+}
#endif
ssh_key pki_key_dup(const ssh_key key, int demote)