Adding SSL_set_cipher_lists and turning on elliptic curve

Summary:
- adding SSL_set_cipher_lists for JSSE support
- enabling elliptic curve for new JSSE cipher suites

Details:

Adding SSL_set_cipher_lists that allows setting of SSL ciphers (and
indirectly ciphers_by_id). This allows us to explicitly set a desired
cipher suite lists with our own ordering for JSSE support.

	patches/jsse.patch

Enabling EC, ECDH, and ECDSA which are needed for RI 6 elliptic curve cipher suites.
- EC    = Elliptic Curve
- ECDH  = Elliptic Curve Diffie-Hellman
- ECDSA = Elliptic Curve Digital Signature Algorithm

	android-config.mk
	patches/apps_Android.mk
	patches/crypto_Android.mk
	openssl.config

Remove warning from openssl output to remove testssl warnings

	patches/progs.patch
	openssl.config

Misc

   Update clean, build, and test instructions

	README.android

   Fixing whitespace inconsistency noted when updating clean target

	patches/ssl_Android.mk

Generated files

   Copied from patches:

	apps/Android.mk
	crypto/Android.mk
	ssl/Android.mk

   Newly imported EC files from openssl-1.0.0.tar.gz
   Interestingly most of the needed files were already present, if not compiled.

	crypto/ec/ec_ameth.c
	crypto/ec/ec_pmeth.c
	crypto/ec/eck_prn.c

   SSL_set_cipher_lists

	include/openssl/ssl.h
	ssl/ssl.h
	ssl/ssl_lib.c

   Disabled warning

	apps/openssl.c

Change-Id: I1d75f64b64e03f7bfb45456876b60ebbf3a09de5
diff --git a/README.android b/README.android
index f6b92c3..6232aa1 100644
--- a/README.android
+++ b/README.android
@@ -38,11 +38,11 @@
 
 5) Cleanup before building with:
 
-     m -j16 clean-openssl clean-libcrypto clean-libssl
+     m -j16 clean-libcrypto clean-libssl clean-openssl clean-ssltest
 
 6) Build openssl from the external/openssl directory with:
 
-     mm -j16
+     mm -j16 snod && adb sync system
 
    If there are build errors, then patches/*.mk, openssl.config, or
    android-config.mk may need updating.
diff --git a/android-config.mk b/android-config.mk
index a28e35d..0597a42 100644
--- a/android-config.mk
+++ b/android-config.mk
@@ -11,4 +11,4 @@
 LOCAL_CFLAGS += -DOPENSSL_NO_BF -DOPENSSL_NO_CAMELLIA -DOPENSSL_NO_CAPIENG -DOPENSSL_NO_CAST -DOPENSSL_NO_CMS -DOPENSSL_NO_GMP -DOPENSSL_NO_IDEA -DOPENSSL_NO_JPAKE -DOPENSSL_NO_MD2 -DOPENSSL_NO_MDC2 -DOPENSSL_NO_RC5 -DOPENSSL_NO_RFC3779 -DOPENSSL_NO_SEED -DOPENSSL_NO_STORE -DOPENSSL_NO_WHIRLPOOL
 
 # Extra
-LOCAL_CFLAGS += -DOPENSSL_NO_HW -DOPENSSL_NO_ENGINE -DOPENSSL_NO_EC -DOPENSSL_NO_ECDH -DOPENSSL_NO_ECDSA -DZLIB
+LOCAL_CFLAGS += -DOPENSSL_NO_HW -DOPENSSL_NO_ENGINE -DZLIB
diff --git a/apps/Android.mk b/apps/Android.mk
index a908806..e9f215c 100644
--- a/apps/Android.mk
+++ b/apps/Android.mk
@@ -17,6 +17,7 @@
 	dsa.c \
 	dsaparam.c \
 	ecparam.c \
+	ec.c \
 	enc.c \
 	engine.c \
 	errstr.c \
@@ -64,7 +65,7 @@
 
 # These flags omit whole features from the commandline "openssl".
 # However, portions of these features are actually turned on.
-LOCAL_CFLAGS += -DOPENSSL_NO_EC -DOPENSSL_NO_ECDSA -DOPENSSL_NO_DTLS1
+LOCAL_CFLAGS += -DOPENSSL_NO_DTLS1
 
 
 LOCAL_MODULE:= openssl
diff --git a/apps/openssl.c b/apps/openssl.c
index 851e639..be37ee6 100644
--- a/apps/openssl.c
+++ b/apps/openssl.c
@@ -275,8 +275,10 @@
 		if (ERR_GET_REASON(ERR_peek_last_error())
 		    == CONF_R_NO_SUCH_FILE)
 			{
+#if 0 /* ANDROID */
 			BIO_printf(bio_err,
 				   "WARNING: can't open config file: %s\n",p);
+#endif
 			ERR_clear_error();
 			NCONF_free(config);
 			config = NULL;
diff --git a/crypto/Android.mk b/crypto/Android.mk
index 14bac8e..cb2dfd4 100644
--- a/crypto/Android.mk
+++ b/crypto/Android.mk
@@ -226,6 +226,33 @@
 	dso/dso_openssl.c \
 	dso/dso_vms.c \
 	dso/dso_win32.c \
+	ec/ec2_mult.c \
+	ec/ec2_smpl.c \
+	ec/ec_ameth.c \
+	ec/ec_asn1.c \
+	ec/ec_check.c \
+	ec/ec_curve.c \
+	ec/ec_cvt.c \
+	ec/ec_err.c \
+	ec/ec_key.c \
+	ec/ec_lib.c \
+	ec/ec_mult.c \
+	ec/ec_pmeth.c \
+	ec/ec_print.c \
+	ec/eck_prn.c \
+	ec/ecp_mont.c \
+	ec/ecp_nist.c \
+	ec/ecp_smpl.c \
+	ecdh/ech_err.c \
+	ecdh/ech_key.c \
+	ecdh/ech_lib.c \
+	ecdh/ech_ossl.c \
+	ecdsa/ecs_asn1.c \
+	ecdsa/ecs_err.c \
+	ecdsa/ecs_lib.c \
+	ecdsa/ecs_ossl.c \
+	ecdsa/ecs_sign.c \
+	ecdsa/ecs_vrf.c \
 	err/err.c \
 	err/err_all.c \
 	err/err_prn.c \
@@ -256,6 +283,7 @@
 	evp/evp_pkey.c \
 	evp/m_dss.c \
 	evp/m_dss1.c \
+	evp/m_ecdsa.c \
 	evp/m_md2.c \
 	evp/m_md4.c \
 	evp/m_md5.c \
diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c
new file mode 100644
index 0000000..c00f7d7
--- /dev/null
+++ b/crypto/ec/ec_ameth.c
@@ -0,0 +1,659 @@
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 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 <stdio.h>
+#include "cryptlib.h"
+#include <openssl/x509.h>
+#include <openssl/ec.h>
+#include <openssl/bn.h>
+#ifndef OPENSSL_NO_CMS
+#include <openssl/cms.h>
+#endif
+#include "asn1_locl.h"
+
+static int eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key)
+	{
+	const EC_GROUP  *group;
+	int nid;
+	if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) 
+	{
+		ECerr(EC_F_ECKEY_PARAM2TYPE, EC_R_MISSING_PARAMETERS);
+		return 0;
+	}
+	if (EC_GROUP_get_asn1_flag(group)
+                     && (nid = EC_GROUP_get_curve_name(group)))
+		/* we have a 'named curve' => just set the OID */
+		{
+		*ppval = OBJ_nid2obj(nid);
+		*pptype = V_ASN1_OBJECT;
+		}
+	else	/* explicit parameters */
+		{
+		ASN1_STRING *pstr = NULL;
+		pstr = ASN1_STRING_new();
+		if (!pstr)
+			return 0;
+		pstr->length = i2d_ECParameters(ec_key, &pstr->data);
+		if (pstr->length < 0)
+			{
+			ASN1_STRING_free(pstr);
+			ECerr(EC_F_ECKEY_PARAM2TYPE, ERR_R_EC_LIB);
+			return 0;
+			}
+		*ppval = pstr;
+		*pptype = V_ASN1_SEQUENCE;
+		}
+	return 1;
+	}
+
+static int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
+	{
+	EC_KEY *ec_key = pkey->pkey.ec;
+	void *pval = NULL;
+	int ptype;
+	unsigned char *penc = NULL, *p;
+	int penclen;
+
+	if (!eckey_param2type(&ptype, &pval, ec_key))
+		{
+		ECerr(EC_F_ECKEY_PUB_ENCODE, ERR_R_EC_LIB);
+		return 0;
+		}
+	penclen = i2o_ECPublicKey(ec_key, NULL);
+	if (penclen <= 0)
+		goto err;
+	penc = OPENSSL_malloc(penclen);
+	if (!penc)
+		goto err;
+	p = penc;
+	penclen = i2o_ECPublicKey(ec_key, &p);
+	if (penclen <= 0)
+		goto err;
+	if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_EC),
+				ptype, pval, penc, penclen))
+		return 1;
+	err:
+	if (ptype == V_ASN1_OBJECT)
+		ASN1_OBJECT_free(pval);
+	else
+		ASN1_STRING_free(pval);
+	if (penc)
+		OPENSSL_free(penc);
+	return 0;
+	}
+
+static EC_KEY *eckey_type2param(int ptype, void *pval)
+	{
+	EC_KEY *eckey = NULL;
+	if (ptype == V_ASN1_SEQUENCE)
+		{
+		ASN1_STRING *pstr = pval;
+		const unsigned char *pm = NULL;
+		int pmlen;
+		pm = pstr->data;
+		pmlen = pstr->length;
+		if (!(eckey = d2i_ECParameters(NULL, &pm, pmlen)))
+			{
+			ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR);
+			goto ecerr;
+			}
+		}
+	else if (ptype == V_ASN1_OBJECT)
+		{
+		ASN1_OBJECT *poid = pval;
+		EC_GROUP *group;
+
+		/* type == V_ASN1_OBJECT => the parameters are given
+		 * by an asn1 OID
+		 */
+		if ((eckey = EC_KEY_new()) == NULL)
+			{
+			ECerr(EC_F_ECKEY_TYPE2PARAM, ERR_R_MALLOC_FAILURE);
+			goto ecerr;
+			}
+		group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(poid));
+		if (group == NULL)
+			goto ecerr;
+		EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
+		if (EC_KEY_set_group(eckey, group) == 0)
+			goto ecerr;
+		EC_GROUP_free(group);
+		}
+	else
+		{
+		ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR);
+		goto ecerr;
+		}
+
+	return eckey;
+
+	ecerr:
+	if (eckey)
+		EC_KEY_free(eckey);
+	return NULL;
+	}
+
+static int eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
+	{
+	const unsigned char *p = NULL;
+	void *pval;
+	int ptype, pklen;
+	EC_KEY *eckey = NULL;
+	X509_ALGOR *palg;
+
+	if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
+		return 0;
+	X509_ALGOR_get0(NULL, &ptype, &pval, palg);
+
+	eckey = eckey_type2param(ptype, pval);
+
+	if (!eckey)
+		{
+		ECerr(EC_F_ECKEY_PUB_DECODE, ERR_R_EC_LIB);
+		return 0;
+		}
+
+	/* We have parameters now set public key */
+	if (!o2i_ECPublicKey(&eckey, &p, pklen))
+		{
+		ECerr(EC_F_ECKEY_PUB_DECODE, EC_R_DECODE_ERROR);
+		goto ecerr;
+		}
+
+	EVP_PKEY_assign_EC_KEY(pkey, eckey);
+	return 1;
+
+	ecerr:
+	if (eckey)
+		EC_KEY_free(eckey);
+	return 0;
+	}
+
+static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
+	{
+	int  r;
+	const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec);
+	const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec),
+	               *pb = EC_KEY_get0_public_key(b->pkey.ec);
+	r = EC_POINT_cmp(group, pa, pb, NULL);
+	if (r == 0)
+		return 1;
+	if (r == 1)
+		return 0;
+	return -2;
+	}
+
+static int eckey_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
+	{
+	const unsigned char *p = NULL;
+	void *pval;
+	int ptype, pklen;
+	EC_KEY *eckey = NULL;
+	X509_ALGOR *palg;
+
+	if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
+		return 0;
+	X509_ALGOR_get0(NULL, &ptype, &pval, palg);
+
+	eckey = eckey_type2param(ptype, pval);
+
+	if (!eckey)
+		goto ecliberr;
+
+	/* We have parameters now set private key */
+	if (!d2i_ECPrivateKey(&eckey, &p, pklen))
+		{
+		ECerr(EC_F_ECKEY_PRIV_DECODE, EC_R_DECODE_ERROR);
+		goto ecerr;
+		}
+
+	/* calculate public key (if necessary) */
+	if (EC_KEY_get0_public_key(eckey) == NULL)
+		{
+		const BIGNUM *priv_key;
+		const EC_GROUP *group;
+		EC_POINT *pub_key;
+		/* the public key was not included in the SEC1 private
+		 * key => calculate the public key */
+		group   = EC_KEY_get0_group(eckey);
+		pub_key = EC_POINT_new(group);
+		if (pub_key == NULL)
+			{
+			ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
+			goto ecliberr;
+			}
+		if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group)))
+			{
+			EC_POINT_free(pub_key);
+			ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
+			goto ecliberr;
+			}
+		priv_key = EC_KEY_get0_private_key(eckey);
+		if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL))
+			{
+			EC_POINT_free(pub_key);
+			ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
+			goto ecliberr;
+			}
+		if (EC_KEY_set_public_key(eckey, pub_key) == 0)
+			{
+			EC_POINT_free(pub_key);
+			ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
+			goto ecliberr;
+			}
+		EC_POINT_free(pub_key);
+		}
+
+	EVP_PKEY_assign_EC_KEY(pkey, eckey);
+	return 1;
+
+	ecliberr:
+	ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
+	ecerr:
+	if (eckey)
+		EC_KEY_free(eckey);
+	return 0;
+	}
+
+static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
+{
+	EC_KEY		*ec_key;
+	unsigned char	*ep, *p;
+	int 		eplen, ptype;
+	void		*pval;
+	unsigned int    tmp_flags, old_flags;
+
+	ec_key = pkey->pkey.ec;
+
+	if (!eckey_param2type(&ptype, &pval, ec_key))
+		{
+		ECerr(EC_F_ECKEY_PRIV_ENCODE, EC_R_DECODE_ERROR);
+		return 0;
+		}
+
+	/* set the private key */
+
+	/* do not include the parameters in the SEC1 private key
+	 * see PKCS#11 12.11 */
+	old_flags = EC_KEY_get_enc_flags(ec_key);
+	tmp_flags = old_flags | EC_PKEY_NO_PARAMETERS;
+	EC_KEY_set_enc_flags(ec_key, tmp_flags);
+	eplen = i2d_ECPrivateKey(ec_key, NULL);
+	if (!eplen)
+	{
+		EC_KEY_set_enc_flags(ec_key, old_flags);
+		ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB);
+		return 0;
+	}
+	ep = (unsigned char *) OPENSSL_malloc(eplen);
+	if (!ep)
+	{
+		EC_KEY_set_enc_flags(ec_key, old_flags);
+		ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	p = ep;
+	if (!i2d_ECPrivateKey(ec_key, &p))
+	{
+		EC_KEY_set_enc_flags(ec_key, old_flags);
+		OPENSSL_free(ep);
+		ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB);
+	}
+	/* restore old encoding flags */
+	EC_KEY_set_enc_flags(ec_key, old_flags);
+
+	if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0,
+				ptype, pval, ep, eplen))
+		return 0;
+
+	return 1;
+}
+
+static int int_ec_size(const EVP_PKEY *pkey)
+	{
+	return ECDSA_size(pkey->pkey.ec);
+	}
+
+static int ec_bits(const EVP_PKEY *pkey)
+	{
+	BIGNUM *order = BN_new();
+	const EC_GROUP *group;
+	int ret;
+
+	if (!order)
+		{
+		ERR_clear_error();
+		return 0;
+		}
+	group = EC_KEY_get0_group(pkey->pkey.ec);
+	if (!EC_GROUP_get_order(group, order, NULL))
+		{
+		ERR_clear_error();
+		return 0;
+		}
+
+	ret = BN_num_bits(order);
+	BN_free(order);
+	return ret;
+	}
+
+static int ec_missing_parameters(const EVP_PKEY *pkey)
+	{
+	if (EC_KEY_get0_group(pkey->pkey.ec) == NULL)
+		return 1;
+	return 0;
+	}
+
+static int ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
+	{
+	EC_GROUP *group = EC_GROUP_dup(EC_KEY_get0_group(from->pkey.ec));
+	if (group == NULL)
+		return 0;
+	if (EC_KEY_set_group(to->pkey.ec, group) == 0)
+		return 0;
+	EC_GROUP_free(group);
+	return 1;
+	}
+
+static int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
+	{
+	const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec),
+	               *group_b = EC_KEY_get0_group(b->pkey.ec);
+	if (EC_GROUP_cmp(group_a, group_b, NULL))
+		return 0;
+	else
+		return 1;
+	}
+
+static void int_ec_free(EVP_PKEY *pkey)
+	{
+	EC_KEY_free(pkey->pkey.ec);
+	}
+
+static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype)
+	{
+	unsigned char *buffer=NULL;
+	const char *ecstr;
+	size_t	buf_len=0, i;
+	int     ret=0, reason=ERR_R_BIO_LIB;
+	BIGNUM  *pub_key=NULL, *order=NULL;
+	BN_CTX  *ctx=NULL;
+	const EC_GROUP *group;
+	const EC_POINT *public_key;
+	const BIGNUM *priv_key;
+ 
+	if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL)
+		{
+		reason = ERR_R_PASSED_NULL_PARAMETER;
+		goto err;
+		}
+
+	ctx = BN_CTX_new();
+	if (ctx == NULL)
+		{
+		reason = ERR_R_MALLOC_FAILURE;
+		goto err;
+		}
+
+	if (ktype > 0)
+		{
+		public_key = EC_KEY_get0_public_key(x);
+		if ((pub_key = EC_POINT_point2bn(group, public_key,
+			EC_KEY_get_conv_form(x), NULL, ctx)) == NULL)
+			{
+			reason = ERR_R_EC_LIB;
+			goto err;
+			}
+		if (pub_key)
+			buf_len = (size_t)BN_num_bytes(pub_key);
+		}
+
+	if (ktype == 2)
+		{
+		priv_key = EC_KEY_get0_private_key(x);
+		if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len)
+			buf_len = i;
+		}
+	else
+		priv_key = NULL;
+
+	if (ktype > 0)
+		{
+		buf_len += 10;
+		if ((buffer = OPENSSL_malloc(buf_len)) == NULL)
+			{
+			reason = ERR_R_MALLOC_FAILURE;
+			goto err;
+			}
+		}
+	if (ktype == 2)
+		ecstr = "Private-Key";
+	else if (ktype == 1)
+		ecstr = "Public-Key";
+	else
+		ecstr = "ECDSA-Parameters";
+
+	if (!BIO_indent(bp, off, 128))
+		goto err;
+	if ((order = BN_new()) == NULL)
+		goto err;
+	if (!EC_GROUP_get_order(group, order, NULL))
+		goto err;
+	if (BIO_printf(bp, "%s: (%d bit)\n", ecstr,
+		BN_num_bits(order)) <= 0) goto err;
+  
+	if ((priv_key != NULL) && !ASN1_bn_print(bp, "priv:", priv_key, 
+		buffer, off))
+		goto err;
+	if ((pub_key != NULL) && !ASN1_bn_print(bp, "pub: ", pub_key,
+		buffer, off))
+		goto err;
+	if (!ECPKParameters_print(bp, group, off))
+		goto err;
+	ret=1;
+err:
+	if (!ret)
+ 		ECerr(EC_F_DO_EC_KEY_PRINT, reason);
+	if (pub_key) 
+		BN_free(pub_key);
+	if (order)
+		BN_free(order);
+	if (ctx)
+		BN_CTX_free(ctx);
+	if (buffer != NULL)
+		OPENSSL_free(buffer);
+	return(ret);
+	}
+
+static int eckey_param_decode(EVP_PKEY *pkey,
+					const unsigned char **pder, int derlen)
+	{
+	EC_KEY *eckey;
+	if (!(eckey = d2i_ECParameters(NULL, pder, derlen)))
+		{
+		ECerr(EC_F_ECKEY_PARAM_DECODE, ERR_R_EC_LIB);
+		return 0;
+		}
+	EVP_PKEY_assign_EC_KEY(pkey, eckey);
+	return 1;
+	}
+
+static int eckey_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
+	{
+	return i2d_ECParameters(pkey->pkey.ec, pder);
+	}
+
+static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+							ASN1_PCTX *ctx)
+	{
+	return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0);
+	}
+
+static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+							ASN1_PCTX *ctx)
+	{
+	return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1);
+	}
+
+
+static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+							ASN1_PCTX *ctx)
+	{
+	return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2);
+	}
+
+static int old_ec_priv_decode(EVP_PKEY *pkey,
+					const unsigned char **pder, int derlen)
+	{
+	EC_KEY *ec;
+	if (!(ec = d2i_ECPrivateKey (NULL, pder, derlen)))
+		{
+		ECerr(EC_F_OLD_EC_PRIV_DECODE, EC_R_DECODE_ERROR);
+		return 0;
+		}
+	EVP_PKEY_assign_EC_KEY(pkey, ec);
+	return 1;
+	}
+
+static int old_ec_priv_encode(const EVP_PKEY *pkey, unsigned char **pder)
+	{
+	return i2d_ECPrivateKey(pkey->pkey.ec, pder);
+	}
+
+static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
+	{
+	switch (op)
+		{
+		case ASN1_PKEY_CTRL_PKCS7_SIGN:
+		if (arg1 == 0)
+			{
+			int snid, hnid;
+			X509_ALGOR *alg1, *alg2;
+			PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
+			if (alg1 == NULL || alg1->algorithm == NULL)
+				return -1;
+			hnid = OBJ_obj2nid(alg1->algorithm);
+			if (hnid == NID_undef)
+				return -1;
+			if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
+				return -1; 
+			X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
+			}
+		return 1;
+#ifndef OPENSSL_NO_CMS
+		case ASN1_PKEY_CTRL_CMS_SIGN:
+		if (arg1 == 0)
+			{
+			int snid, hnid;
+			X509_ALGOR *alg1, *alg2;
+			CMS_SignerInfo_get0_algs(arg2, NULL, NULL,
+								&alg1, &alg2);
+			if (alg1 == NULL || alg1->algorithm == NULL)
+				return -1;
+			hnid = OBJ_obj2nid(alg1->algorithm);
+			if (hnid == NID_undef)
+				return -1;
+			if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
+				return -1; 
+			X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
+			}
+		return 1;
+#endif
+
+		case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
+		*(int *)arg2 = NID_sha1;
+		return 2;
+
+		default:
+		return -2;
+
+		}
+
+	}
+
+const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = 
+	{
+	EVP_PKEY_EC,
+	EVP_PKEY_EC,
+	0,
+	"EC",
+	"OpenSSL EC algorithm",
+
+	eckey_pub_decode,
+	eckey_pub_encode,
+	eckey_pub_cmp,
+	eckey_pub_print,
+
+	eckey_priv_decode,
+	eckey_priv_encode,
+	eckey_priv_print,
+
+	int_ec_size,
+	ec_bits,
+
+	eckey_param_decode,
+	eckey_param_encode,
+	ec_missing_parameters,
+	ec_copy_parameters,
+	ec_cmp_parameters,
+	eckey_param_print,
+
+	int_ec_free,
+	ec_pkey_ctrl,
+	old_ec_priv_decode,
+	old_ec_priv_encode
+	};
diff --git a/crypto/ec/ec_pmeth.c b/crypto/ec/ec_pmeth.c
new file mode 100644
index 0000000..f433076
--- /dev/null
+++ b/crypto/ec/ec_pmeth.c
@@ -0,0 +1,340 @@
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 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 <stdio.h>
+#include "cryptlib.h"
+#include <openssl/asn1t.h>
+#include <openssl/x509.h>
+#include <openssl/ec.h>
+#include <openssl/ecdsa.h>
+#include <openssl/evp.h>
+#include "evp_locl.h"
+
+/* EC pkey context structure */
+
+typedef struct
+	{
+	/* Key and paramgen group */
+	EC_GROUP *gen_group;
+	/* message digest */
+	const EVP_MD *md;
+	} EC_PKEY_CTX;
+
+static int pkey_ec_init(EVP_PKEY_CTX *ctx)
+	{
+	EC_PKEY_CTX *dctx;
+	dctx = OPENSSL_malloc(sizeof(EC_PKEY_CTX));
+	if (!dctx)
+		return 0;
+	dctx->gen_group = NULL;
+	dctx->md = NULL;
+
+	ctx->data = dctx;
+
+	return 1;
+	}
+
+static int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
+	{
+	EC_PKEY_CTX *dctx, *sctx;
+	if (!pkey_ec_init(dst))
+		return 0;
+       	sctx = src->data;
+	dctx = dst->data;
+	if (sctx->gen_group)
+		{
+		dctx->gen_group = EC_GROUP_dup(sctx->gen_group);
+		if (!dctx->gen_group)
+			return 0;
+		}
+	dctx->md = sctx->md;
+	return 1;
+	}
+
+static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx)
+	{
+	EC_PKEY_CTX *dctx = ctx->data;
+	if (dctx)
+		{
+		if (dctx->gen_group)
+			EC_GROUP_free(dctx->gen_group);
+		OPENSSL_free(dctx);
+		}
+	}
+
+static int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
+					const unsigned char *tbs, size_t tbslen)
+	{
+	int ret, type;
+	unsigned int sltmp;
+	EC_PKEY_CTX *dctx = ctx->data;
+	EC_KEY *ec = ctx->pkey->pkey.ec;
+
+	if (!sig)
+		{
+		*siglen = ECDSA_size(ec);
+		return 1;
+		}
+	else if(*siglen < (size_t)ECDSA_size(ec))
+		{
+		ECerr(EC_F_PKEY_EC_SIGN, EC_R_BUFFER_TOO_SMALL);
+		return 0;
+		}
+
+	if (dctx->md)
+		type = EVP_MD_type(dctx->md);
+	else
+		type = NID_sha1;
+
+
+	ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec);
+
+	if (ret <= 0)
+		return ret;
+	*siglen = (size_t)sltmp;
+	return 1;
+	}
+
+static int pkey_ec_verify(EVP_PKEY_CTX *ctx,
+					const unsigned char *sig, size_t siglen,
+					const unsigned char *tbs, size_t tbslen)
+	{
+	int ret, type;
+	EC_PKEY_CTX *dctx = ctx->data;
+	EC_KEY *ec = ctx->pkey->pkey.ec;
+
+	if (dctx->md)
+		type = EVP_MD_type(dctx->md);
+	else
+		type = NID_sha1;
+
+	ret = ECDSA_verify(type, tbs, tbslen, sig, siglen, ec);
+
+	return ret;
+	}
+
+static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
+	{
+	int ret;
+	size_t outlen;
+	const EC_POINT *pubkey = NULL;
+	if (!ctx->pkey || !ctx->peerkey)
+		{
+		ECerr(EC_F_PKEY_EC_DERIVE, EC_R_KEYS_NOT_SET);
+		return 0;
+		}
+
+	if (!key)
+		{
+		const EC_GROUP *group;
+		group = EC_KEY_get0_group(ctx->pkey->pkey.ec);
+		*keylen = (EC_GROUP_get_degree(group) + 7)/8;
+		return 1;
+		}
+
+	pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec);
+
+	/* NB: unlike PKS#3 DH, if *outlen is less than maximum size this is
+	 * not an error, the result is truncated.
+	 */
+
+	outlen = *keylen;
+		
+	ret = ECDH_compute_key(key, outlen, pubkey, ctx->pkey->pkey.ec, 0);
+	if (ret < 0)
+		return ret;
+	*keylen = ret;
+	return 1;
+	}
+
+static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
+	{
+	EC_PKEY_CTX *dctx = ctx->data;
+	EC_GROUP *group;
+	switch (type)
+		{
+		case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID:
+		group = EC_GROUP_new_by_curve_name(p1);
+		if (group == NULL)
+			{
+			ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_CURVE);
+			return 0;
+			}
+		if (dctx->gen_group)
+			EC_GROUP_free(dctx->gen_group);
+		dctx->gen_group = group;
+		return 1;
+
+		case EVP_PKEY_CTRL_MD:
+		if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 &&
+		    EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
+		    EVP_MD_type((const EVP_MD *)p2) != NID_sha256 &&
+		    EVP_MD_type((const EVP_MD *)p2) != NID_sha384 &&
+		    EVP_MD_type((const EVP_MD *)p2) != NID_sha512)
+			{
+			ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE);
+			return 0;
+			}
+		dctx->md = p2;
+		return 1;
+
+		case EVP_PKEY_CTRL_PEER_KEY:
+		/* Default behaviour is OK */
+		case EVP_PKEY_CTRL_DIGESTINIT:
+		case EVP_PKEY_CTRL_PKCS7_SIGN:
+		case EVP_PKEY_CTRL_CMS_SIGN:
+		return 1;
+
+		default:
+		return -2;
+
+		}
+	}
+			
+static int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx,
+			const char *type, const char *value)
+	{
+	if (!strcmp(type, "ec_paramgen_curve"))
+		{
+		int nid;
+		nid = OBJ_sn2nid(value);
+		if (nid == NID_undef)
+			nid = OBJ_ln2nid(value);
+		if (nid == NID_undef)
+			{
+			ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_CURVE);
+			return 0;
+			}
+		return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid);
+		}
+	return -2;
+	}
+
+static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+	{
+	EC_KEY *ec = NULL;
+	EC_PKEY_CTX *dctx = ctx->data;
+	int ret = 0;
+	if (dctx->gen_group == NULL)
+		{
+		ECerr(EC_F_PKEY_EC_PARAMGEN, EC_R_NO_PARAMETERS_SET);
+		return 0;
+		}
+	ec = EC_KEY_new();
+	if (!ec)
+		return 0;
+	ret = EC_KEY_set_group(ec, dctx->gen_group);
+	if (ret)
+		EVP_PKEY_assign_EC_KEY(pkey, ec);
+	else
+		EC_KEY_free(ec);
+	return ret;
+	}
+
+static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+	{
+	EC_KEY *ec = NULL;
+	if (ctx->pkey == NULL)
+		{
+		ECerr(EC_F_PKEY_EC_KEYGEN, EC_R_NO_PARAMETERS_SET);
+		return 0;
+		}
+	ec = EC_KEY_new();
+	if (!ec)
+		return 0;
+	EVP_PKEY_assign_EC_KEY(pkey, ec);
+	/* Note: if error return, pkey is freed by parent routine */
+	if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey))
+		return 0;
+	return EC_KEY_generate_key(pkey->pkey.ec);
+	}
+
+const EVP_PKEY_METHOD ec_pkey_meth = 
+	{
+	EVP_PKEY_EC,
+	0,
+	pkey_ec_init,
+	pkey_ec_copy,
+	pkey_ec_cleanup,
+
+	0,
+	pkey_ec_paramgen,
+
+	0,
+	pkey_ec_keygen,
+
+	0,
+	pkey_ec_sign,
+
+	0,
+	pkey_ec_verify,
+
+	0,0,
+
+	0,0,0,0,
+
+	0,0,
+
+	0,0,
+
+	0,
+	pkey_ec_derive,
+
+	pkey_ec_ctrl,
+	pkey_ec_ctrl_str
+
+	};
diff --git a/crypto/ec/eck_prn.c b/crypto/ec/eck_prn.c
new file mode 100644
index 0000000..7d3e175
--- /dev/null
+++ b/crypto/ec/eck_prn.c
@@ -0,0 +1,391 @@
+/* crypto/ec/eck_prn.c */
+/*
+ * Written by Nils Larsch for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2005 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
+ *    openssl-core@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).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * Portions originally developed by SUN MICROSYSTEMS, INC., and 
+ * contributed to the OpenSSL project.
+ */
+
+#include <stdio.h>
+#include "cryptlib.h"
+#include <openssl/evp.h>
+#include <openssl/ec.h>
+#include <openssl/bn.h>
+
+#ifndef OPENSSL_NO_FP_API
+int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off)
+	{
+	BIO *b;
+	int ret;
+
+	if ((b=BIO_new(BIO_s_file())) == NULL)
+		{
+		ECerr(EC_F_ECPKPARAMETERS_PRINT_FP,ERR_R_BUF_LIB);
+		return(0);
+		}
+	BIO_set_fp(b, fp, BIO_NOCLOSE);
+	ret = ECPKParameters_print(b, x, off);
+	BIO_free(b);
+	return(ret);
+	}
+
+int EC_KEY_print_fp(FILE *fp, const EC_KEY *x, int off)
+	{
+	BIO *b;
+	int ret;
+ 
+	if ((b=BIO_new(BIO_s_file())) == NULL)
+		{
+		ECerr(EC_F_EC_KEY_PRINT_FP, ERR_R_BIO_LIB);
+		return(0);
+		}
+	BIO_set_fp(b, fp, BIO_NOCLOSE);
+	ret = EC_KEY_print(b, x, off);
+	BIO_free(b);
+	return(ret);
+	}
+
+int ECParameters_print_fp(FILE *fp, const EC_KEY *x)
+	{
+	BIO *b;
+	int ret;
+ 
+	if ((b=BIO_new(BIO_s_file())) == NULL)
+		{
+		ECerr(EC_F_ECPARAMETERS_PRINT_FP, ERR_R_BIO_LIB);
+		return(0);
+		}
+	BIO_set_fp(b, fp, BIO_NOCLOSE);
+	ret = ECParameters_print(b, x);
+	BIO_free(b);
+	return(ret);
+	}
+#endif
+
+int EC_KEY_print(BIO *bp, const EC_KEY *x, int off)
+	{
+	EVP_PKEY *pk;
+	int ret;
+	pk = EVP_PKEY_new();
+	if (!pk || !EVP_PKEY_set1_EC_KEY(pk, (EC_KEY *)x))
+		return 0;
+	ret = EVP_PKEY_print_private(bp, pk, off, NULL);
+	EVP_PKEY_free(pk);
+	return ret;
+	}
+
+int ECParameters_print(BIO *bp, const EC_KEY *x)
+	{
+	EVP_PKEY *pk;
+	int ret;
+	pk = EVP_PKEY_new();
+	if (!pk || !EVP_PKEY_set1_EC_KEY(pk, (EC_KEY *)x))
+		return 0;
+	ret = EVP_PKEY_print_params(bp, pk, 4, NULL);
+	EVP_PKEY_free(pk);
+	return ret;
+	}
+
+static int print_bin(BIO *fp, const char *str, const unsigned char *num,
+		size_t len, int off);
+
+int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off)
+	{
+	unsigned char *buffer=NULL;
+	size_t	buf_len=0, i;
+	int     ret=0, reason=ERR_R_BIO_LIB;
+	BN_CTX  *ctx=NULL;
+	const EC_POINT *point=NULL;
+	BIGNUM	*p=NULL, *a=NULL, *b=NULL, *gen=NULL,
+		*order=NULL, *cofactor=NULL;
+	const unsigned char *seed;
+	size_t	seed_len=0;
+	
+	static const char *gen_compressed = "Generator (compressed):";
+	static const char *gen_uncompressed = "Generator (uncompressed):";
+	static const char *gen_hybrid = "Generator (hybrid):";
+ 
+	if (!x)
+		{
+		reason = ERR_R_PASSED_NULL_PARAMETER;
+		goto err;
+		}
+
+	ctx = BN_CTX_new();
+	if (ctx == NULL)
+		{
+		reason = ERR_R_MALLOC_FAILURE;
+		goto err;
+		}
+
+	if (EC_GROUP_get_asn1_flag(x))
+		{
+		/* the curve parameter are given by an asn1 OID */
+		int nid;
+
+		if (!BIO_indent(bp, off, 128))
+			goto err;
+
+		nid = EC_GROUP_get_curve_name(x);
+		if (nid == 0)
+			goto err;
+
+		if (BIO_printf(bp, "ASN1 OID: %s", OBJ_nid2sn(nid)) <= 0)
+			goto err;
+		if (BIO_printf(bp, "\n") <= 0)
+			goto err;
+		}
+	else
+		{
+		/* explicit parameters */
+		int is_char_two = 0;
+		point_conversion_form_t form;
+		int tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(x));
+
+		if (tmp_nid == NID_X9_62_characteristic_two_field)
+			is_char_two = 1;
+
+		if ((p = BN_new()) == NULL || (a = BN_new()) == NULL ||
+			(b = BN_new()) == NULL || (order = BN_new()) == NULL ||
+			(cofactor = BN_new()) == NULL)
+			{
+			reason = ERR_R_MALLOC_FAILURE;
+			goto err;
+			}
+
+		if (is_char_two)
+			{
+			if (!EC_GROUP_get_curve_GF2m(x, p, a, b, ctx))
+				{
+				reason = ERR_R_EC_LIB;
+				goto err;
+				}
+			}
+		else /* prime field */
+			{
+			if (!EC_GROUP_get_curve_GFp(x, p, a, b, ctx))
+				{
+				reason = ERR_R_EC_LIB;
+				goto err;
+				}
+			}
+
+		if ((point = EC_GROUP_get0_generator(x)) == NULL)
+			{
+			reason = ERR_R_EC_LIB;
+			goto err;
+			}
+		if (!EC_GROUP_get_order(x, order, NULL) || 
+            		!EC_GROUP_get_cofactor(x, cofactor, NULL))
+			{
+			reason = ERR_R_EC_LIB;
+			goto err;
+			}
+		
+		form = EC_GROUP_get_point_conversion_form(x);
+
+		if ((gen = EC_POINT_point2bn(x, point, 
+				form, NULL, ctx)) == NULL)
+			{
+			reason = ERR_R_EC_LIB;
+			goto err;
+			}
+
+		buf_len = (size_t)BN_num_bytes(p);
+		if (buf_len < (i = (size_t)BN_num_bytes(a)))
+			buf_len = i;
+		if (buf_len < (i = (size_t)BN_num_bytes(b)))
+			buf_len = i;
+		if (buf_len < (i = (size_t)BN_num_bytes(gen)))
+			buf_len = i;
+		if (buf_len < (i = (size_t)BN_num_bytes(order)))
+			buf_len = i;
+		if (buf_len < (i = (size_t)BN_num_bytes(cofactor))) 
+			buf_len = i;
+
+		if ((seed = EC_GROUP_get0_seed(x)) != NULL)
+			seed_len = EC_GROUP_get_seed_len(x);
+
+		buf_len += 10;
+		if ((buffer = OPENSSL_malloc(buf_len)) == NULL)
+			{
+			reason = ERR_R_MALLOC_FAILURE;
+			goto err;
+			}
+
+		if (!BIO_indent(bp, off, 128))
+			goto err;
+
+		/* print the 'short name' of the field type */
+		if (BIO_printf(bp, "Field Type: %s\n", OBJ_nid2sn(tmp_nid))
+			<= 0)
+			goto err;  
+
+		if (is_char_two)
+			{
+			/* print the 'short name' of the base type OID */
+			int basis_type = EC_GROUP_get_basis_type(x);
+			if (basis_type == 0)
+				goto err;
+
+			if (!BIO_indent(bp, off, 128))
+				goto err;
+
+			if (BIO_printf(bp, "Basis Type: %s\n", 
+				OBJ_nid2sn(basis_type)) <= 0)
+				goto err;
+
+			/* print the polynomial */
+			if ((p != NULL) && !ASN1_bn_print(bp, "Polynomial:", p, buffer,
+				off))
+				goto err;
+			}
+		else
+			{
+			if ((p != NULL) && !ASN1_bn_print(bp, "Prime:", p, buffer,off))
+				goto err;
+			}
+		if ((a != NULL) && !ASN1_bn_print(bp, "A:   ", a, buffer, off)) 
+			goto err;
+		if ((b != NULL) && !ASN1_bn_print(bp, "B:   ", b, buffer, off))
+			goto err;
+		if (form == POINT_CONVERSION_COMPRESSED)
+			{
+			if ((gen != NULL) && !ASN1_bn_print(bp, gen_compressed, gen,
+				buffer, off))
+				goto err;
+			}
+		else if (form == POINT_CONVERSION_UNCOMPRESSED)
+			{
+			if ((gen != NULL) && !ASN1_bn_print(bp, gen_uncompressed, gen,
+				buffer, off))
+				goto err;
+			}
+		else /* form == POINT_CONVERSION_HYBRID */
+			{
+			if ((gen != NULL) && !ASN1_bn_print(bp, gen_hybrid, gen,
+				buffer, off))
+				goto err;
+			}
+		if ((order != NULL) && !ASN1_bn_print(bp, "Order: ", order, 
+			buffer, off)) goto err;
+		if ((cofactor != NULL) && !ASN1_bn_print(bp, "Cofactor: ", cofactor, 
+			buffer, off)) goto err;
+		if (seed && !print_bin(bp, "Seed:", seed, seed_len, off))
+			goto err;
+		}
+	ret=1;
+err:
+	if (!ret)
+ 		ECerr(EC_F_ECPKPARAMETERS_PRINT, reason);
+	if (p) 
+		BN_free(p);
+	if (a) 
+		BN_free(a);
+	if (b)
+		BN_free(b);
+	if (gen)
+		BN_free(gen);
+	if (order)
+		BN_free(order);
+	if (cofactor)
+		BN_free(cofactor);
+	if (ctx)
+		BN_CTX_free(ctx);
+	if (buffer != NULL) 
+		OPENSSL_free(buffer);
+	return(ret);	
+	}
+
+static int print_bin(BIO *fp, const char *name, const unsigned char *buf,
+		size_t len, int off)
+	{
+	size_t i;
+	char str[128];
+
+	if (buf == NULL)
+		return 1;
+	if (off)
+		{
+		if (off > 128)
+			off=128;
+		memset(str,' ',off);
+		if (BIO_write(fp, str, off) <= 0)
+			return 0;
+		}
+
+	if (BIO_printf(fp,"%s", name) <= 0)
+		return 0;
+
+	for (i=0; i<len; i++)
+		{
+		if ((i%15) == 0)
+			{
+			str[0]='\n';
+			memset(&(str[1]),' ',off+4);
+			if (BIO_write(fp, str, off+1+4) <= 0)
+				return 0;
+			}
+		if (BIO_printf(fp,"%02x%s",buf[i],((i+1) == len)?"":":") <= 0)
+			return 0;
+		}
+	if (BIO_write(fp,"\n",1) <= 0)
+		return 0;
+
+	return 1;
+	}
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index e48f42e..f9e34ec 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -1512,6 +1512,7 @@
 BIO *	SSL_get_wbio(const SSL *s);
 #endif
 int	SSL_set_cipher_list(SSL *s, const char *str);
