From dc38b357c3a6e0db4a7172af29148961b86b0724 Mon Sep 17 00:00:00 2001
From: tb <>
Date: Sat, 19 Jan 2019 01:07:00 +0000
Subject: Partial port of EC_KEY_METHOD from OpenSSL 1.1. This commit adds
 init/free, support for signing, setting and getting the method, engine
 support as well as extra data.

from markus
---
 src/lib/libcrypto/Makefile          |  10 +-
 src/lib/libcrypto/Symbols.list      |  13 ++
 src/lib/libcrypto/crypto.h          |   3 +-
 src/lib/libcrypto/ec/ec.h           |  31 +++-
 src/lib/libcrypto/ec/ec_key.c       |  91 +++++++++---
 src/lib/libcrypto/ec/ec_kmeth.c     | 272 ++++++++++++++++++++++++++++++++++++
 src/lib/libcrypto/ec/ec_lcl.h       |  30 +++-
 src/lib/libcrypto/ecdsa/ecdsa.h     |  22 ++-
 src/lib/libcrypto/ecdsa/ecs_locl.h  |  10 +-
 src/lib/libcrypto/ecdsa/ecs_ossl.c  |  39 +++++-
 src/lib/libcrypto/ecdsa/ecs_sign.c  |  38 +++--
 src/lib/libcrypto/engine/eng_fat.c  |  11 +-
 src/lib/libcrypto/engine/eng_int.h  |   3 +-
 src/lib/libcrypto/engine/eng_list.c |   5 +-
 src/lib/libcrypto/engine/engine.h   |  14 +-
 src/lib/libcrypto/engine/tb_eckey.c | 123 ++++++++++++++++
 16 files changed, 659 insertions(+), 56 deletions(-)
 create mode 100644 src/lib/libcrypto/ec/ec_kmeth.c
 create mode 100644 src/lib/libcrypto/engine/tb_eckey.c

(limited to 'src')

diff --git a/src/lib/libcrypto/Makefile b/src/lib/libcrypto/Makefile
index 8e39d92ab4..66f511761b 100644
--- a/src/lib/libcrypto/Makefile
+++ b/src/lib/libcrypto/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.30 2018/11/11 06:53:31 tb Exp $
+# $OpenBSD: Makefile,v 1.31 2019/01/19 01:07:00 tb Exp $
 
 LIB=	crypto
 LIBREBUILD=y
@@ -31,6 +31,10 @@ CFLAGS+= -I${LCRYPTO_SRC}
 CFLAGS+= -I${LCRYPTO_SRC}/asn1 -I${LCRYPTO_SRC}/bn -I${LCRYPTO_SRC}/evp
 CFLAGS+= -I${LCRYPTO_SRC}/modes
 
+# XXX FIXME ecdsa and ec should be merged
+CFLAGS+= -I${LCRYPTO_SRC}/ecdsa
+CFLAGS+= -I${LCRYPTO_SRC}/ec
+
 VERSION_SCRIPT=	Symbols.map
 SYMBOL_LIST=	${.CURDIR}/Symbols.list
 
@@ -125,7 +129,7 @@ SRCS+= dso_openssl.c
 # ec/
 SRCS+= ec_lib.c ecp_smpl.c ecp_mont.c ecp_nist.c ec_cvt.c ec_mult.c
 SRCS+= ec_err.c ec_curve.c ec_check.c ec_print.c ec_asn1.c ec_key.c
-SRCS+= ec2_smpl.c ec2_mult.c ec_ameth.c ec_pmeth.c eck_prn.c
+SRCS+= ec2_smpl.c ec2_mult.c ec_ameth.c ec_pmeth.c ec_kmeth.c eck_prn.c
 SRCS+= ecp_nistp224.c ecp_nistp256.c ecp_nistp521.c ecp_nistputil.c
 SRCS+= ecp_oct.c ec2_oct.c ec_oct.c
 
@@ -139,7 +143,7 @@ SRCS+= ecs_lib.c ecs_asn1.c ecs_ossl.c ecs_sign.c ecs_vrf.c ecs_err.c
 SRCS+= eng_err.c eng_lib.c eng_list.c eng_init.c eng_ctrl.c
 SRCS+= eng_table.c eng_pkey.c eng_fat.c eng_all.c
 SRCS+= tb_rsa.c tb_dsa.c tb_ecdsa.c tb_dh.c tb_ecdh.c tb_rand.c tb_store.c
-SRCS+= tb_cipher.c tb_digest.c tb_pkmeth.c tb_asnmth.c
+SRCS+= tb_cipher.c tb_digest.c tb_pkmeth.c tb_asnmth.c tb_eckey.c
 SRCS+= eng_openssl.c eng_cnf.c eng_dyn.c
 # XXX unnecessary? handled in EVP now...
 # SRCS+= eng_aesni.c # local addition
diff --git a/src/lib/libcrypto/Symbols.list b/src/lib/libcrypto/Symbols.list
index c4b78dbef2..2734fed62a 100644
--- a/src/lib/libcrypto/Symbols.list
+++ b/src/lib/libcrypto/Symbols.list
@@ -955,6 +955,13 @@ EC_GROUP_set_curve_name
 EC_GROUP_set_generator
 EC_GROUP_set_point_conversion_form
 EC_GROUP_set_seed
+EC_KEY_METHOD_free
+EC_KEY_METHOD_get_init
+EC_KEY_METHOD_get_sign
+EC_KEY_METHOD_new
+EC_KEY_METHOD_set_init
+EC_KEY_METHOD_set_sign
+EC_KEY_OpenSSL
 EC_KEY_check_key
 EC_KEY_clear_flags
 EC_KEY_copy
@@ -965,9 +972,12 @@ EC_KEY_get0_group
 EC_KEY_get0_private_key
 EC_KEY_get0_public_key
 EC_KEY_get_conv_form
+EC_KEY_get_default_method
 EC_KEY_get_enc_flags
+EC_KEY_get_ex_data
 EC_KEY_get_flags
 EC_KEY_get_key_method_data
