Add ECDH support.

Additional changes:
 - use EC_GROUP_get_degree() in apps/req.c
 - add ECDSA and ECDH to apps/speed.c
 - adds support for EC curves over binary fields to ECDSA
 - new function EC_KEY_up_ref() in crypto/ec/ec_key.c
 - reorganize crypto/ecdsa/ecdsatest.c
 - add engine support for ECDH
 - fix a few bugs in ECDSA engine support

Submitted by: Douglas Stebila <douglas.stebila@sun.com>
diff --git a/crypto/engine/Makefile.ssl b/crypto/engine/Makefile.ssl
index 1b3680b..4dab2dc 100644
--- a/crypto/engine/Makefile.ssl
+++ b/crypto/engine/Makefile.ssl
@@ -25,13 +25,13 @@
 LIB=$(TOP)/libcrypto.a
 LIBSRC= eng_err.c eng_lib.c eng_list.c eng_init.c eng_ctrl.c \
 	eng_table.c eng_pkey.c eng_fat.c eng_all.c \
-	tb_rsa.c tb_dsa.c tb_ecdsa.c tb_dh.c tb_rand.c tb_cipher.c tb_digest.c \
+	tb_rsa.c tb_dsa.c tb_ecdsa.c tb_dh.c tb_rand.c tb_cipher.c tb_digest.c tb_ecdh.c \
 	eng_openssl.c eng_dyn.c eng_cnf.c \
 	hw_atalla.c hw_cswift.c hw_ncipher.c hw_nuron.c hw_ubsec.c \
 	hw_openbsd_dev_crypto.c hw_aep.c hw_sureware.c hw_4758_cca.c
 LIBOBJ= eng_err.o eng_lib.o eng_list.o eng_init.o eng_ctrl.o \
 	eng_table.o eng_pkey.o eng_fat.o eng_all.o \
-	tb_rsa.o tb_dsa.o tb_ecdsa.o tb_dh.o tb_rand.o tb_cipher.o tb_digest.o \
+	tb_rsa.o tb_dsa.o tb_ecdsa.o tb_dh.o tb_rand.o tb_cipher.o tb_digest.o tb_ecdh.o \
 	eng_openssl.o eng_dyn.o eng_cnf.o \
 	hw_atalla.o hw_cswift.o hw_ncipher.o hw_nuron.o hw_ubsec.o \
 	hw_openbsd_dev_crypto.o hw_aep.o hw_sureware.o hw_4758_cca.o
@@ -540,6 +540,28 @@
 tb_dsa.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
 tb_dsa.o: ../../include/openssl/ui.h ../../include/openssl/ui_compat.h
 tb_dsa.o: eng_int.h tb_dsa.c
+tb_ecdh.o: ../../include/openssl/aes.h ../../include/openssl/asn1.h
+tb_ecdh.o: ../../include/openssl/asn1t.h ../../include/openssl/bio.h
+tb_ecdh.o: ../../include/openssl/blowfish.h ../../include/openssl/bn.h
+tb_ecdh.o: ../../include/openssl/cast.h ../../include/openssl/crypto.h
+tb_ecdh.o: ../../include/openssl/des.h ../../include/openssl/des_old.h
+tb_ecdh.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h
+tb_ecdh.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
+tb_ecdh.o: ../../include/openssl/ecdh.h ../../include/openssl/engine.h
+tb_ecdh.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+tb_ecdh.o: ../../include/openssl/idea.h ../../include/openssl/lhash.h
+tb_ecdh.o: ../../include/openssl/md2.h ../../include/openssl/md4.h
+tb_ecdh.o: ../../include/openssl/md5.h ../../include/openssl/mdc2.h
+tb_ecdh.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
+tb_ecdh.o: ../../include/openssl/opensslconf.h
+tb_ecdh.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+tb_ecdh.o: ../../include/openssl/rand.h ../../include/openssl/rc2.h
+tb_ecdh.o: ../../include/openssl/rc4.h ../../include/openssl/rc5.h
+tb_ecdh.o: ../../include/openssl/ripemd.h ../../include/openssl/rsa.h
+tb_ecdh.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
+tb_ecdh.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
+tb_ecdh.o: ../../include/openssl/ui.h ../../include/openssl/ui_compat.h
+tb_ecdh.o: eng_int.h tb_ecdh.c
 tb_ecdsa.o: ../../include/openssl/aes.h ../../include/openssl/asn1.h
 tb_ecdsa.o: ../../include/openssl/bio.h ../../include/openssl/blowfish.h
 tb_ecdsa.o: ../../include/openssl/bn.h ../../include/openssl/cast.h