+int	SSL_set_cipher_lists(SSL *s, STACK_OF(SSL_CIPHER) *sk);
 void	SSL_set_read_ahead(SSL *s, int yes);
 int	SSL_get_verify_mode(const SSL *s);
 int	SSL_get_verify_depth(const SSL *s);
diff --git a/openssl.config b/openssl.config
index 4328101..3b109b6 100644
--- a/openssl.config
+++ b/openssl.config
@@ -84,9 +84,6 @@
 	crypto/dso/Makefile			\
 	crypto/dso/dso_beos.c			\
 	crypto/ec/Makefile			\
-	crypto/ec/ec_ameth.c			\
-	crypto/ec/ec_pmeth.c			\
-	crypto/ec/eck_prn.c			\
 	crypto/ecdh/Makefile			\
 	crypto/ecdsa/Makefile			\
 	crypto/engine/Makefile			\
@@ -167,6 +164,7 @@
 "
 
 OPENSSL_PATCHES_progs_SOURCES="\
+	apps/openssl.c	\
 	apps/progs.h	\
 	apps/speed.c"
 
diff --git a/patches/apps_Android.mk b/patches/apps_Android.mk
index a908806..e9f215c 100644
--- a/patches/apps_Android.mk
+++ b/patches/apps_Android.mk
@@ -17,6 +17,7 @@
 	dsa.c \
 	dsaparam.c \
 	ecparam.c \