+EC_KEY_get_method
 EC_KEY_insert_key_method_data
 EC_KEY_new
 EC_KEY_new_by_curve_name
@@ -976,9 +986,12 @@ EC_KEY_print
 EC_KEY_print_fp
 EC_KEY_set_asn1_flag
 EC_KEY_set_conv_form
+EC_KEY_set_default_method
 EC_KEY_set_enc_flags
+EC_KEY_set_ex_data
 EC_KEY_set_flags
 EC_KEY_set_group
+EC_KEY_set_method
 EC_KEY_set_private_key
 EC_KEY_set_public_key
 EC_KEY_set_public_key_affine_coordinates
diff --git a/src/lib/libcrypto/crypto.h b/src/lib/libcrypto/crypto.h
index 8d549da8b5..7de8abb437 100644
--- a/src/lib/libcrypto/crypto.h
+++ b/src/lib/libcrypto/crypto.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: crypto.h,v 1.49 2018/11/11 16:32:28 bcook Exp $ */
+/* $OpenBSD: crypto.h,v 1.50 2019/01/19 01:07:00 tb Exp $ */
 /* ====================================================================
  * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
  *
@@ -286,6 +286,7 @@ DECLARE_STACK_OF(CRYPTO_EX_DATA_FUNCS)
 #define CRYPTO_EX_INDEX_ECDH		13
 #define CRYPTO_EX_INDEX_COMP		14
 #define CRYPTO_EX_INDEX_STORE		15
+#define CRYPTO_EX_INDEX_EC_KEY		16
 
 /* Dynamically assigned indexes start from this value (don't use directly, use
  * via CRYPTO_ex_data_new_class). */
diff --git a/src/lib/libcrypto/ec/ec.h b/src/lib/libcrypto/ec/ec.h
index d9df48603a..1173459dae 100644
--- a/src/lib/libcrypto/ec/ec.h
+++ b/src/lib/libcrypto/ec/ec.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ec.h,v 1.13 2018/05/19 10:37:02 tb Exp $ */
+/* $OpenBSD: ec.h,v 1.14 2019/01/19 01:07:00 tb Exp $ */
 /*
  * Originally written by Bodo Moeller for the OpenSSL project.
  */
@@ -705,6 +705,7 @@ int     ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off);
 /********************************************************************/
 
 typedef struct ec_key_st EC_KEY;
+typedef struct ec_key_method_st EC_KEY_METHOD;
 
 /* some values for the encoding_flag */
 #define EC_PKEY_NO_PARAMETERS	0x001
@@ -945,6 +946,34 @@ int	ECParameters_print_fp(FILE *fp, const EC_KEY *key);
  */
 int	EC_KEY_print_fp(FILE *fp, const EC_KEY *key, int off);
 
+#define EC_KEY_get_ex_new_index(l, p, newf, dupf, freef) \
+    CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_EC_KEY, l, p, newf, dupf, freef)
+int EC_KEY_set_ex_data(EC_KEY *key, int idx, void *arg);
+void *EC_KEY_get_ex_data(const EC_KEY *key, int idx);
+
+const EC_KEY_METHOD *EC_KEY_OpenSSL(void);
+const EC_KEY_METHOD *EC_KEY_get_default_method(void);
+void EC_KEY_set_default_method(const EC_KEY_METHOD *meth);
+const EC_KEY_METHOD *EC_KEY_get_method(const EC_KEY *key);
+int EC_KEY_set_method(EC_KEY *key, const EC_KEY_METHOD *meth);
+EC_KEY *EC_KEY_new_method(ENGINE *engine);
+EC_KEY_METHOD *EC_KEY_METHOD_new(const EC_KEY_METHOD *meth);
+void EC_KEY_METHOD_free(EC_KEY_METHOD *meth);
+void EC_KEY_METHOD_set_init(EC_KEY_METHOD *meth,
+    int (*init)(EC_KEY *key),
+    void (*finish)(EC_KEY *key),
+    int (*copy)(EC_KEY *dest, const EC_KEY *src),
+    int (*set_group)(EC_KEY *key, const EC_GROUP *grp),
+    int (*set_private)(EC_KEY *key, const BIGNUM *priv_key),
+    int (*set_public)(EC_KEY *key, const EC_POINT *pub_key));
+void EC_KEY_METHOD_get_init(EC_KEY_METHOD *meth,
+    int (**pinit)(EC_KEY *key),
+    void (**pfinish)(EC_KEY *key),
+    int (**pcopy)(EC_KEY *dest, const EC_KEY *src),
+    int (**pset_group)(EC_KEY *key, const EC_GROUP *grp),
+    int (**pset_private)(EC_KEY *key, const BIGNUM *priv_key),
+    int (**pset_public)(EC_KEY *key, const EC_POINT *pub_key));
+
 EC_KEY *ECParameters_dup(EC_KEY *key);
 
 #ifndef __cplusplus
diff --git a/src/lib/libcrypto/ec/ec_key.c b/src/lib/libcrypto/ec/ec_key.c
index fcdf461d20..f57e078c7f 100644
--- a/src/lib/libcrypto/ec/ec_key.c
+++ b/src/lib/libcrypto/ec/ec_key.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ec_key.c,v 1.22 2018/11/09 23:39:45 tb Exp $ */
+/* $OpenBSD: ec_key.c,v 1.23 2019/01/19 01:07:00 tb Exp $ */
 /*
  * Written by Nils Larsch for the OpenSSL project.
  */
@@ -65,30 +65,18 @@
 
 #include <openssl/opensslconf.h>
 
+#ifndef OPENSSL_NO_ENGINE
+#include <openssl/engine.h>
+#endif
+#include <openssl/err.h>
+
 #include "bn_lcl.h"
 #include "ec_lcl.h"