diff --git a/crypto/engine/eng_fat.c b/crypto/engine/eng_fat.c
index f7edb5a..c0d03cc 100644
--- a/crypto/engine/eng_fat.c
+++ b/crypto/engine/eng_fat.c
@@ -52,6 +52,11 @@
  * Hudson (tjh@cryptsoft.com).
  *
  */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by 
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
 
 #include <openssl/crypto.h>
 #include "cryptlib.h"
@@ -77,6 +82,14 @@
 	if((flags & ENGINE_METHOD_DH) & !ENGINE_set_default_DH(e))
 		return 0;
 #endif
+#ifndef OPENSSL_NO_ECDH
+	if((flags & ENGINE_METHOD_ECDH) & !ENGINE_set_default_ECDH(e))
+		return 0;
+#endif
+#ifndef OPENSSL_NO_ECDSA
+	if((flags & ENGINE_METHOD_ECDSA) & !ENGINE_set_default_ECDSA(e))
+		return 0;
+#endif
 	if((flags & ENGINE_METHOD_RAND) & !ENGINE_set_default_RAND(e))
 		return 0;
 	return 1;
@@ -93,6 +106,10 @@
 		*pflags |= ENGINE_METHOD_RSA;
 	else if (!strncmp(alg, "DSA", len))
 		*pflags |= ENGINE_METHOD_DSA;
+	else if (!strncmp(alg, "ECDH", len))
+		*pflags |= ENGINE_METHOD_ECDH;
+	else if (!strncmp(alg, "ECDSA", len))
+		*pflags |= ENGINE_METHOD_ECDSA;
 	else if (!strncmp(alg, "DH", len))
 		*pflags |= ENGINE_METHOD_DH;
 	else if (!strncmp(alg, "RAND", len))
@@ -133,6 +150,12 @@
 #ifndef OPENSSL_NO_DH
 	ENGINE_register_DH(e);
 #endif
+#ifndef OPENSSL_NO_ECDH
+	ENGINE_register_ECDH(e);
+#endif
+#ifndef OPENSSL_NO_ECDSA
+	ENGINE_register_ECDSA(e);
+#endif
 	ENGINE_register_RAND(e);
 	return 1;
 	}
diff --git a/crypto/engine/eng_int.h b/crypto/engine/eng_int.h
index 0407de9..2c82861 100644
--- a/crypto/engine/eng_int.h
+++ b/crypto/engine/eng_int.h
@@ -55,6 +55,11 @@
  * Hudson (tjh@cryptsoft.com).
  *
  */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by 
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
 
 #ifndef HEADER_ENGINE_INT_H
 #define HEADER_ENGINE_INT_H
@@ -146,6 +151,7 @@
 	const RSA_METHOD *rsa_meth;
 	const DSA_METHOD *dsa_meth;
 	const DH_METHOD *dh_meth;
+	const ECDH_METHOD *ecdh_meth;
 	const ECDSA_METHOD *ecdsa_meth;
 	const RAND_METHOD *rand_meth;
 	/* Cipher handling is via this callback */
diff --git a/crypto/engine/eng_list.c b/crypto/engine/eng_list.c
index da53c1c..5018856 100644
--- a/crypto/engine/eng_list.c
+++ b/crypto/engine/eng_list.c
@@ -55,6 +55,11 @@
  * Hudson (tjh@cryptsoft.com).
  *
  */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by 
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
 
 #include <openssl/crypto.h>
 #include "cryptlib.h"
@@ -324,6 +329,9 @@
 #ifndef OPENSSL_NO_DH
 	dest->dh_meth = src->dh_meth;
 #endif
+#ifndef OPENSSL_NO_ECDH
+	dest->ecdh_meth = src->ecdh_meth;
+#endif
 #ifndef OPENSSL_NO_ECDSA
 	dest->ecdsa_meth = src->ecdsa_meth;
 #endif
diff --git a/crypto/engine/eng_openssl.c b/crypto/engine/eng_openssl.c
index e9d976f..45fa618 100644
--- a/crypto/engine/eng_openssl.c
+++ b/crypto/engine/eng_openssl.c
@@ -55,6 +55,11 @@
  * Hudson (tjh@cryptsoft.com).
  *
  */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by 
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
 
 
 #include <stdio.h>