+	ec.c \
 	enc.c \
 	engine.c \
 	errstr.c \
@@ -64,7 +65,7 @@
 
 # These flags omit whole features from the commandline "openssl".
 # However, portions of these features are actually turned on.
-LOCAL_CFLAGS += -DOPENSSL_NO_EC -DOPENSSL_NO_ECDSA -DOPENSSL_NO_DTLS1
+LOCAL_CFLAGS += -DOPENSSL_NO_DTLS1
 
 
 LOCAL_MODULE:= openssl
diff --git a/patches/crypto_Android.mk b/patches/crypto_Android.mk
index 14bac8e..cb2dfd4 100644
--- a/patches/crypto_Android.mk
+++ b/patches/crypto_Android.mk
@@ -226,6 +226,33 @@
 	dso/dso_openssl.c \
 	dso/dso_vms.c \
 	dso/dso_win32.c \
+	ec/ec2_mult.c \
+	ec/ec2_smpl.c \
+	ec/ec_ameth.c \
+	ec/ec_asn1.c \
+	ec/ec_check.c \
+	ec/ec_curve.c \
+	ec/ec_cvt.c \
+	ec/ec_err.c \
+	ec/ec_key.c \
+	ec/ec_lib.c \
+	ec/ec_mult.c \
+	ec/ec_pmeth.c \
+	ec/ec_print.c \
+	ec/eck_prn.c \
+	ec/ecp_mont.c \
+	ec/ecp_nist.c \
+	ec/ecp_smpl.c \
+	ecdh/ech_err.c \
+	ecdh/ech_key.c \
+	ecdh/ech_lib.c \
+	ecdh/ech_ossl.c \
+	ecdsa/ecs_asn1.c \
+	ecdsa/ecs_err.c \
+	ecdsa/ecs_lib.c \
+	ecdsa/ecs_ossl.c \
+	ecdsa/ecs_sign.c \
+	ecdsa/ecs_vrf.c \
 	err/err.c \
 	err/err_all.c \
 	err/err_prn.c \