-#include <openssl/err.h>
 
 EC_KEY *
 EC_KEY_new(void)
 {
-	EC_KEY *ret;
-
-	ret = malloc(sizeof(EC_KEY));
-	if (ret == NULL) {
-		ECerror(ERR_R_MALLOC_FAILURE);
-		return (NULL);
-	}
-	ret->version = 1;
-	ret->flags = 0;
-	ret->group = NULL;
-	ret->pub_key = NULL;
-	ret->priv_key = NULL;
-	ret->enc_flag = 0;
-	ret->conv_form = POINT_CONVERSION_UNCOMPRESSED;
-	ret->references = 1;
-	ret->method_data = NULL;
-	return (ret);
+	return EC_KEY_new_method(NULL);
 }
 
 EC_KEY *
@@ -102,6 +90,11 @@ EC_KEY_new_by_curve_name(int nid)
 		EC_KEY_free(ret);
 		return NULL;
 	}
+	if (ret->meth->set_group != NULL &&
+	    ret->meth->set_group(ret, ret->group) == 0) {
+		EC_KEY_free(ret);
+		return NULL;
+	}
 	return ret;
 }
 
@@ -117,6 +110,14 @@ EC_KEY_free(EC_KEY * r)
 	if (i > 0)
 		return;
 
+	if (r->meth != NULL && r->meth->finish != NULL)
+		r->meth->finish(r);
+
+#ifndef OPENSSL_NO_ENGINE
+	ENGINE_finish(r->engine);
+#endif
+	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EC_KEY, r, &r->ex_data);
+
 	EC_GROUP_free(r->group);
 	EC_POINT_free(r->pub_key);
 	BN_clear_free(r->priv_key);
@@ -135,6 +136,15 @@ EC_KEY_copy(EC_KEY * dest, const EC_KEY * src)
 		ECerror(ERR_R_PASSED_NULL_PARAMETER);
 		return NULL;
 	}