@@ -109,6 +114,12 @@
 #ifndef OPENSSL_NO_DSA
 			|| !ENGINE_set_DSA(e, DSA_get_default_method())
 #endif
+#ifndef OPENSSL_NO_ECDH
+			|| !ENGINE_set_ECDH(e, ECDH_OpenSSL())
+#endif
+#ifndef OPENSSL_NO_ECDSA
+			|| !ENGINE_set_ECDSA(e, ECDSA_OpenSSL())
+#endif
 #ifndef OPENSSL_NO_DH
 			|| !ENGINE_set_DH(e, DH_get_default_method())
 #endif
diff --git a/crypto/engine/engine.h b/crypto/engine/engine.h
index 1cd27f8..50638d4 100644
--- a/crypto/engine/engine.h
+++ b/crypto/engine/engine.h
@@ -55,6 +55,11 @@
  * Hudson (tjh@cryptsoft.com).
  *
  */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by 
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
 
 #ifndef HEADER_ENGINE_H
 #define HEADER_ENGINE_H
@@ -70,6 +75,9 @@
 #ifndef OPENSSL_NO_DH
 #include <openssl/dh.h>
 #endif
+#ifndef OPENSSL_NO_ECDH
+#include <openssl/ecdh.h>
+#endif
 #ifndef OPENSSL_NO_ECDSA
 #include <openssl/ecdsa.h>
 #endif
@@ -92,6 +100,9 @@
 #ifdef OPENSSL_NO_DH
 typedef void DH_METHOD;
 #endif
+#ifdef OPENSSL_NO_ECDH
+typedef void ECDH_METHOD;
+#endif
 #ifdef OPENSSL_NO_ECDSA
 typedef void ECDSA_METHOD;
 #endif
@@ -102,7 +113,8 @@
 #define ENGINE_METHOD_DSA		(unsigned int)0x0002
 #define ENGINE_METHOD_DH		(unsigned int)0x0004
 #define ENGINE_METHOD_RAND		(unsigned int)0x0008
-#define ENGINE_METHOD_ECDSA		(unsigned int)0x000F
+#define ENGINE_METHOD_ECDH		(unsigned int)0x0010
+#define ENGINE_METHOD_ECDSA		(unsigned int)0x0020
 #define ENGINE_METHOD_CIPHERS		(unsigned int)0x0040
 #define ENGINE_METHOD_DIGESTS		(unsigned int)0x0080
 /* Obvious all-or-nothing cases. */
@@ -338,6 +350,10 @@
 void ENGINE_unregister_DSA(ENGINE *e);
 void ENGINE_register_all_DSA(void);
 
+int ENGINE_register_ECDH(ENGINE *e);
+void ENGINE_unregister_ECDH(ENGINE *e);
+void ENGINE_register_all_ECDH(void);
+
 int ENGINE_register_ECDSA(ENGINE *e);
 void ENGINE_unregister_ECDSA(ENGINE *e);
 void ENGINE_register_all_ECDSA(void);
@@ -421,6 +437,7 @@
 int ENGINE_set_name(ENGINE *e, const char *name);
 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_DH(ENGINE *e, const DH_METHOD *dh_meth);
 int ENGINE_set_RAND(ENGINE *e, const RAND_METHOD *rand_meth);
@@ -454,6 +471,7 @@
 const char *ENGINE_get_name(const ENGINE *e);
 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 DH_METHOD *ENGINE_get_DH(const ENGINE *e);
 const RAND_METHOD *ENGINE_get_RAND(const ENGINE *e);
@@ -507,6 +525,7 @@
 ENGINE *ENGINE_get_default_RSA(void);
 /* Same for the other "methods" */
 ENGINE *ENGINE_get_default_DSA(void);
+ENGINE *ENGINE_get_default_ECDH(void);
 ENGINE *ENGINE_get_default_ECDSA(void);
 ENGINE *ENGINE_get_default_DH(void);
 ENGINE *ENGINE_get_default_RAND(void);
@@ -523,6 +542,7 @@
 int ENGINE_set_default_string(ENGINE *e, const char *list);
 /* Same for the other "methods" */
 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_DH(ENGINE *e);
 int ENGINE_set_default_RAND(ENGINE *e);