@@ -256,6 +283,7 @@
 	evp/evp_pkey.c \
 	evp/m_dss.c \
 	evp/m_dss1.c \
+	evp/m_ecdsa.c \
 	evp/m_md2.c \
 	evp/m_md4.c \
 	evp/m_md5.c \
diff --git a/patches/jsse.patch b/patches/jsse.patch
index f1c14a8..b0ae319 100644
--- a/patches/jsse.patch
+++ b/patches/jsse.patch
@@ -10,7 +10,15 @@
  	/* Default generate session ID callback. */
  	GEN_SESSION_CB generate_session_id;
  
-@@ -1559,6 +1571,7 @@ int	SSL_SESSION_print(BIO *fp,const SSL_
+@@ -1500,6 +1512,7 @@ BIO *	SSL_get_rbio(const SSL *s);
+ BIO *	SSL_get_wbio(const SSL *s);
+ #endif
+ int	SSL_set_cipher_list(SSL *s, const char *str);
++int	SSL_set_cipher_lists(SSL *s, STACK_OF(SSL_CIPHER) *sk);
+ void	SSL_set_read_ahead(SSL *s, int yes);
+ int	SSL_get_verify_mode(const SSL *s);
+ int	SSL_get_verify_depth(const SSL *s);
+@@ -1559,6 +1572,7 @@ int	SSL_SESSION_print(BIO *fp,const SSL_
  void	SSL_SESSION_free(SSL_SESSION *ses);
  int	i2d_SSL_SESSION(SSL_SESSION *in,unsigned char **pp);
  int	SSL_set_session(SSL *to, SSL_SESSION *session);
@@ -18,7 +26,7 @@
  int	SSL_CTX_add_session(SSL_CTX *s, SSL_SESSION *c);
  int	SSL_CTX_remove_session(SSL_CTX *,SSL_SESSION *c);
  int	SSL_CTX_set_generate_session_id(SSL_CTX *, GEN_SESSION_CB);
-@@ -2204,6 +2217,7 @@ void ERR_load_SSL_strings(void);
+@@ -2204,6 +2218,7 @@ void ERR_load_SSL_strings(void);
  #define SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING		 345
  #define SSL_R_SERVERHELLO_TLSEXT			 275
  #define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED		 277
@@ -27,7 +35,7 @@
  #define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE	 220
  #define SSL_R_SSL23_DOING_SESSION_ID_REUSE		 221
 --- openssl-1.0.0.orig/ssl/d1_clnt.c	2010-01-26 11:46:29.000000000 -0800
-+++ openssl-1.0.0/ssl/d1_clnt.c	2010-05-03 01:44:52.000000000 -0700
++++ openssl-1.0.0/ssl/d1_clnt.c	2010-05-12 22:07:36.000000000 -0700
 @@ -613,6 +613,12 @@ int dtls1_client_hello(SSL *s)
  #endif
  			(s->session->not_resumable))
@@ -42,7 +50,7 @@
  				goto err;
  			}
 --- openssl-1.0.0.orig/ssl/s23_clnt.c	2010-02-16 06:20:40.000000000 -0800