+	if (src->meth != dest->meth) {
+		if (dest->meth != NULL && dest->meth->finish != NULL)
+			dest->meth->finish(dest);
+#ifndef OPENSSL_NO_ENGINE
+		if (ENGINE_finish(dest->engine) == 0)
+			return 0;
+		dest->engine = NULL;
+#endif
+	}
 	/* copy the parameters */
 	if (src->group) {
 		const EC_METHOD *meth = EC_GROUP_method_of(src->group);
@@ -184,14 +194,32 @@ EC_KEY_copy(EC_KEY * dest, const EC_KEY * src)
 	dest->version = src->version;
 	dest->flags = src->flags;
 
+	if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY, &dest->ex_data,
+	    &((EC_KEY *)src)->ex_data))	/* XXX const */
+		return NULL;
+
+	if (src->meth != dest->meth) {
+#ifndef OPENSSL_NO_ENGINE
+		if (src->engine != NULL && ENGINE_init(src->engine) == 0)
+			return 0;
+		dest->engine = src->engine;
+#endif
+		dest->meth = src->meth;
+	}
+
+	if (src->meth != NULL && src->meth->copy != NULL &&
+	    src->meth->copy(dest, src) == 0)
+		return 0;
+
 	return dest;
 }
 
 EC_KEY *
 EC_KEY_dup(const EC_KEY * ec_key)
 {
-	EC_KEY *ret = EC_KEY_new();
-	if (ret == NULL)
+	EC_KEY *ret;
+
+	if ((ret = EC_KEY_new_method(ec_key->engine)) == NULL)
 		return NULL;
 	if (EC_KEY_copy(ret, ec_key) == NULL) {
 		EC_KEY_free(ret);
@@ -207,6 +235,18 @@ EC_KEY_up_ref(EC_KEY * r)
 	return ((i > 1) ? 1 : 0);
 }
 
+int
+EC_KEY_set_ex_data(EC_KEY *r, int idx, void *arg)
+{
+	return CRYPTO_set_ex_data(&r->ex_data, idx, arg);
+}
+
+void *
+EC_KEY_get_ex_data(const EC_KEY *r, int idx)
+{
+	return CRYPTO_get_ex_data(&r->ex_data, idx);
+}
+
 int 
 EC_KEY_generate_key(EC_KEY *eckey)
 {
@@ -407,6 +447,9 @@ EC_KEY_get0_group(const EC_KEY * key)
 int 
 EC_KEY_set_group(EC_KEY * key, const EC_GROUP * group)
 {
+	if (key->meth->set_group != NULL &&
+	    key->meth->set_group(key, group) == 0)
+		return 0;
 	EC_GROUP_free(key->group);
 	key->group = EC_GROUP_dup(group);
 	return (key->group == NULL) ? 0 : 1;
@@ -421,6 +464,9 @@ EC_KEY_get0_private_key(const EC_KEY * key)
 int 
 EC_KEY_set_private_key(EC_KEY * key, const BIGNUM * priv_key)
 {
+	if (key->meth->set_private != NULL &&
+	    key->meth->set_private(key, priv_key) == 0)
+		return 0;
 	BN_clear_free(key->priv_key);
 	key->priv_key = BN_dup(priv_key);
 	return (key->priv_key == NULL) ? 0 : 1;
@@ -435,6 +481,9 @@ EC_KEY_get0_public_key(const EC_KEY * key)
 int 
 EC_KEY_set_public_key(EC_KEY * key, const EC_POINT * pub_key)
 {
+	if (key->meth->set_public != NULL &&
+	    key->meth->set_public(key, pub_key) == 0)
+		return 0;
 	EC_POINT_free(key->pub_key);
 	key->pub_key = EC_POINT_dup(pub_key, key->group);
 	return (key->pub_key == NULL) ? 0 : 1;
diff --git a/src/lib/libcrypto/ec/ec_kmeth.c b/src/lib/libcrypto/ec/ec_kmeth.c
new file mode 100644
index 0000000000..b714c62236
--- /dev/null
+++ b/src/lib/libcrypto/ec/ec_kmeth.c
@@ -0,0 +1,272 @@
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2015 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include <openssl/ec.h>
+#ifndef OPENSSL_NO_ENGINE
+#include <openssl/engine.h>
+#endif
+#include <openssl/err.h>
+
+#include "ec_lcl.h"
+#include "ecs_locl.h"
+
+static const EC_KEY_METHOD openssl_ec_key_method = {
+	.name = "OpenSSL EC_KEY method",
+	.flags = 0,
+
+	.init = NULL,
+	.finish = NULL,
+	.copy = NULL,
+
+	.set_group = NULL,
+	.set_private = NULL,
+	.set_public = NULL,
+
+	.sign = ossl_ecdsa_sign,
+	.sign_setup = ossl_ecdsa_sign_setup,
+	.sign_sig = ossl_ecdsa_sign_sig,
+};
+
+const EC_KEY_METHOD *default_ec_key_meth = &openssl_ec_key_method;
+
+const EC_KEY_METHOD *
+EC_KEY_OpenSSL(void)
+{
+	return &openssl_ec_key_method;
+}
+
+const EC_KEY_METHOD *
+EC_KEY_get_default_method(void)
+{
+	return default_ec_key_meth;
+}
+
+void
+EC_KEY_set_default_method(const EC_KEY_METHOD *meth)
+{
+	if (meth == NULL)
+		default_ec_key_meth = &openssl_ec_key_method;
+	else
+		default_ec_key_meth = meth;
+}
+
+const EC_KEY_METHOD *
+EC_KEY_get_method(const EC_KEY *key)
+{
+	return key->meth;
+}
+
+int
+EC_KEY_set_method(EC_KEY *key, const EC_KEY_METHOD *meth)
+{
+	void (*finish)(EC_KEY *key) = key->meth->finish;
+
+	if (finish != NULL)
+		finish(key);
+
+#ifndef OPENSSL_NO_ENGINE
+	ENGINE_finish(key->engine);
+	key->engine = NULL;
+#endif
+
+	key->meth = meth;
+	if (meth->init != NULL)
+		return meth->init(key);
+	return 1;
+}
+
+EC_KEY *
+EC_KEY_new_method(ENGINE *engine)
+{
+	EC_KEY *ret;
+
+	if ((ret = calloc(1, sizeof(EC_KEY))) == NULL) {
+		ECerror(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+	ret->meth = EC_KEY_get_default_method();
+#ifndef OPENSSL_NO_ENGINE
+	if (engine != NULL) {
+		if (!ENGINE_init(engine)) {
+			ECerror(ERR_R_ENGINE_LIB);
+			goto err;
+		}
+		ret->engine = engine;
+	} else
+		ret->engine = ENGINE_get_default_EC();
+	if (ret->engine) {
+		ret->meth = ENGINE_get_EC(ret->engine);
+		if (ret->meth == NULL) {
+			ECerror(ERR_R_ENGINE_LIB);
+			goto err;
+		}
+	}
+#endif
+	ret->version = 1;
+	ret->flags = 0;
+	ret->group = NULL;
+	ret->pub_key = NULL;
+	ret->priv_key = NULL;
+	ret->enc_flag = 0;
+	ret->conv_form = POINT_CONVERSION_UNCOMPRESSED;
+	ret->references = 1;
+	ret->method_data = NULL;
+
+	if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data))
+		goto err;
+	if (ret->meth->init != NULL && ret->meth->init(ret) == 0)
+		goto err;
+
+	return ret;
+
+ err:
+	EC_KEY_free(ret);
+	return NULL;
+}
+
+EC_KEY_METHOD *
+EC_KEY_METHOD_new(const EC_KEY_METHOD *meth)
+{
+	EC_KEY_METHOD *ret;
+
+	if ((ret = malloc(sizeof(*meth))) == NULL)
+		return NULL;
+	if (meth != NULL)
+		*ret = *meth;
+	ret->flags |= EC_KEY_METHOD_DYNAMIC;
+	return ret;
+}
+
+void
+EC_KEY_METHOD_free(EC_KEY_METHOD *meth)
+{
+	if (meth == NULL)
+		return;
+	if (meth->flags & EC_KEY_METHOD_DYNAMIC)
+		free(meth);
+}
+
+void
+EC_KEY_METHOD_get_init(EC_KEY_METHOD *meth,
+    int (**pinit)(EC_KEY *key),
+    void (**pfinish)(EC_KEY *key),
+    int (**pcopy)(EC_KEY *dest, const EC_KEY *src),
+    int (**pset_group)(EC_KEY *key, const EC_GROUP *grp),
+    int (**pset_private)(EC_KEY *key, const BIGNUM *priv_key),
+    int (**pset_public)(EC_KEY *key, const EC_POINT *pub_key))
+{
+	if (pinit != NULL)
+		*pinit = meth->init;
+	if (pfinish != NULL)
+		*pfinish = meth->finish;
+	if (pcopy != NULL)
+		*pcopy = meth->copy;
+	if (pset_group != NULL)
+		*pset_group = meth->set_group;
+	if (pset_private != NULL)
+		*pset_private = meth->set_private;
+	if (pset_public != NULL)
+		*pset_public = meth->set_public;
+}
+
+void
+EC_KEY_METHOD_set_init(EC_KEY_METHOD *meth,
+    int (*init)(EC_KEY *key),
+    void (*finish)(EC_KEY *key),
+    int (*copy)(EC_KEY *dest, const EC_KEY *src),
+    int (*set_group)(EC_KEY *key, const EC_GROUP *grp),
+    int (*set_private)(EC_KEY *key, const BIGNUM *priv_key),
+    int (*set_public)(EC_KEY *key, const EC_POINT *pub_key))
+{
+	meth->init = init;
+	meth->finish = finish;
+	meth->copy = copy;
+	meth->set_group = set_group;
+	meth->set_private = set_private;
+	meth->set_public = set_public;
+}
+
+void
+EC_KEY_METHOD_get_sign(EC_KEY_METHOD *meth,
+    int (**psign)(int type, const unsigned char *dgst,
+	int dlen, unsigned char *sig, unsigned int *siglen,
+	const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey),
+    int (**psign_setup)(EC_KEY *eckey, BN_CTX *ctx_in,
+	BIGNUM **kinvp, BIGNUM **rp),
+    ECDSA_SIG *(**psign_sig)(const unsigned char *dgst,
+	int dgst_len, const BIGNUM *in_kinv, const BIGNUM *in_r,
+	EC_KEY *eckey))
+{
+	if (psign != NULL)
+		*psign = meth->sign;
+	if (psign_setup != NULL)
+		*psign_setup = meth->sign_setup;
+	if (psign_sig != NULL)
+		*psign_sig = meth->sign_sig;
+}
+
+void
+EC_KEY_METHOD_set_sign(EC_KEY_METHOD *meth,
+    int (*sign)(int type, const unsigned char *dgst,
+	int dlen, unsigned char *sig, unsigned int *siglen,
+	const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey),
+    int (*sign_setup)(EC_KEY *eckey, BN_CTX *ctx_in,
+	BIGNUM **kinvp, BIGNUM **rp),
+    ECDSA_SIG *(*sign_sig)(const unsigned char *dgst,
+	int dgst_len, const BIGNUM *in_kinv,
+	const BIGNUM *in_r, EC_KEY *eckey))
+{
+	meth->sign = sign;
+	meth->sign_setup = sign_setup;
+	meth->sign_sig = sign_sig;
+}
diff --git a/src/lib/libcrypto/ec/ec_lcl.h b/src/lib/libcrypto/ec/ec_lcl.h
index c177246f36..cff0892e89 100644
--- a/src/lib/libcrypto/ec/ec_lcl.h
+++ b/src/lib/libcrypto/ec/ec_lcl.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ec_lcl.h,v 1.11 2018/11/05 20:18:21 tb Exp $ */
+/* $OpenBSD: ec_lcl.h,v 1.12 2019/01/19 01:07:00 tb Exp $ */
 /*
  * Originally written by Bodo Moeller for the OpenSSL project.
  */
@@ -73,6 +73,7 @@
 
 #include <openssl/obj_mac.h>
 #include <openssl/ec.h>
+#include <openssl/ecdsa.h>
 #include <openssl/bn.h>
 
 __BEGIN_HIDDEN_DECLS
@@ -245,6 +246,9 @@ struct ec_group_st {
 } /* EC_GROUP */;
 
 struct ec_key_st {
+	const EC_KEY_METHOD *meth;
+	ENGINE	*engine;
+
 	int version;
 
 	EC_GROUP *group;
@@ -259,6 +263,7 @@ struct ec_key_st {
 	int	flags;
 
 	EC_EXTRA_DATA *method_data;
+	CRYPTO_EX_DATA ex_data;
 } /* EC_KEY */;
 
 /* Basically a 'mixin' for extra data, but available for EC_GROUPs/EC_KEYs only
@@ -441,6 +446,29 @@ int ec_GFp_nistp256_have_precompute_mult(const EC_GROUP *group);
 const EC_METHOD *EC_GFp_nistz256_method(void);
 #endif
 
+/* EC_METHOD definitions */
+
+struct ec_key_method_st {
+	const char *name;
+	int32_t flags;
+	int (*init)(EC_KEY *key);
+	void (*finish)(EC_KEY *key);
+	int (*copy)(EC_KEY *dest, const EC_KEY *src);
+	int (*set_group)(EC_KEY *key, const EC_GROUP *grp);
+	int (*set_private)(EC_KEY *key, const BIGNUM *priv_key);
+	int (*set_public)(EC_KEY *key, const EC_POINT *pub_key);
+	int (*sign)(int type, const unsigned char *dgst, int dlen, unsigned char
+	    *sig, unsigned int *siglen, const BIGNUM *kinv,
+	    const BIGNUM *r, EC_KEY *eckey);
+	int (*sign_setup)(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
+	    BIGNUM **rp);
+	ECDSA_SIG *(*sign_sig)(const unsigned char *dgst, int dgst_len,
+	    const BIGNUM *in_kinv, const BIGNUM *in_r,
+	    EC_KEY *eckey);
+} /* EC_KEY_METHOD */;
+
+#define EC_KEY_METHOD_DYNAMIC   1
+
 /* method functions in ecp_nistp521.c */
 int ec_GFp_nistp521_group_init(EC_GROUP *group);
 int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *n, BN_CTX *);
diff --git a/src/lib/libcrypto/ecdsa/ecdsa.h b/src/lib/libcrypto/ecdsa/ecdsa.h
index 9c53230a88..12d6677ce3 100644
--- a/src/lib/libcrypto/ecdsa/ecdsa.h
+++ b/src/lib/libcrypto/ecdsa/ecdsa.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ecdsa.h,v 1.5 2018/03/17 15:24:44 tb Exp $ */
+/* $OpenBSD: ecdsa.h,v 1.6 2019/01/19 01:07:00 tb Exp $ */
 /**
  * \file   crypto/ecdsa/ecdsa.h Include file for the OpenSSL ECDSA functions
  * \author Written by Nils Larsch for the OpenSSL project
@@ -269,6 +269,26 @@ int ECDSA_set_ex_data(EC_KEY *d, int idx, void *arg);
 void *ECDSA_get_ex_data(EC_KEY *d, int idx);
 
 
+/* XXX should be in ec.h, but needs ECDSA_SIG */
+void EC_KEY_METHOD_set_sign(EC_KEY_METHOD *meth,
+    int (*sign)(int type, const unsigned char *dgst,
+	int dlen, unsigned char *sig, unsigned int *siglen,
+	const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey),
+    int (*sign_setup)(EC_KEY *eckey, BN_CTX *ctx_in,
+	BIGNUM **kinvp, BIGNUM **rp),
+    ECDSA_SIG *(*sign_sig)(const unsigned char *dgst,
+	int dgst_len, const BIGNUM *in_kinv, const BIGNUM *in_r,
+	EC_KEY *eckey));
+void EC_KEY_METHOD_get_sign(EC_KEY_METHOD *meth,
+    int (**psign)(int type, const unsigned char *dgst,
+	int dlen, unsigned char *sig, unsigned int *siglen,
+	const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey),
+    int (**psign_setup)(EC_KEY *eckey, BN_CTX *ctx_in,
+	BIGNUM **kinvp, BIGNUM **rp),
+    ECDSA_SIG *(**psign_sig)(const unsigned char *dgst,
+	int dgst_len, const BIGNUM *in_kinv, const BIGNUM *in_r,
+	EC_KEY *eckey));
+
 /* BEGIN ERROR CODES */
 /* The following lines are auto generated by the script mkerr.pl. Any changes
  * made after this point may be overwritten when the script is next run.
diff --git a/src/lib/libcrypto/ecdsa/ecs_locl.h b/src/lib/libcrypto/ecdsa/ecs_locl.h
index 94e8874332..0a9f17908b 100644
--- a/src/lib/libcrypto/ecdsa/ecs_locl.h
+++ b/src/lib/libcrypto/ecdsa/ecs_locl.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ecs_locl.h,v 1.5 2016/12/21 15:49:29 jsing Exp $ */
+/* $OpenBSD: ecs_locl.h,v 1.6 2019/01/19 01:07:00 tb Exp $ */
 /*
  * Written by Nils Larsch for the OpenSSL project
  */
@@ -81,6 +81,14 @@ typedef struct ecdsa_data_st {
  */
 ECDSA_DATA *ecdsa_check(EC_KEY *eckey);
 
+int ossl_ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
+    BIGNUM **rp);
+int ossl_ecdsa_sign(int type, const unsigned char *dgst, int dlen,
+    unsigned char *sig, unsigned int *siglen, const BIGNUM *kinv,
+    const BIGNUM *r, EC_KEY *eckey);
+ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
+    const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey);
+
 __END_HIDDEN_DECLS
 
 #endif /* HEADER_ECS_LOCL_H */
diff --git a/src/lib/libcrypto/ecdsa/ecs_ossl.c b/src/lib/libcrypto/ecdsa/ecs_ossl.c
index 87d80642df..4e05cb9aac 100644
--- a/src/lib/libcrypto/ecdsa/ecs_ossl.c
+++ b/src/lib/libcrypto/ecdsa/ecs_ossl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ecs_ossl.c,v 1.16 2018/07/10 21:36:02 tb Exp $ */
+/* $OpenBSD: ecs_ossl.c,v 1.17 2019/01/19 01:07:00 tb Exp $ */
 /*
  * Written by Nils Larsch for the OpenSSL project
  */
@@ -111,6 +111,21 @@ ecdsa_prepare_digest(const unsigned char *dgst, int dgst_len, BIGNUM *order,
 	return 1;
 }
 
+int
+ossl_ecdsa_sign(int type, const unsigned char *dgst, int dlen, unsigned char *sig,
+    unsigned int *siglen, const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey)
+{
+	ECDSA_SIG *s;
+
+	if ((s = ECDSA_do_sign_ex(dgst, dlen, kinv, r, eckey)) == NULL) {
+		*siglen = 0;
+		return 0;
+	}
+	*siglen = i2d_ECDSA_SIG(s, &sig);
+	ECDSA_SIG_free(s);
+	return 1;
+}
+
 static int
 ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
 {
@@ -234,6 +249,16 @@ ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
 	return (ret);
 }
 
+/* replace w/ ecdsa_sign_setup() when ECDSA_METHOD gets removed */
+int
+ossl_ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
+{
+	ECDSA_DATA *ecdsa;
+
+	if ((ecdsa = ecdsa_check(eckey)) == NULL)
+		return 0;
+	return ecdsa->meth->ecdsa_sign_setup(eckey, ctx_in, kinvp, rp);
+}
 
 static ECDSA_SIG *
 ecdsa_do_sign(const unsigned char *dgst, int dgst_len,
@@ -384,6 +409,18 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len,
 	return ret;
 }
 
+/* replace w/ ecdsa_do_sign() when ECDSA_METHOD gets removed */
+ECDSA_SIG *
+ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
+    const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey)
+{
+	ECDSA_DATA *ecdsa;
+
+	if ((ecdsa = ecdsa_check(eckey)) == NULL)
+		return NULL;
+	return ecdsa->meth->ecdsa_do_sign(dgst, dgst_len, in_kinv, in_r, eckey);
+}
+
 static int
 ecdsa_do_verify(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig,
     EC_KEY *eckey)
diff --git a/src/lib/libcrypto/ecdsa/ecs_sign.c b/src/lib/libcrypto/ecdsa/ecs_sign.c
index 029a0cb562..5beb853b94 100644
--- a/src/lib/libcrypto/ecdsa/ecs_sign.c
+++ b/src/lib/libcrypto/ecdsa/ecs_sign.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ecs_sign.c,v 1.6 2015/02/08 13:35:07 jsing Exp $ */
+/* $OpenBSD: ecs_sign.c,v 1.7 2019/01/19 01:07:00 tb Exp $ */
 /* ====================================================================
  * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
  *
@@ -55,11 +55,13 @@
 
 #include <openssl/opensslconf.h>
 
-#include "ecs_locl.h"
 #ifndef OPENSSL_NO_ENGINE
 #include <openssl/engine.h>
 #endif
 
+#include "ecs_locl.h"
+#include "ec_lcl.h"
+
 ECDSA_SIG *
 ECDSA_do_sign(const unsigned char *dgst, int dlen, EC_KEY *eckey)
 {
@@ -70,11 +72,10 @@ ECDSA_SIG *
 ECDSA_do_sign_ex(const unsigned char *dgst, int dlen, const BIGNUM *kinv,
     const BIGNUM *rp, EC_KEY *eckey)
 {
-	ECDSA_DATA *ecdsa = ecdsa_check(eckey);
-
-	if (ecdsa == NULL)
-		return NULL;
-	return ecdsa->meth->ecdsa_do_sign(dgst, dlen, kinv, rp, eckey);
+	if (eckey->meth->sign_sig != NULL)
+		return eckey->meth->sign_sig(dgst, dlen, kinv, rp, eckey);
+	ECDSAerror(EVP_R_METHOD_NOT_SUPPORTED);
+	return 0;
 }
 
 int
@@ -88,24 +89,17 @@ int
 ECDSA_sign_ex(int type, const unsigned char *dgst, int dlen, unsigned char *sig,
     unsigned int *siglen, const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey)
 {
-	ECDSA_SIG *s;
-
-	s = ECDSA_do_sign_ex(dgst, dlen, kinv, r, eckey);
-	if (s == NULL) {
-		*siglen = 0;
-		return 0;
-	}
-	*siglen = i2d_ECDSA_SIG(s, &sig);
-	ECDSA_SIG_free(s);
-	return 1;
+	if (eckey->meth->sign != NULL)
+		return eckey->meth->sign(type, dgst, dlen, sig, siglen, kinv, r, eckey);
+	ECDSAerror(EVP_R_METHOD_NOT_SUPPORTED);
+	return 0;
 }
 
 int
 ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
 {
-	ECDSA_DATA *ecdsa = ecdsa_check(eckey);
-
-	if (ecdsa == NULL)
-		return 0;
-	return ecdsa->meth->ecdsa_sign_setup(eckey, ctx_in, kinvp, rp);
+	if (eckey->meth->sign_setup != NULL)
+		return eckey->meth->sign_setup(eckey, ctx_in, kinvp, rp);
+	ECDSAerror(EVP_R_METHOD_NOT_SUPPORTED);
+	return 0;
 }
diff --git a/src/lib/libcrypto/engine/eng_fat.c b/src/lib/libcrypto/engine/eng_fat.c
index c97695a7d3..baf1a54883 100644
--- a/src/lib/libcrypto/engine/eng_fat.c
+++ b/src/lib/libcrypto/engine/eng_fat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: eng_fat.c,v 1.16 2017/01/29 17:49:23 beck Exp $ */
+/* $OpenBSD: eng_fat.c,v 1.17 2019/01/19 01:07:00 tb Exp $ */
 /* ====================================================================
  * Copyright (c) 1999-2001 The OpenSSL Project.  All rights reserved.
  *
@@ -92,6 +92,10 @@ ENGINE_set_default(ENGINE *e, unsigned int flags)
 #ifndef OPENSSL_NO_ECDSA
 	if ((flags & ENGINE_METHOD_ECDSA) && !ENGINE_set_default_ECDSA(e))
 		return 0;
+#endif
+#ifndef OPENSSL_NO_EC
+	if ((flags & ENGINE_METHOD_EC) && !ENGINE_set_default_EC(e))
+		return 0;
 #endif
 	if ((flags & ENGINE_METHOD_RAND) && !ENGINE_set_default_RAND(e))
 		return 0;
@@ -123,6 +127,8 @@ int_def_cb(const char *alg, int len, void *arg)
 		*pflags |= ENGINE_METHOD_ECDSA;
 	else if (!strncmp(alg, "DH", len))
 		*pflags |= ENGINE_METHOD_DH;
+	else if (strncmp(alg, "EC", len) == 0)
+		*pflags |= ENGINE_METHOD_EC;
 	else if (!strncmp(alg, "RAND", len))
 		*pflags |= ENGINE_METHOD_RAND;
 	else if (!strncmp(alg, "CIPHERS", len))
@@ -173,6 +179,9 @@ ENGINE_register_complete(ENGINE *e)
 #endif
 #ifndef OPENSSL_NO_ECDSA
 	ENGINE_register_ECDSA(e);
+#endif
+#ifndef OPENSSL_NO_EC
+	ENGINE_register_EC(e);
 #endif
 	ENGINE_register_RAND(e);
 	ENGINE_register_pkey_meths(e);
diff --git a/src/lib/libcrypto/engine/eng_int.h b/src/lib/libcrypto/engine/eng_int.h
index dbb639949d..298c0e327f 100644
--- a/src/lib/libcrypto/engine/eng_int.h
+++ b/src/lib/libcrypto/engine/eng_int.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: eng_int.h,v 1.9 2016/12/21 15:49:29 jsing Exp $ */
+/* $OpenBSD: eng_int.h,v 1.10 2019/01/19 01:07:00 tb Exp $ */
 /* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
  * project 2000.
  */
@@ -159,6 +159,7 @@ struct engine_st {
 	const DH_METHOD *dh_meth;
 	const ECDH_METHOD *ecdh_meth;
 	const ECDSA_METHOD *ecdsa_meth;
+	const EC_KEY_METHOD *ec_meth;
 	const RAND_METHOD *rand_meth;
 	const STORE_METHOD *store_meth;
 	/* Cipher handling is via this callback */
diff --git a/src/lib/libcrypto/engine/eng_list.c b/src/lib/libcrypto/engine/eng_list.c
index 134866d2c6..b29b4102e4 100644
--- a/src/lib/libcrypto/engine/eng_list.c
+++ b/src/lib/libcrypto/engine/eng_list.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: eng_list.c,v 1.23 2018/08/24 19:25:31 tb Exp $ */
+/* $OpenBSD: eng_list.c,v 1.24 2019/01/19 01:07:00 tb Exp $ */
 /* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
  * project 2000.
  */
@@ -315,6 +315,9 @@ engine_cpy(ENGINE *dest, const ENGINE *src)
 #endif
 #ifndef OPENSSL_NO_ECDSA
 	dest->ecdsa_meth = src->ecdsa_meth;
+#endif
+#ifndef OPENSSL_NO_EC
+	dest->ec_meth = src->ec_meth;
 #endif
 	dest->rand_meth = src->rand_meth;
 	dest->store_meth = src->store_meth;
diff --git a/src/lib/libcrypto/engine/engine.h b/src/lib/libcrypto/engine/engine.h
index 0f603feaaf..dc14be8e38 100644
--- a/src/lib/libcrypto/engine/engine.h
+++ b/src/lib/libcrypto/engine/engine.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: engine.h,v 1.32 2018/11/11 06:41:28 bcook Exp $ */
+/* $OpenBSD: engine.h,v 1.33 2019/01/19 01:07:00 tb Exp $ */
 /* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
  * project 2000.
  */
@@ -87,6 +87,9 @@
 #ifndef OPENSSL_NO_ECDSA
 #include <openssl/ecdsa.h>
 #endif
+#ifndef OPENSSL_NO_EC
+#include <openssl/ec.h>
+#endif
 #include <openssl/ui.h>
 #include <openssl/err.h>
 #endif
@@ -112,6 +115,7 @@ extern "C" {
 #define ENGINE_METHOD_STORE		(unsigned int)0x0100
 #define ENGINE_METHOD_PKEY_METHS	(unsigned int)0x0200
 #define ENGINE_METHOD_PKEY_ASN1_METHS	(unsigned int)0x0400
+#define ENGINE_METHOD_EC		(unsigned int)0x0800
 /* Obvious all-or-nothing cases. */
 #define ENGINE_METHOD_ALL		(unsigned int)0xFFFF
 #define ENGINE_METHOD_NONE		(unsigned int)0x0000
@@ -353,6 +357,10 @@ int ENGINE_register_ECDSA(ENGINE *e);
 void ENGINE_unregister_ECDSA(ENGINE *e);
 void ENGINE_register_all_ECDSA(void);
 
+int ENGINE_register_EC(ENGINE *e);
+void ENGINE_unregister_EC(ENGINE *e);
+void ENGINE_register_all_EC(void);
+
 int ENGINE_register_DH(ENGINE *e);
 void ENGINE_unregister_DH(ENGINE *e);
 void ENGINE_register_all_DH(void);
@@ -447,6 +455,7 @@ int ENGINE_set_RSA(ENGINE *e, const RSA_METHOD *rsa_meth);
 int ENGINE_set_DSA(ENGINE *e, const DSA_METHOD *dsa_meth);
 int ENGINE_set_ECDH(ENGINE *e, const ECDH_METHOD *ecdh_meth);
 int ENGINE_set_ECDSA(ENGINE *e, const ECDSA_METHOD *ecdsa_meth);
+int ENGINE_set_EC(ENGINE *e, const EC_KEY_METHOD *ec_meth);
 int ENGINE_set_DH(ENGINE *e, const DH_METHOD *dh_meth);
 int ENGINE_set_RAND(ENGINE *e, const RAND_METHOD *rand_meth);
 int ENGINE_set_STORE(ENGINE *e, const STORE_METHOD *store_meth);
@@ -486,6 +495,7 @@ const RSA_METHOD *ENGINE_get_RSA(const ENGINE *e);
 const DSA_METHOD *ENGINE_get_DSA(const ENGINE *e);
 const ECDH_METHOD *ENGINE_get_ECDH(const ENGINE *e);
 const ECDSA_METHOD *ENGINE_get_ECDSA(const ENGINE *e);
+const EC_KEY_METHOD *ENGINE_get_EC(const ENGINE *e);
 const DH_METHOD *ENGINE_get_DH(const ENGINE *e);
 const RAND_METHOD *ENGINE_get_RAND(const ENGINE *e);
 const STORE_METHOD *ENGINE_get_STORE(const ENGINE *e);
@@ -553,6 +563,7 @@ ENGINE *ENGINE_get_default_RSA(void);
 ENGINE *ENGINE_get_default_DSA(void);
 ENGINE *ENGINE_get_default_ECDH(void);
 ENGINE *ENGINE_get_default_ECDSA(void);
+ENGINE *ENGINE_get_default_EC(void);
 ENGINE *ENGINE_get_default_DH(void);
 ENGINE *ENGINE_get_default_RAND(void);
 /* These functions can be used to get a functional reference to perform
@@ -572,6 +583,7 @@ int ENGINE_set_default_string(ENGINE *e, const char *def_list);
 int ENGINE_set_default_DSA(ENGINE *e);
 int ENGINE_set_default_ECDH(ENGINE *e);
 int ENGINE_set_default_ECDSA(ENGINE *e);
+int ENGINE_set_default_EC(ENGINE *e);
 int ENGINE_set_default_DH(ENGINE *e);
 int ENGINE_set_default_RAND(ENGINE *e);
 int ENGINE_set_default_ciphers(ENGINE *e);
diff --git a/src/lib/libcrypto/engine/tb_eckey.c b/src/lib/libcrypto/engine/tb_eckey.c
new file mode 100644
index 0000000000..dd30815788
--- /dev/null
+++ b/src/lib/libcrypto/engine/tb_eckey.c
@@ -0,0 +1,123 @@
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "eng_int.h"
+
+static ENGINE_TABLE *ec_table = NULL;
+static const int dummy_nid = 1;
+
+void
+ENGINE_unregister_EC(ENGINE *e)
+{
+	engine_table_unregister(&ec_table, e);
+}
+
+static void
+engine_unregister_all_EC(void)
+{
+	engine_table_cleanup(&ec_table);
+}
+
+int
+ENGINE_register_EC(ENGINE *e)
+{
+	if (e->ec_meth)
+		return engine_table_register(&ec_table,
+		    engine_unregister_all_EC, e, &dummy_nid, 1, 0);
+	return 1;
+}
+
+void
+ENGINE_register_all_EC(void)
+{
+	ENGINE *e;
+
+	for (e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e))
+		ENGINE_register_EC(e);
+}
+
+int
+ENGINE_set_default_EC(ENGINE *e)
+{
+	if (e->ec_meth != NULL)
+		return engine_table_register(&ec_table,
+		    engine_unregister_all_EC, e, &dummy_nid, 1, 1);
+	return 1;
+}
+
+/*
+ * Exposed API function to get a functional reference from the implementation
+ * table (ie. try to get a functional reference from the tabled structural
+ * references).
+ */
+ENGINE *
+ENGINE_get_default_EC(void)
+{
+	return engine_table_select(&ec_table, dummy_nid);
+}
+
+/* Obtains an EC_KEY implementation from an ENGINE functional reference */
+const EC_KEY_METHOD *
+ENGINE_get_EC(const ENGINE *e)
+{
+	return e->ec_meth;
+}
+
+/* Sets an EC_KEY implementation in an ENGINE structure */
+int
+ENGINE_set_EC(ENGINE *e, const EC_KEY_METHOD *ec_meth)
+{
+	e->ec_meth = ec_meth;
+	return 1;
+}
-- 
cgit v1.2.3-55-g6feb