diff options
author | Andreas Schneider <asn@cryptomilk.org> | 2011-12-28 18:21:47 +0100 |
---|---|---|
committer | Andreas Schneider <asn@cryptomilk.org> | 2012-02-04 18:37:04 +0100 |
commit | f35c284761359b4b71c0f8228126fa920430ad66 (patch) | |
tree | daf2aa48e326644b673352045effdd14d9369c7e | |
parent | fa37965ab08ce66875be15f340e54f4c283075d9 (diff) | |
download | libssh-f35c284761359b4b71c0f8228126fa920430ad66.tar.gz libssh-f35c284761359b4b71c0f8228126fa920430ad66.tar.xz libssh-f35c284761359b4b71c0f8228126fa920430ad66.zip |
pki: Add support to import ecdsa pubkeys.
-rw-r--r-- | include/libssh/pki_priv.h | 3 | ||||
-rw-r--r-- | src/pki.c | 39 | ||||
-rw-r--r-- | src/pki_crypto.c | 52 |
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, @@ -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) |