-+++ openssl-1.0.0/ssl/s23_clnt.c	2010-05-03 01:44:52.000000000 -0700
++++ openssl-1.0.0/ssl/s23_clnt.c	2010-05-12 22:07:36.000000000 -0700
 @@ -687,6 +687,13 @@ static int ssl23_get_server_hello(SSL *s
  
  	/* Since, if we are sending a ssl23 client hello, we are not
@@ -58,7 +66,7 @@
  		goto err;
  
 --- openssl-1.0.0.orig/ssl/s3_clnt.c	2010-02-27 16:24:24.000000000 -0800
-+++ openssl-1.0.0/ssl/s3_clnt.c	2010-05-03 01:44:52.000000000 -0700
++++ openssl-1.0.0/ssl/s3_clnt.c	2010-05-12 22:07:36.000000000 -0700
 @@ -621,6 +668,12 @@ int ssl3_client_hello(SSL *s)
  #endif
  			(sess->not_resumable))
@@ -86,7 +94,7 @@
  				{
  				al=SSL_AD_INTERNAL_ERROR;
 --- openssl-1.0.0.orig/ssl/s3_srvr.c	2010-02-27 15:04:10.000000000 -0800
-+++ openssl-1.0.0/ssl/s3_srvr.c	2010-05-03 01:44:52.000000000 -0700
++++ openssl-1.0.0/ssl/s3_srvr.c	2010-05-12 22:07:36.000000000 -0700
 @@ -869,6 +869,12 @@ int ssl3_get_client_hello(SSL *s)
  	 */
  	if ((s->new_session && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)))
