ports/security/libssh2/files/patch-src_openssl.c
Jung-uk Kim 0b987dd74d Add support for ECDSA key exchange and SHA256 MAC.
Note these patches were cherry-piecked from the following upstream commits:

https://github.com/libssh2/libssh2/commit/bbc43cb
https://github.com/libssh2/libssh2/commit/aba34f5
https://github.com/libssh2/libssh2/commit/62b825c

Submitted by:	Andrew Heybey <ath@heybey.org>
Reviewed by:	sbz (maintainer)
2019-01-31 00:08:46 +00:00

727 lines
18 KiB
C

--- src/openssl.c.orig 2016-10-22 14:16:47 UTC
+++ src/openssl.c
@@ -48,6 +48,24 @@
#define EVP_MAX_BLOCK_LENGTH 32
#endif
+static unsigned char *
+write_bn(unsigned char *buf, const BIGNUM *bn, int bn_bytes)
+{
+ unsigned char *p = buf;
+
+ /* Left space for bn size which will be written below. */
+ p += 4;
+
+ *p = 0;
+ BN_bn2bin(bn, p + 1);
+ if (!(*(p + 1) & 0x80)) {
+ memmove(p, p + 1, --bn_bytes);
+ }
+ _libssh2_htonu32(p - 4, bn_bytes); /* Post write bn size. */
+
+ return p + bn_bytes;
+}
+
int
_libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
const unsigned char *edata,
@@ -230,6 +248,144 @@ _libssh2_dsa_sha1_verify(libssh2_dsa_ctx
}
#endif /* LIBSSH_DSA */
+#if LIBSSH2_ECDSA
+
+/* _libssh2_ecdsa_key_get_curve_type
+ *
+ * returns key curve type that maps to libssh2_curve_type
+ *
+ */
+
+libssh2_curve_type
+_libssh2_ecdsa_key_get_curve_type(_libssh2_ec_key *key)
+{
+ const EC_GROUP *group = EC_KEY_get0_group(key);
+ return EC_GROUP_get_curve_name(group);
+}
+
+/* _libssh2_ecdsa_curve_type_from_name
+ *
+ * returns 0 for success, key curve type that maps to libssh2_curve_type
+ *
+ */
+
+int
+_libssh2_ecdsa_curve_type_from_name(const char *name, libssh2_curve_type *out_type)
+{
+ int ret = 0;
+ libssh2_curve_type type;
+
+ if ( name == NULL || strlen(name) != 19 )
+ return -1;
+
+ if ( strcmp(name, "ecdsa-sha2-nistp256") == 0)
+ type = LIBSSH2_EC_CURVE_NISTP256;
+ else if ( strcmp(name, "ecdsa-sha2-nistp384") == 0)
+ type = LIBSSH2_EC_CURVE_NISTP384;
+ else if ( strcmp(name, "ecdsa-sha2-nistp521") == 0)
+ type = LIBSSH2_EC_CURVE_NISTP521;
+ else {
+ ret = -1;
+ }
+
+ if (ret == 0 && out_type) {
+ *out_type = type;
+ }
+
+ return ret;
+}
+
+/* _libssh2_ecdsa_curve_name_with_octal_new
+ *
+ * Creates a new public key given an octal string, length and type
+ *
+ */
+
+int
+_libssh2_ecdsa_curve_name_with_octal_new(libssh2_ecdsa_ctx ** ec_ctx,
+ const unsigned char *k,
+ size_t k_len, libssh2_curve_type curve)
+{
+
+ int ret = 0;
+ const EC_GROUP *ec_group = NULL;
+ EC_KEY *ec_key = EC_KEY_new_by_curve_name(curve);
+ EC_POINT *point = NULL;
+
+ if ( ec_key ) {
+ ec_group = EC_KEY_get0_group(ec_key);
+ point = EC_POINT_new(ec_group);
+ ret = EC_POINT_oct2point(ec_group, point, k, k_len, NULL);
+ ret = EC_KEY_set_public_key(ec_key, point);
+
+ if (point != NULL)
+ EC_POINT_free(point);
+
+ if ( ec_ctx != NULL )
+ *ec_ctx = ec_key;
+ }
+
+ return (ret == 1) ? 0 : -1;
+}
+
+#define LIBSSH2_ECDSA_VERIFY(digest_type) \
+{ \
+ unsigned char hash[SHA##digest_type##_DIGEST_LENGTH]; \
+ libssh2_sha##digest_type(m, m_len, hash); \
+ ret = ECDSA_do_verify(hash, SHA##digest_type##_DIGEST_LENGTH, \
+ ecdsa_sig, ec_key); \
+ \
+}
+
+int
+_libssh2_ecdsa_verify(libssh2_ecdsa_ctx * ctx,
+ const unsigned char *r, size_t r_len,
+ const unsigned char *s, size_t s_len,
+ const unsigned char *m, size_t m_len)
+{
+ int ret = 0;
+ EC_KEY *ec_key = (EC_KEY*)ctx;
+ libssh2_curve_type type = _libssh2_ecdsa_key_get_curve_type(ec_key);
+
+#if HAVE_OPAQUE_STRUCTS
+ ECDSA_SIG *ecdsa_sig = ECDSA_SIG_new();
+ BIGNUM *pr = BN_new();
+ BIGNUM *ps = BN_new();
+
+ BN_bin2bn(r, r_len, pr);
+ BN_bin2bn(s, s_len, ps);
+ ECDSA_SIG_set0(ecdsa_sig, pr, ps);
+
+#else
+ ECDSA_SIG ecdsa_sig_;
+ ECDSA_SIG *ecdsa_sig = &ecdsa_sig_;
+ ecdsa_sig_.r = BN_new();
+ BN_bin2bn(r, r_len, ecdsa_sig_.r);
+ ecdsa_sig_.s = BN_new();
+ BN_bin2bn(s, s_len, ecdsa_sig_.s);
+#endif
+
+ if ( type == LIBSSH2_EC_CURVE_NISTP256 ) {
+ LIBSSH2_ECDSA_VERIFY(256);
+ }else if ( type == LIBSSH2_EC_CURVE_NISTP384 ) {
+ LIBSSH2_ECDSA_VERIFY(384);
+ }else if ( type == LIBSSH2_EC_CURVE_NISTP521 ) {
+ LIBSSH2_ECDSA_VERIFY(512);
+ }
+
+#if HAVE_OPAQUE_STRUCTS
+ if ( ecdsa_sig )
+ ECDSA_SIG_free(ecdsa_sig);
+#else
+ BN_clear_free(ecdsa_sig_.s);
+ BN_clear_free(ecdsa_sig_.r);
+#endif
+
+ return (ret == 1) ? 0 : -1;
+}
+
+#endif /* LIBSSH2_ECDSA */
+
int
_libssh2_cipher_init(_libssh2_cipher_ctx * h,
_libssh2_cipher_type(algo),
@@ -606,6 +762,41 @@ _libssh2_dsa_new_private(libssh2_dsa_ctx
}
#endif /* LIBSSH_DSA */
+#if LIBSSH2_ECDSA
+
+int
+_libssh2_ecdsa_new_private_frommemory(libssh2_ecdsa_ctx ** ec_ctx,
+ LIBSSH2_SESSION * session,
+ const char *filedata, size_t filedata_len,
+ unsigned const char *passphrase)
+{
+ pem_read_bio_func read_ec =
+ (pem_read_bio_func) &PEM_read_bio_ECPrivateKey;
+ (void) session;
+
+ _libssh2_init_if_needed();
+
+ return read_private_key_from_memory((void **) ec_ctx, read_ec,
+ filedata, filedata_len, passphrase);
+}
+
+int
+_libssh2_ecdsa_new_private(libssh2_ecdsa_ctx ** ec_ctx,
+ LIBSSH2_SESSION * session,
+ const char *filename, unsigned const char *passphrase)
+{
+ pem_read_bio_func read_ec = (pem_read_bio_func) &PEM_read_bio_ECPrivateKey;
+ (void) session;
+
+ _libssh2_init_if_needed ();
+
+ return read_private_key_from_file((void **) ec_ctx, read_ec,
+ filename, passphrase);
+}
+
+#endif /* LIBSSH2_ECDSA */
+
+
int
_libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session,
libssh2_rsa_ctx * rsactx,
@@ -682,6 +873,69 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx *
}
#endif /* LIBSSH_DSA */
+#if LIBSSH2_ECDSA
+
+int
+_libssh2_ecdsa_sign(LIBSSH2_SESSION * session, libssh2_ecdsa_ctx * ec_ctx,
+ const unsigned char *hash, unsigned long hash_len,
+ unsigned char **signature, size_t *signature_len)
+{
+ int r_len, s_len;
+ int rc = 0;
+ size_t out_buffer_len = 0;
+ unsigned char *sp;
+ const BIGNUM *pr = NULL, *ps = NULL;
+ unsigned char *temp_buffer = NULL;
+ unsigned char *out_buffer = NULL;
+
+ ECDSA_SIG *sig = ECDSA_do_sign(hash, hash_len, ec_ctx);
+ if ( sig == NULL )
+ return -1;
+#if HAVE_OPAQUE_STRUCTS
+ ECDSA_SIG_get0(sig, &pr, &ps);
+#else
+ pr = sig->r;
+ ps = sig->s;
+#endif
+
+ r_len = BN_num_bytes(pr) + 1;
+ s_len = BN_num_bytes(ps) + 1;
+
+ temp_buffer = malloc(r_len + s_len + 8);
+ if ( temp_buffer == NULL ) {
+ rc = -1;
+ goto clean_exit;
+ }
+
+ sp = temp_buffer;
+ sp = write_bn(sp, pr, r_len);
+ sp = write_bn(sp, ps, s_len);
+
+ out_buffer_len = (size_t)(sp - temp_buffer);
+
+ out_buffer = LIBSSH2_CALLOC(session, out_buffer_len);
+ if ( out_buffer == NULL ) {
+ rc = -1;
+ goto clean_exit;
+ }
+
+ memcpy(out_buffer, temp_buffer, out_buffer_len);
+
+ *signature = out_buffer;
+ *signature_len = out_buffer_len;
+
+clean_exit:
+
+ if ( temp_buffer != NULL )
+ free(temp_buffer);
+
+ if ( sig )
+ ECDSA_SIG_free(sig);
+
+ return rc;
+}
+#endif /* LIBSSH2_ECDSA */
+
int
_libssh2_sha1_init(libssh2_sha1_ctx *ctx)
{
@@ -787,7 +1041,7 @@ _libssh2_sha256(const unsigned char *mes
}
int
-_libssh2_md5_init(libssh2_md5_ctx *ctx)
+_libssh2_sha384_init(libssh2_sha384_ctx *ctx)
{
#ifdef HAVE_OPAQUE_STRUCTS
*ctx = EVP_MD_CTX_new();
@@ -795,7 +1049,7 @@ _libssh2_md5_init(libssh2_md5_ctx *ctx)
if (*ctx == NULL)
return 0;
- if (EVP_DigestInit(*ctx, EVP_get_digestbyname("md5")))
+ if (EVP_DigestInit(*ctx, EVP_get_digestbyname("sha384")))
return 1;
EVP_MD_CTX_free(*ctx);
@@ -804,26 +1058,112 @@ _libssh2_md5_init(libssh2_md5_ctx *ctx)
return 0;
#else
EVP_MD_CTX_init(ctx);
- return EVP_DigestInit(ctx, EVP_get_digestbyname("md5"));
+ return EVP_DigestInit(ctx, EVP_get_digestbyname("sha384"));
#endif
}
-static unsigned char *
-write_bn(unsigned char *buf, const BIGNUM *bn, int bn_bytes)
+int
+_libssh2_sha384(const unsigned char *message, unsigned long len,
+ unsigned char *out)
{
- unsigned char *p = buf;
+#ifdef HAVE_OPAQUE_STRUCTS
+ EVP_MD_CTX * ctx = EVP_MD_CTX_new();
- /* Left space for bn size which will be written below. */
- p += 4;
+ if (ctx == NULL)
+ return 1; /* error */
- *p = 0;
- BN_bn2bin(bn, p + 1);
- if (!(*(p + 1) & 0x80)) {
- memmove(p, p + 1, --bn_bytes);
+ if(EVP_DigestInit(ctx, EVP_get_digestbyname("sha384"))) {
+ EVP_DigestUpdate(ctx, message, len);
+ EVP_DigestFinal(ctx, out, NULL);
+ EVP_MD_CTX_free(ctx);
+ return 0; /* success */
}
- _libssh2_htonu32(p - 4, bn_bytes); /* Post write bn size. */
+ EVP_MD_CTX_free(ctx);
+#else
+ EVP_MD_CTX ctx;
- return p + bn_bytes;
+ EVP_MD_CTX_init(&ctx);
+ if(EVP_DigestInit(&ctx, EVP_get_digestbyname("sha384"))) {
+ EVP_DigestUpdate(&ctx, message, len);
+ EVP_DigestFinal(&ctx, out, NULL);
+ return 0; /* success */
+ }
+#endif
+ return 1; /* error */
+}
+
+int
+_libssh2_sha512_init(libssh2_sha512_ctx *ctx)
+{
+#ifdef HAVE_OPAQUE_STRUCTS
+ *ctx = EVP_MD_CTX_new();
+
+ if (*ctx == NULL)
+ return 0;
+
+ if (EVP_DigestInit(*ctx, EVP_get_digestbyname("sha512")))
+ return 1;
+
+ EVP_MD_CTX_free(*ctx);
+ *ctx = NULL;
+
+ return 0;
+#else
+ EVP_MD_CTX_init(ctx);
+ return EVP_DigestInit(ctx, EVP_get_digestbyname("sha512"));
+#endif
+}
+
+int
+_libssh2_sha512(const unsigned char *message, unsigned long len,
+ unsigned char *out)
+{
+#ifdef HAVE_OPAQUE_STRUCTS
+ EVP_MD_CTX * ctx = EVP_MD_CTX_new();
+
+ if (ctx == NULL)
+ return 1; /* error */
+
+ if(EVP_DigestInit(ctx, EVP_get_digestbyname("sha512"))) {
+ EVP_DigestUpdate(ctx, message, len);
+ EVP_DigestFinal(ctx, out, NULL);
+ EVP_MD_CTX_free(ctx);
+ return 0; /* success */
+ }
+ EVP_MD_CTX_free(ctx);
+#else
+ EVP_MD_CTX ctx;
+
+ EVP_MD_CTX_init(&ctx);
+ if(EVP_DigestInit(&ctx, EVP_get_digestbyname("sha512"))) {
+ EVP_DigestUpdate(&ctx, message, len);
+ EVP_DigestFinal(&ctx, out, NULL);
+ return 0; /* success */
+ }
+#endif
+ return 1; /* error */
+}
+
+int
+_libssh2_md5_init(libssh2_md5_ctx *ctx)
+{
+#ifdef HAVE_OPAQUE_STRUCTS
+ *ctx = EVP_MD_CTX_new();
+
+ if (*ctx == NULL)
+ return 0;
+
+ if (EVP_DigestInit(*ctx, EVP_get_digestbyname("md5")))
+ return 1;
+
+ EVP_MD_CTX_free(*ctx);
+ *ctx = NULL;
+
+ return 0;
+#else
+ EVP_MD_CTX_init(ctx);
+ return EVP_DigestInit(ctx, EVP_get_digestbyname("md5"));
+#endif
}
static unsigned char *
@@ -1036,6 +1376,272 @@ gen_publickey_from_dsa_evp(LIBSSH2_SESSI
}
#endif /* LIBSSH_DSA */
+#if LIBSSH2_ECDSA
+
+static int
+gen_publickey_from_ec_evp(LIBSSH2_SESSION *session,
+ unsigned char **method,
+ size_t *method_len,
+ unsigned char **pubkeydata,
+ size_t *pubkeydata_len,
+ EVP_PKEY *pk)
+{
+ int rc = 0;
+ EC_KEY *ec = NULL;
+ unsigned char *p;
+ unsigned char* method_buf = NULL;
+ unsigned char *key;
+ size_t key_len = 0;
+ unsigned char *octal_value = NULL;
+ size_t octal_len;
+ const EC_POINT *public_key;
+ const EC_GROUP *group;
+ BN_CTX *bn_ctx;
+ libssh2_curve_type type;
+
+ _libssh2_debug(session,
+ LIBSSH2_TRACE_AUTH,
+ "Computing public key from EC private key envelop");
+
+ bn_ctx = BN_CTX_new();
+ if ( bn_ctx == NULL )
+ return -1;
+
+ ec = EVP_PKEY_get1_EC_KEY(pk);
+ if ( ec == NULL ) {
+ rc = -1;
+ goto clean_exit;
+ }
+
+ public_key = EC_KEY_get0_public_key(ec);
+ group = EC_KEY_get0_group(ec);
+ type = _libssh2_ecdsa_key_get_curve_type(ec);
+
+ method_buf = LIBSSH2_ALLOC(session, 19);
+ if (method_buf == NULL) {
+ return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "out of memory");
+ }
+
+ if ( type == LIBSSH2_EC_CURVE_NISTP256 )
+ memcpy(method_buf, "ecdsa-sha2-nistp256", 19);
+ else if ( type == LIBSSH2_EC_CURVE_NISTP384 )
+ memcpy(method_buf, "ecdsa-sha2-nistp384", 19);
+ else if ( type == LIBSSH2_EC_CURVE_NISTP521 )
+ memcpy(method_buf, "ecdsa-sha2-nistp521", 19);
+ else {
+ _libssh2_debug(session,
+ LIBSSH2_TRACE_ERROR,
+ "Unsupported EC private key type");
+ rc = -1;
+ goto clean_exit;
+ }
+
+ /* get length */
+ octal_len = EC_POINT_point2oct(group, public_key, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, bn_ctx);
+ if (octal_len > EC_MAX_POINT_LEN) {
+ rc = -1;
+ goto clean_exit;
+ }
+
+ octal_value = malloc(octal_len);
+ if ( octal_value == NULL ) {
+ rc = -1;
+ goto clean_exit;
+ }
+
+ /* convert to octal */
+ if (EC_POINT_point2oct(group, public_key, POINT_CONVERSION_UNCOMPRESSED,
+ octal_value, octal_len, bn_ctx) != octal_len) {
+ rc = -1;
+ goto clean_exit;
+ }
+
+ /* Key form is: type_len(4) + type(19) + domain_len(4) + domain(8) + pub_key_len(4) + pub_key(~65). */
+ key_len = 4 + 19 + 4 + 8 + 4 + octal_len;
+ key = LIBSSH2_ALLOC(session, key_len);
+ if (key == NULL) {
+ rc = -1;
+ goto clean_exit;
+ }
+
+ /* Process key encoding. */
+ p = key;
+
+ /* Key type */
+ _libssh2_store_str(&p, (const char*)method_buf, 19);
+
+ /* Name domain */
+ _libssh2_store_str(&p, (const char*)method_buf + 11, 8);
+
+ /* Public key */
+ _libssh2_store_str(&p, (const char*)octal_value, octal_len);
+
+ *method = method_buf;
+ *method_len = 19;
+ *pubkeydata = key;
+ *pubkeydata_len = key_len;
+
+clean_exit:
+
+ if ( ec != NULL)
+ EC_KEY_free(ec);
+
+ if (bn_ctx != NULL) {
+ BN_CTX_free(bn_ctx);
+ }
+
+ if ( octal_value != NULL )
+ free(octal_value);
+
+ if ( rc == 0 )
+ return 0;
+
+ if (method_buf != NULL )
+ LIBSSH2_FREE(session, method_buf);
+
+ return -1;
+}
+
+/*
+ * _libssh2_ecdsa_create_key
+ *
+ * Creates a local private key based on input curve
+ * and returns octal value and octal length
+ *
+ */
+
+int
+_libssh2_ecdsa_create_key(_libssh2_ec_key **out_private_key,
+ unsigned char **out_public_key_octal,
+ size_t *out_public_key_octal_len, libssh2_curve_type curve_type)
+{
+ int ret = 1;
+ size_t octal_len = 0;
+ unsigned char octal_value[EC_MAX_POINT_LEN];
+ const EC_POINT *public_key = NULL;
+ EC_KEY *private_key = NULL;
+ const EC_GROUP *group = NULL;
+
+ /* create key */
+ BN_CTX *bn_ctx = BN_CTX_new();
+ if (!bn_ctx)
+ return -1;
+
+ private_key = EC_KEY_new_by_curve_name(curve_type);
+ group = EC_KEY_get0_group(private_key);
+
+ EC_KEY_generate_key(private_key);
+ public_key = EC_KEY_get0_public_key(private_key);
+
+ /* get length */
+ octal_len = EC_POINT_point2oct(group, public_key, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, bn_ctx);
+ if (octal_len > EC_MAX_POINT_LEN) {
+ ret = -1;
+ goto clean_exit;
+ }
+
+ /* convert to octal */
+ if (EC_POINT_point2oct(group, public_key, POINT_CONVERSION_UNCOMPRESSED,
+ octal_value, octal_len, bn_ctx) != octal_len){
+ ret = -1;
+ goto clean_exit;
+ }
+
+ if (out_private_key != NULL)
+ *out_private_key = private_key;
+
+ if (out_public_key_octal) {
+ *out_public_key_octal = malloc(octal_len);
+ if (out_public_key_octal == NULL) {
+ ret = -1;
+ goto clean_exit;
+ }
+
+ memcpy(*out_public_key_octal, octal_value, octal_len);
+ }
+
+ if (out_public_key_octal_len != NULL)
+ *out_public_key_octal_len = octal_len;
+
+clean_exit:
+
+ if (bn_ctx)
+ BN_CTX_free(bn_ctx);
+
+ return (ret == 1) ? 0 : -1;
+}
+
+/* _libssh2_ecdh_gen_k
+ *
+ * Computes the shared secret K given a local private key,
+ * remote public key and length
+ */
+
+int
+_libssh2_ecdh_gen_k(_libssh2_bn **k, _libssh2_ec_key *private_key,
+ const unsigned char *server_public_key, size_t server_public_key_len)
+{
+ int ret = 0;
+ int rc;
+ size_t secret_len;
+ unsigned char *secret;
+ const EC_GROUP *private_key_group;
+ EC_POINT *server_public_key_point;
+
+ BN_CTX *bn_ctx = BN_CTX_new();
+
+ if ( !bn_ctx )
+ return -1;
+
+ if ( k == NULL )
+ return -1;
+
+ private_key_group = EC_KEY_get0_group(private_key);
+
+ server_public_key_point = EC_POINT_new(private_key_group);
+ if ( server_public_key_point == NULL )
+ return -1;
+
+ rc = EC_POINT_oct2point(private_key_group, server_public_key_point, server_public_key, server_public_key_len, bn_ctx);
+ if ( rc != 1 ) {
+ ret = -1;
+ goto clean_exit;
+ }
+
+ secret_len = (EC_GROUP_get_degree(private_key_group) + 7) / 8;
+ secret = malloc(secret_len);
+ if (!secret) {
+ ret = -1;
+ goto clean_exit;
+ }
+
+ secret_len = ECDH_compute_key(secret, secret_len, server_public_key_point, private_key, NULL);
+
+ if( secret_len <= 0 || secret_len > EC_MAX_POINT_LEN ) {
+ ret = -1;
+ goto clean_exit;
+ }
+
+ BN_bin2bn(secret, secret_len, *k);
+
+clean_exit:
+
+ if ( server_public_key_point != NULL )
+ EC_POINT_free(server_public_key_point);
+
+ if ( bn_ctx != NULL )
+ BN_CTX_free(bn_ctx);
+
+ if ( secret != NULL )
+ free(secret);
+
+ return ret;
+}
+
+
+#endif /* LIBSSH2_ECDSA */
+
int
_libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session,
unsigned char **method,
@@ -1102,6 +1708,13 @@ _libssh2_pub_priv_keyfile(LIBSSH2_SESSIO
break;
#endif /* LIBSSH_DSA */
+#if LIBSSH2_ECDSA
+ case EVP_PKEY_EC :
+ st = gen_publickey_from_ec_evp(
+ session, method, method_len, pubkeydata, pubkeydata_len, pk);
+ break;
+#endif
+
default :
st = _libssh2_error(session,
LIBSSH2_ERROR_FILE,
@@ -1176,6 +1789,12 @@ _libssh2_pub_priv_keyfilememory(LIBSSH2_
pubkeydata, pubkeydata_len, pk);
break;
#endif /* LIBSSH_DSA */
+#if LIBSSH2_ECDSA
+ case EVP_PKEY_EC :
+ st = gen_publickey_from_ec_evp(session, method, method_len,
+ pubkeydata, pubkeydata_len, pk);
+ break;
+#endif
default :
st = _libssh2_error(session,
LIBSSH2_ERROR_FILE,