@@ -114,7 +122,7 @@
  				goto err;
  			}
 --- openssl-1.0.0.orig/ssl/ssl_err.c	2010-01-06 09:37:38.000000000 -0800
-+++ openssl-1.0.0/ssl/ssl_err.c	2010-05-03 01:44:52.000000000 -0700
++++ openssl-1.0.0/ssl/ssl_err.c	2010-05-12 22:07:36.000000000 -0700
 @@ -462,6 +462,7 @@ static ERR_STRING_DATA SSL_str_reasons[]
  {ERR_REASON(SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING),"scsv received when renegotiating"},
  {ERR_REASON(SSL_R_SERVERHELLO_TLSEXT)    ,"serverhello tlsext"},
@@ -124,7 +132,7 @@
  {ERR_REASON(SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE),"signature for non signing certificate"},
  {ERR_REASON(SSL_R_SSL23_DOING_SESSION_ID_REUSE),"ssl23 doing session id reuse"},
 --- openssl-1.0.0.orig/ssl/ssl_lib.c	2010-02-17 11:43:46.000000000 -0800
-+++ openssl-1.0.0/ssl/ssl_lib.c	2010-05-03 01:44:52.000000000 -0700
++++ openssl-1.0.0/ssl/ssl_lib.c	2010-05-12 22:07:36.000000000 -0700
 @@ -326,6 +326,7 @@ SSL *SSL_new(SSL_CTX *ctx)
  	OPENSSL_assert(s->sid_ctx_length <= sizeof s->sid_ctx);
  	memcpy(&s->sid_ctx,&ctx->sid_ctx,sizeof(s->sid_ctx));
@@ -133,8 +141,41 @@
  	s->generate_session_id=ctx->generate_session_id;
  
  	s->param = X509_VERIFY_PARAM_new();
+@@ -1303,6 +1304,32 @@ int SSL_set_cipher_list(SSL *s,const cha
+ 	return 1;
+ 	}
+ 
++/** specify the ciphers to be used by the SSL */
++int SSL_set_cipher_lists(SSL *s,STACK_OF(SSL_CIPHER) *sk)
++	{
++	STACK_OF(SSL_CIPHER) *tmp_cipher_list;
++
++	if (sk == NULL)
++		return 0;
++
++        /* Based on end of ssl_create_cipher_list */
++	tmp_cipher_list = sk_SSL_CIPHER_dup(sk);
++	if (tmp_cipher_list == NULL)
++		{
++		return 0;
++		}
++	if (s->cipher_list != NULL)
++		sk_SSL_CIPHER_free(s->cipher_list);
++	s->cipher_list = sk;
++	if (s->cipher_list_by_id != NULL)
++		sk_SSL_CIPHER_free(s->cipher_list_by_id);
++	s->cipher_list_by_id = tmp_cipher_list;
++	(void)sk_SSL_CIPHER_set_cmp_func(s->cipher_list_by_id,ssl_cipher_ptr_id_cmp);
++
++	sk_SSL_CIPHER_sort(s->cipher_list_by_id);
++	return 1;
++	}
++
+ /* works well for SSLv2, not so good for SSLv3 */
+ char *SSL_get_shared_ciphers(const SSL *s,char *buf,int len)
+ 	{
 --- openssl-1.0.0.orig/ssl/ssl_sess.c	2010-02-01 08:49:42.000000000 -0800
-+++ openssl-1.0.0/ssl/ssl_sess.c	2010-05-03 01:44:52.000000000 -0700
++++ openssl-1.0.0/ssl/ssl_sess.c	2010-05-12 22:07:36.000000000 -0700
 @@ -261,6 +261,11 @@ static int def_generate_session_id(const
  	return 0;
  }
diff --git a/patches/progs.patch b/patches/progs.patch
index d7b794c..f82ea66 100644
--- a/patches/progs.patch
+++ b/patches/progs.patch
@@ -1,5 +1,18 @@
+--- openssl-1.0.0.orig/apps/openssl.c	2009-10-04 09:43:21.000000000 -0700
++++ openssl-1.0.0/apps/openssl.c	2010-05-14 11:50:23.000000000 -0700
+@@ -275,8 +275,10 @@ int main(int Argc, char *Argv[])
+ 		if (ERR_GET_REASON(ERR_peek_last_error())
+ 		    == CONF_R_NO_SUCH_FILE)
+ 			{
++#if 0 /* ANDROID */
+ 			BIO_printf(bio_err,
+ 				   "WARNING: can't open config file: %s\n",p);
++#endif
+ 			ERR_clear_error();
+ 			NCONF_free(config);
+ 			config = NULL;
 --- openssl-1.0.0.orig/apps/progs.h	2009-06-30 08:08:38.000000000 -0700
-+++ openssl-1.0.0/apps/progs.h	2010-04-14 14:19:31.000000000 -0700
++++ openssl-1.0.0/apps/progs.h	2010-05-14 11:50:23.000000000 -0700
 @@ -43,7 +43,9 @@ extern int spkac_main(int argc,char *arg
  extern int smime_main(int argc,char *argv[]);
  extern int rand_main(int argc,char *argv[]);
@@ -44,7 +57,7 @@
  	{FUNC_TYPE_MD,"md2",dgst_main},
  #endif
 --- openssl-1.0.0.orig/apps/speed.c	2010-03-03 11:56:17.000000000 -0800
-+++ openssl-1.0.0/apps/speed.c	2010-04-13 16:53:43.000000000 -0700
++++ openssl-1.0.0/apps/speed.c	2010-05-14 11:50:23.000000000 -0700
 @@ -1718,6 +1718,7 @@ int MAIN(int argc, char **argv)
  			}
  		}
diff --git a/patches/ssl_Android.mk b/patches/ssl_Android.mk
index 0ea0b45..201a740 100644
--- a/patches/ssl_Android.mk
+++ b/patches/ssl_Android.mk
@@ -60,7 +60,7 @@
 
 # ssltest
 
-LOCAL_SRC_FILES:=ssltest.c
+LOCAL_SRC_FILES:= ssltest.c
 
 LOCAL_C_INCLUDES += $(local_c_includes)
 
@@ -68,7 +68,7 @@
 
 include $(LOCAL_PATH)/../android-config.mk
 
-LOCAL_MODULE:=ssltest
+LOCAL_MODULE:= ssltest
 
 LOCAL_MODULE_TAGS := optional
 
diff --git a/ssl/Android.mk b/ssl/Android.mk
index 0ea0b45..201a740 100644
--- a/ssl/Android.mk
+++ b/ssl/Android.mk
@@ -60,7 +60,7 @@
 
 # ssltest
 
-LOCAL_SRC_FILES:=ssltest.c
+LOCAL_SRC_FILES:= ssltest.c
 
 LOCAL_C_INCLUDES += $(local_c_includes)
 
@@ -68,7 +68,7 @@
 
 include $(LOCAL_PATH)/../android-config.mk
 
-LOCAL_MODULE:=ssltest
+LOCAL_MODULE:= ssltest
 
 LOCAL_MODULE_TAGS := optional
 
diff --git a/ssl/ssl.h b/ssl/ssl.h
index e48f42e..f9e34ec 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -1512,6 +1512,7 @@
 BIO *	SSL_get_wbio(const SSL *s);
 #endif
 int	SSL_set_cipher_list(SSL *s, const char *str);
+int	SSL_set_cipher_lists(SSL *s, STACK_OF(SSL_CIPHER) *sk);
 void	SSL_set_read_ahead(SSL *s, int yes);
 int	SSL_get_verify_mode(const SSL *s);
 int	SSL_get_verify_depth(const SSL *s);
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index a594b79..e3437a0 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1304,6 +1304,32 @@
 	return 1;
 	}
 
+/** specify the ciphers to be used by the SSL */
+int SSL_set_cipher_lists(SSL *s,STACK_OF(SSL_CIPHER) *sk)
+	{
+	STACK_OF(SSL_CIPHER) *tmp_cipher_list;
+
+	if (sk == NULL)
+		return 0;
+
+        /* Based on end of ssl_create_cipher_list */
+	tmp_cipher_list = sk_SSL_CIPHER_dup(sk);
+	if (tmp_cipher_list == NULL)
+		{
+		return 0;
+		}
+	if (s->cipher_list != NULL)
+		sk_SSL_CIPHER_free(s->cipher_list);
+	s->cipher_list = sk;
+	if (s->cipher_list_by_id != NULL)
+		sk_SSL_CIPHER_free(s->cipher_list_by_id);
+	s->cipher_list_by_id = tmp_cipher_list;
+	(void)sk_SSL_CIPHER_set_cmp_func(s->cipher_list_by_id,ssl_cipher_ptr_id_cmp);
+
+	sk_SSL_CIPHER_sort(s->cipher_list_by_id);
+	return 1;
+	}
+
 /* works well for SSLv2, not so good for SSLv3 */
 char *SSL_get_shared_ciphers(const SSL *s,char *buf,int len)
 	{