#14371: Add opensll to main repository
diff --git a/jni/openssl/crypto/ec/ec.h b/jni/openssl/crypto/ec/ec.h
new file mode 100644
index 0000000..9d01325
--- /dev/null
+++ b/jni/openssl/crypto/ec/ec.h
@@ -0,0 +1,1159 @@
+/* crypto/ec/ec.h */
+/*
+ * Originally written by Bodo Moeller for the OpenSSL project.
+ */
+/**
+ * \file crypto/ec/ec.h Include file for the OpenSSL EC functions
+ * \author Originally written by Bodo Moeller 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 of the attached software ("Contribution") are developed by 
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * The elliptic curve binary polynomial software is originally written by 
+ * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
+ *
+ */
+
+#ifndef HEADER_EC_H
+#define HEADER_EC_H
+
+#include <openssl/opensslconf.h>
+
+#ifdef OPENSSL_NO_EC
+#error EC is disabled.
+#endif
+
+#include <openssl/asn1.h>
+#include <openssl/symhacks.h>
+#ifndef OPENSSL_NO_DEPRECATED
+#include <openssl/bn.h>
+#endif
+
+#ifdef  __cplusplus
+extern "C" {
+#elif defined(__SUNPRO_C)
+# if __SUNPRO_C >= 0x520
+# pragma error_messages (off,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE)
+# endif
+#endif
+
+  
+#ifndef OPENSSL_ECC_MAX_FIELD_BITS
+# define OPENSSL_ECC_MAX_FIELD_BITS 661
+#endif
+
+/** Enum for the point conversion form as defined in X9.62 (ECDSA)
+ *  for the encoding of a elliptic curve point (x,y) */
+typedef enum {
+	/** the point is encoded as z||x, where the octet z specifies 
+	 *  which solution of the quadratic equation y is  */
+	POINT_CONVERSION_COMPRESSED = 2,
+	/** the point is encoded as z||x||y, where z is the octet 0x02  */
+	POINT_CONVERSION_UNCOMPRESSED = 4,
+	/** the point is encoded as z||x||y, where the octet z specifies
+         *  which solution of the quadratic equation y is  */
+	POINT_CONVERSION_HYBRID = 6
+} point_conversion_form_t;
+
+
+typedef struct ec_method_st EC_METHOD;
+
+typedef struct ec_group_st
+	/*
+	 EC_METHOD *meth;
+	 -- field definition
+	 -- curve coefficients
+	 -- optional generator with associated information (order, cofactor)
+	 -- optional extra data (precomputed table for fast computation of multiples of generator)
+	 -- ASN1 stuff
+	*/
+	EC_GROUP;
+
+typedef struct ec_point_st EC_POINT;
+
+
+/********************************************************************/
+/*               EC_METHODs for curves over GF(p)                   */       
+/********************************************************************/
+
+/** Returns the basic GFp ec methods which provides the basis for the
+ *  optimized methods. 
+ *  \return  EC_METHOD object
+ */
+const EC_METHOD *EC_GFp_simple_method(void);
+
+/** Returns GFp methods using montgomery multiplication.
+ *  \return  EC_METHOD object
+ */
+const EC_METHOD *EC_GFp_mont_method(void);
+
+/** Returns GFp methods using optimized methods for NIST recommended curves
+ *  \return  EC_METHOD object
+ */
+const EC_METHOD *EC_GFp_nist_method(void);
+
+#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
+/** Returns 64-bit optimized methods for nistp224
+ *  \return  EC_METHOD object
+ */
+const EC_METHOD *EC_GFp_nistp224_method(void);
+
+/** Returns 64-bit optimized methods for nistp256
+ *  \return  EC_METHOD object
+ */
+const EC_METHOD *EC_GFp_nistp256_method(void);
+
+/** Returns 64-bit optimized methods for nistp521
+ *  \return  EC_METHOD object
+ */
+const EC_METHOD *EC_GFp_nistp521_method(void);
+#endif
+
+#ifndef OPENSSL_NO_EC2M
+/********************************************************************/ 
+/*           EC_METHOD for curves over GF(2^m)                      */
+/********************************************************************/
+
+/** Returns the basic GF2m ec method 
+ *  \return  EC_METHOD object
+ */
+const EC_METHOD *EC_GF2m_simple_method(void);
+
+#endif
+
+
+/********************************************************************/
+/*                   EC_GROUP functions                             */
+/********************************************************************/
+
+/** Creates a new EC_GROUP object
+ *  \param   meth  EC_METHOD to use
+ *  \return  newly created EC_GROUP object or NULL in case of an error.
+ */
+EC_GROUP *EC_GROUP_new(const EC_METHOD *meth);
+
+/** Frees a EC_GROUP object
+ *  \param  group  EC_GROUP object to be freed.
+ */
+void EC_GROUP_free(EC_GROUP *group);
+
+/** Clears and frees a EC_GROUP object
+ *  \param  group  EC_GROUP object to be cleared and freed.
+ */
+void EC_GROUP_clear_free(EC_GROUP *group);
+
+/** Copies EC_GROUP objects. Note: both EC_GROUPs must use the same EC_METHOD.
+ *  \param  dst  destination EC_GROUP object
+ *  \param  src  source EC_GROUP object
+ *  \return 1 on success and 0 if an error occurred.
+ */
+int EC_GROUP_copy(EC_GROUP *dst, const EC_GROUP *src);
+
+/** Creates a new EC_GROUP object and copies the copies the content
+ *  form src to the newly created EC_KEY object
+ *  \param  src  source EC_GROUP object
+ *  \return newly created EC_GROUP object or NULL in case of an error.
+ */
+EC_GROUP *EC_GROUP_dup(const EC_GROUP *src);
+
+/** Returns the EC_METHOD of the EC_GROUP object.
+ *  \param  group  EC_GROUP object 
+ *  \return EC_METHOD used in this EC_GROUP object.
+ */
+const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group);
+
+/** Returns the field type of the EC_METHOD.
+ *  \param  meth  EC_METHOD object
+ *  \return NID of the underlying field type OID.
+ */
+int EC_METHOD_get_field_type(const EC_METHOD *meth);
+
+/** Sets the generator and it's order/cofactor of a EC_GROUP object.
+ *  \param  group      EC_GROUP object 
+ *  \param  generator  EC_POINT object with the generator.
+ *  \param  order      the order of the group generated by the generator.
+ *  \param  cofactor   the index of the sub-group generated by the generator
+ *                     in the group of all points on the elliptic curve.
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor);
+
+/** Returns the generator of a EC_GROUP object.
+ *  \param  group  EC_GROUP object
+ *  \return the currently used generator (possibly NULL).
+ */
+const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group);
+
+/** Gets the order of a EC_GROUP
+ *  \param  group  EC_GROUP object
+ *  \param  order  BIGNUM to which the order is copied
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx);
+
+/** Gets the cofactor of a EC_GROUP
+ *  \param  group     EC_GROUP object
+ *  \param  cofactor  BIGNUM to which the cofactor is copied
+ *  \param  ctx       BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx);
+
+/** Sets the name of a EC_GROUP object
+ *  \param  group  EC_GROUP object
+ *  \param  nid    NID of the curve name OID
+ */
+void EC_GROUP_set_curve_name(EC_GROUP *group, int nid);
+
+/** Returns the curve name of a EC_GROUP object
+ *  \param  group  EC_GROUP object
+ *  \return NID of the curve name OID or 0 if not set.
+ */
+int EC_GROUP_get_curve_name(const EC_GROUP *group);
+
+void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag);
+int EC_GROUP_get_asn1_flag(const EC_GROUP *group);
+
+void EC_GROUP_set_point_conversion_form(EC_GROUP *, point_conversion_form_t);
+point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *);
+
+unsigned char *EC_GROUP_get0_seed(const EC_GROUP *);
+size_t EC_GROUP_get_seed_len(const EC_GROUP *);
+size_t EC_GROUP_set_seed(EC_GROUP *, const unsigned char *, size_t len);
+
+/** Sets the parameter of a ec over GFp defined by y^2 = x^3 + a*x + b
+ *  \param  group  EC_GROUP object
+ *  \param  p      BIGNUM with the prime number
+ *  \param  a      BIGNUM with parameter a of the equation
+ *  \param  b      BIGNUM with parameter b of the equation
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
+
+/** Gets the parameter of the ec over GFp defined by y^2 = x^3 + a*x + b
+ *  \param  group  EC_GROUP object
+ *  \param  p      BIGNUM for the prime number
+ *  \param  a      BIGNUM for parameter a of the equation
+ *  \param  b      BIGNUM for parameter b of the equation
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx);
+
+#ifndef OPENSSL_NO_EC2M
+/** Sets the parameter of a ec over GF2m defined by y^2 + x*y = x^3 + a*x^2 + b
+ *  \param  group  EC_GROUP object
+ *  \param  p      BIGNUM with the polynomial defining the underlying field
+ *  \param  a      BIGNUM with parameter a of the equation
+ *  \param  b      BIGNUM with parameter b of the equation
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
+
+/** Gets the parameter of the ec over GF2m defined by y^2 + x*y = x^3 + a*x^2 + b
+ *  \param  group  EC_GROUP object
+ *  \param  p      BIGNUM for the polynomial defining the underlying field
+ *  \param  a      BIGNUM for parameter a of the equation
+ *  \param  b      BIGNUM for parameter b of the equation
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx);
+#endif
+/** Returns the number of bits needed to represent a field element 
+ *  \param  group  EC_GROUP object
+ *  \return number of bits needed to represent a field element
+ */
+int EC_GROUP_get_degree(const EC_GROUP *group);
+
+/** Checks whether the parameter in the EC_GROUP define a valid ec group
+ *  \param  group  EC_GROUP object
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 if group is a valid ec group and 0 otherwise
+ */
+int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx);
+
+/** Checks whether the discriminant of the elliptic curve is zero or not
+ *  \param  group  EC_GROUP object
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 if the discriminant is not zero and 0 otherwise
+ */
+int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx);
+
+/** Compares two EC_GROUP objects
+ *  \param  a    first EC_GROUP object
+ *  \param  b    second EC_GROUP object
+ *  \param  ctx  BN_CTX object (optional)
+ *  \return 0 if both groups are equal and 1 otherwise
+ */
+int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx);
+
+/* EC_GROUP_new_GF*() calls EC_GROUP_new() and EC_GROUP_set_GF*()
+ * after choosing an appropriate EC_METHOD */
+
+/** Creates a new EC_GROUP object with the specified parameters defined
+ *  over GFp (defined by the equation y^2 = x^3 + a*x + b)
+ *  \param  p    BIGNUM with the prime number
+ *  \param  a    BIGNUM with the parameter a of the equation
+ *  \param  b    BIGNUM with the parameter b of the equation
+ *  \param  ctx  BN_CTX object (optional)
+ *  \return newly created EC_GROUP object with the specified parameters
+ */
+EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
+#ifndef OPENSSL_NO_EC2M
+/** Creates a new EC_GROUP object with the specified parameters defined
+ *  over GF2m (defined by the equation y^2 + x*y = x^3 + a*x^2 + b)
+ *  \param  p    BIGNUM with the polynomial defining the underlying field
+ *  \param  a    BIGNUM with the parameter a of the equation
+ *  \param  b    BIGNUM with the parameter b of the equation
+ *  \param  ctx  BN_CTX object (optional)
+ *  \return newly created EC_GROUP object with the specified parameters
+ */
+EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
+#endif
+/** Creates a EC_GROUP object with a curve specified by a NID
+ *  \param  nid  NID of the OID of the curve name
+ *  \return newly created EC_GROUP object with specified curve or NULL
+ *          if an error occurred
+ */
+EC_GROUP *EC_GROUP_new_by_curve_name(int nid);
+
+
+/********************************************************************/
+/*               handling of internal curves                        */
+/********************************************************************/
+
+typedef struct { 
+	int nid;
+	const char *comment;
+	} EC_builtin_curve;
+
+/* EC_builtin_curves(EC_builtin_curve *r, size_t size) returns number 
+ * of all available curves or zero if a error occurred. 
+ * In case r ist not zero nitems EC_builtin_curve structures 
+ * are filled with the data of the first nitems internal groups */
+size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems);
+
+
+/********************************************************************/
+/*                    EC_POINT functions                            */
+/********************************************************************/
+
+/** Creates a new EC_POINT object for the specified EC_GROUP
+ *  \param  group  EC_GROUP the underlying EC_GROUP object
+ *  \return newly created EC_POINT object or NULL if an error occurred
+ */
+EC_POINT *EC_POINT_new(const EC_GROUP *group);
+
+/** Frees a EC_POINT object
+ *  \param  point  EC_POINT object to be freed
+ */
+void EC_POINT_free(EC_POINT *point);
+
+/** Clears and frees a EC_POINT object
+ *  \param  point  EC_POINT object to be cleared and freed
+ */
+void EC_POINT_clear_free(EC_POINT *point);
+
+/** Copies EC_POINT object
+ *  \param  dst  destination EC_POINT object
+ *  \param  src  source EC_POINT object
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_copy(EC_POINT *dst, const EC_POINT *src);
+
+/** Creates a new EC_POINT object and copies the content of the supplied
+ *  EC_POINT
+ *  \param  src    source EC_POINT object
+ *  \param  group  underlying the EC_GROUP object
+ *  \return newly created EC_POINT object or NULL if an error occurred 
+ */
+EC_POINT *EC_POINT_dup(const EC_POINT *src, const EC_GROUP *group);
+ 
+/** Returns the EC_METHOD used in EC_POINT object 
+ *  \param  point  EC_POINT object
+ *  \return the EC_METHOD used
+ */
+const EC_METHOD *EC_POINT_method_of(const EC_POINT *point);
+
+/** Sets a point to infinity (neutral element)
+ *  \param  group  underlying EC_GROUP object
+ *  \param  point  EC_POINT to set to infinity
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point);
+
+/** Sets the jacobian projective coordinates of a EC_POINT over GFp
+ *  \param  group  underlying EC_GROUP object
+ *  \param  p      EC_POINT object
+ *  \param  x      BIGNUM with the x-coordinate
+ *  \param  y      BIGNUM with the y-coordinate
+ *  \param  z      BIGNUM with the z-coordinate
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *p,
+	const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx);
+
+/** Gets the jacobian projective coordinates of a EC_POINT over GFp
+ *  \param  group  underlying EC_GROUP object
+ *  \param  p      EC_POINT object
+ *  \param  x      BIGNUM for the x-coordinate
+ *  \param  y      BIGNUM for the y-coordinate
+ *  \param  z      BIGNUM for the z-coordinate
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
+	const EC_POINT *p, BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx);
+
+/** Sets the affine coordinates of a EC_POINT over GFp
+ *  \param  group  underlying EC_GROUP object
+ *  \param  p      EC_POINT object
+ *  \param  x      BIGNUM with the x-coordinate
+ *  \param  y      BIGNUM with the y-coordinate
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *p,
+	const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx);
+
+/** Gets the affine coordinates of a EC_POINT over GFp
+ *  \param  group  underlying EC_GROUP object
+ *  \param  p      EC_POINT object
+ *  \param  x      BIGNUM for the x-coordinate
+ *  \param  y      BIGNUM for the y-coordinate
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
+	const EC_POINT *p, BIGNUM *x, BIGNUM *y, BN_CTX *ctx);
+
+/** Sets the x9.62 compressed coordinates of a EC_POINT over GFp
+ *  \param  group  underlying EC_GROUP object
+ *  \param  p      EC_POINT object
+ *  \param  x      BIGNUM with x-coordinate
+ *  \param  y_bit  integer with the y-Bit (either 0 or 1)
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *p,
+	const BIGNUM *x, int y_bit, BN_CTX *ctx);
+#ifndef OPENSSL_NO_EC2M
+/** Sets the affine coordinates of a EC_POINT over GF2m
+ *  \param  group  underlying EC_GROUP object
+ *  \param  p      EC_POINT object
+ *  \param  x      BIGNUM with the x-coordinate
+ *  \param  y      BIGNUM with the y-coordinate
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *p,
+	const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx);
+
+/** Gets the affine coordinates of a EC_POINT over GF2m
+ *  \param  group  underlying EC_GROUP object
+ *  \param  p      EC_POINT object
+ *  \param  x      BIGNUM for the x-coordinate
+ *  \param  y      BIGNUM for the y-coordinate
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,
+	const EC_POINT *p, BIGNUM *x, BIGNUM *y, BN_CTX *ctx);
+
+/** Sets the x9.62 compressed coordinates of a EC_POINT over GF2m
+ *  \param  group  underlying EC_GROUP object
+ *  \param  p      EC_POINT object
+ *  \param  x      BIGNUM with x-coordinate
+ *  \param  y_bit  integer with the y-Bit (either 0 or 1)
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, EC_POINT *p,
+	const BIGNUM *x, int y_bit, BN_CTX *ctx);
+#endif
+/** Encodes a EC_POINT object to a octet string
+ *  \param  group  underlying EC_GROUP object
+ *  \param  p      EC_POINT object
+ *  \param  form   point conversion form
+ *  \param  buf    memory buffer for the result. If NULL the function returns
+ *                 required buffer size.
+ *  \param  len    length of the memory buffer
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return the length of the encoded octet string or 0 if an error occurred
+ */
+size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *p,
+	point_conversion_form_t form,
+        unsigned char *buf, size_t len, BN_CTX *ctx);
+
+/** Decodes a EC_POINT from a octet string
+ *  \param  group  underlying EC_GROUP object
+ *  \param  p      EC_POINT object
+ *  \param  buf    memory buffer with the encoded ec point
+ *  \param  len    length of the encoded ec point
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *p,
+        const unsigned char *buf, size_t len, BN_CTX *ctx);
+
+/* other interfaces to point2oct/oct2point: */
+BIGNUM *EC_POINT_point2bn(const EC_GROUP *, const EC_POINT *,
+	point_conversion_form_t form, BIGNUM *, BN_CTX *);
+EC_POINT *EC_POINT_bn2point(const EC_GROUP *, const BIGNUM *,
+	EC_POINT *, BN_CTX *);
+char *EC_POINT_point2hex(const EC_GROUP *, const EC_POINT *,
+	point_conversion_form_t form, BN_CTX *);
+EC_POINT *EC_POINT_hex2point(const EC_GROUP *, const char *,
+	EC_POINT *, BN_CTX *);
+
+
+/********************************************************************/
+/*         functions for doing EC_POINT arithmetic                  */
+/********************************************************************/
+
+/** Computes the sum of two EC_POINT 
+ *  \param  group  underlying EC_GROUP object
+ *  \param  r      EC_POINT object for the result (r = a + b)
+ *  \param  a      EC_POINT object with the first summand
+ *  \param  b      EC_POINT object with the second summand
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx);
+
+/** Computes the double of a EC_POINT
+ *  \param  group  underlying EC_GROUP object
+ *  \param  r      EC_POINT object for the result (r = 2 * a)
+ *  \param  a      EC_POINT object 
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx);
+
+/** Computes the inverse of a EC_POINT
+ *  \param  group  underlying EC_GROUP object
+ *  \param  a      EC_POINT object to be inverted (it's used for the result as well)
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx);
+
+/** Checks whether the point is the neutral element of the group
+ *  \param  group  the underlying EC_GROUP object
+ *  \param  p      EC_POINT object
+ *  \return 1 if the point is the neutral element and 0 otherwise
+ */
+int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *p);
+
+/** Checks whether the point is on the curve 
+ *  \param  group  underlying EC_GROUP object
+ *  \param  point  EC_POINT object to check
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 if point if on the curve and 0 otherwise
+ */
+int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx);
+
+/** Compares two EC_POINTs 
+ *  \param  group  underlying EC_GROUP object
+ *  \param  a      first EC_POINT object
+ *  \param  b      second EC_POINT object
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 0 if both points are equal and a value != 0 otherwise
+ */
+int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx);
+
+int EC_POINT_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *);
+int EC_POINTs_make_affine(const EC_GROUP *, size_t num, EC_POINT *[], BN_CTX *);
+
+/** Computes r = generator * n sum_{i=0}^num p[i] * m[i]
+ *  \param  group  underlying EC_GROUP object
+ *  \param  r      EC_POINT object for the result
+ *  \param  n      BIGNUM with the multiplier for the group generator (optional)
+ *  \param  num    number futher summands
+ *  \param  p      array of size num of EC_POINT objects
+ *  \param  m      array of size num of BIGNUM objects
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, size_t num, const EC_POINT *p[], const BIGNUM *m[], BN_CTX *ctx);
+
+/** Computes r = generator * n + q * m
+ *  \param  group  underlying EC_GROUP object
+ *  \param  r      EC_POINT object for the result
+ *  \param  n      BIGNUM with the multiplier for the group generator (optional)
+ *  \param  q      EC_POINT object with the first factor of the second summand
+ *  \param  m      BIGNUM with the second factor of the second summand
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, const EC_POINT *q, const BIGNUM *m, BN_CTX *ctx);
+
+/** Stores multiples of generator for faster point multiplication
+ *  \param  group  EC_GROUP object
+ *  \param  ctx    BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occured
+ */
+int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
+
+/** Reports whether a precomputation has been done
+ *  \param  group  EC_GROUP object
+ *  \return 1 if a pre-computation has been done and 0 otherwise
+ */
+int EC_GROUP_have_precompute_mult(const EC_GROUP *group);
+
+
+/********************************************************************/
+/*                       ASN1 stuff                                 */
+/********************************************************************/
+
+/* EC_GROUP_get_basis_type() returns the NID of the basis type
+ * used to represent the field elements */
+int EC_GROUP_get_basis_type(const EC_GROUP *);
+#ifndef OPENSSL_NO_EC2M
+int EC_GROUP_get_trinomial_basis(const EC_GROUP *, unsigned int *k);
+int EC_GROUP_get_pentanomial_basis(const EC_GROUP *, unsigned int *k1, 
+	unsigned int *k2, unsigned int *k3);
+#endif
+
+#define OPENSSL_EC_NAMED_CURVE	0x001
+
+typedef struct ecpk_parameters_st ECPKPARAMETERS;
+
+EC_GROUP *d2i_ECPKParameters(EC_GROUP **, const unsigned char **in, long len);
+int i2d_ECPKParameters(const EC_GROUP *, unsigned char **out);
+
+#define d2i_ECPKParameters_bio(bp,x) ASN1_d2i_bio_of(EC_GROUP,NULL,d2i_ECPKParameters,bp,x)
+#define i2d_ECPKParameters_bio(bp,x) ASN1_i2d_bio_of_const(EC_GROUP,i2d_ECPKParameters,bp,x)
+#define d2i_ECPKParameters_fp(fp,x) (EC_GROUP *)ASN1_d2i_fp(NULL, \
+                (char *(*)())d2i_ECPKParameters,(fp),(unsigned char **)(x))
+#define i2d_ECPKParameters_fp(fp,x) ASN1_i2d_fp(i2d_ECPKParameters,(fp), \
+		(unsigned char *)(x))
+
+#ifndef OPENSSL_NO_BIO
+int     ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off);
+#endif
+#ifndef OPENSSL_NO_FP_API
+int     ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off);
+#endif
+
+
+/********************************************************************/
+/*                      EC_KEY functions                            */
+/********************************************************************/
+
+typedef struct ec_key_st EC_KEY;
+
+/* some values for the encoding_flag */
+#define EC_PKEY_NO_PARAMETERS	0x001
+#define EC_PKEY_NO_PUBKEY	0x002
+
+/* some values for the flags field */
+#define EC_FLAG_NON_FIPS_ALLOW	0x1
+#define EC_FLAG_FIPS_CHECKED	0x2
+
+/** Creates a new EC_KEY object.
+ *  \return EC_KEY object or NULL if an error occurred.
+ */
+EC_KEY *EC_KEY_new(void);
+
+int EC_KEY_get_flags(const EC_KEY *key);
+
+void EC_KEY_set_flags(EC_KEY *key, int flags);
+
+void EC_KEY_clear_flags(EC_KEY *key, int flags);
+
+/** Creates a new EC_KEY object using a named curve as underlying
+ *  EC_GROUP object.
+ *  \param  nid  NID of the named curve.
+ *  \return EC_KEY object or NULL if an error occurred. 
+ */
+EC_KEY *EC_KEY_new_by_curve_name(int nid);
+
+/** Frees a EC_KEY object.
+ *  \param  key  EC_KEY object to be freed.
+ */
+void EC_KEY_free(EC_KEY *key);
+
+/** Copies a EC_KEY object.
+ *  \param  dst  destination EC_KEY object
+ *  \param  src  src EC_KEY object
+ *  \return dst or NULL if an error occurred.
+ */
+EC_KEY *EC_KEY_copy(EC_KEY *dst, const EC_KEY *src);
+
+/** Creates a new EC_KEY object and copies the content from src to it.
+ *  \param  src  the source EC_KEY object
+ *  \return newly created EC_KEY object or NULL if an error occurred.
+ */
+EC_KEY *EC_KEY_dup(const EC_KEY *src);
+
+/** Increases the internal reference count of a EC_KEY object.
+ *  \param  key  EC_KEY object
+ *  \return 1 on success and 0 if an error occurred.
+ */
+int EC_KEY_up_ref(EC_KEY *key);
+
+/** Returns the EC_GROUP object of a EC_KEY object
+ *  \param  key  EC_KEY object
+ *  \return the EC_GROUP object (possibly NULL).
+ */
+const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key);
+
+/** Sets the EC_GROUP of a EC_KEY object.
+ *  \param  key    EC_KEY object
+ *  \param  group  EC_GROUP to use in the EC_KEY object (note: the EC_KEY
+ *                 object will use an own copy of the EC_GROUP).
+ *  \return 1 on success and 0 if an error occurred.
+ */
+int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group);
+
+/** Returns the private key of a EC_KEY object.
+ *  \param  key  EC_KEY object
+ *  \return a BIGNUM with the private key (possibly NULL).
+ */
+const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key);
+
+/** Sets the private key of a EC_KEY object.
+ *  \param  key  EC_KEY object
+ *  \param  prv  BIGNUM with the private key (note: the EC_KEY object
+ *               will use an own copy of the BIGNUM).
+ *  \return 1 on success and 0 if an error occurred.
+ */
+int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *prv);
+
+/** Returns the public key of a EC_KEY object.
+ *  \param  key  the EC_KEY object
+ *  \return a EC_POINT object with the public key (possibly NULL)
+ */
+const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key);
+
+/** Sets the public key of a EC_KEY object.
+ *  \param  key  EC_KEY object
+ *  \param  pub  EC_POINT object with the public key (note: the EC_KEY object
+ *               will use an own copy of the EC_POINT object).
+ *  \return 1 on success and 0 if an error occurred.
+ */
+int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub);
+
+unsigned EC_KEY_get_enc_flags(const EC_KEY *key);
+void EC_KEY_set_enc_flags(EC_KEY *, unsigned int);
+point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *);
+void EC_KEY_set_conv_form(EC_KEY *, point_conversion_form_t);
+/* functions to set/get method specific data  */
+void *EC_KEY_get_key_method_data(EC_KEY *, 
+	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
+void EC_KEY_insert_key_method_data(EC_KEY *, void *data,
+	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
+/* wrapper functions for the underlying EC_GROUP object */
+void EC_KEY_set_asn1_flag(EC_KEY *, int);
+
+/** Creates a table of pre-computed multiples of the generator to 
+ *  accelerate further EC_KEY operations.
+ *  \param  key  EC_KEY object
+ *  \param  ctx  BN_CTX object (optional)
+ *  \return 1 on success and 0 if an error occurred.
+ */
+int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx);
+
+/** Creates a new ec private (and optional a new public) key.
+ *  \param  key  EC_KEY object
+ *  \return 1 on success and 0 if an error occurred.
+ */
+int EC_KEY_generate_key(EC_KEY *key);
+
+/** Verifies that a private and/or public key is valid.
+ *  \param  key  the EC_KEY object
+ *  \return 1 on success and 0 otherwise.
+ */
+int EC_KEY_check_key(const EC_KEY *key);
+
+/** Sets a public key from affine coordindates performing
+ *  neccessary NIST PKV tests.
+ *  \param  key  the EC_KEY object
+ *  \param  x    public key x coordinate
+ *  \param  y    public key y coordinate
+ *  \return 1 on success and 0 otherwise.
+ */
+int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y);
+
+
+/********************************************************************/
+/*        de- and encoding functions for SEC1 ECPrivateKey          */
+/********************************************************************/
+
+/** Decodes a private key from a memory buffer.
+ *  \param  key  a pointer to a EC_KEY object which should be used (or NULL)
+ *  \param  in   pointer to memory with the DER encoded private key
+ *  \param  len  length of the DER encoded private key
+ *  \return the decoded private key or NULL if an error occurred.
+ */
+EC_KEY *d2i_ECPrivateKey(EC_KEY **key, const unsigned char **in, long len);
+
+/** Encodes a private key object and stores the result in a buffer.
+ *  \param  key  the EC_KEY object to encode
+ *  \param  out  the buffer for the result (if NULL the function returns number
+ *               of bytes needed).
+ *  \return 1 on success and 0 if an error occurred.
+ */
+int i2d_ECPrivateKey(EC_KEY *key, unsigned char **out);
+
+
+/********************************************************************/
+/*        de- and encoding functions for EC parameters              */
+/********************************************************************/
+
+/** Decodes ec parameter from a memory buffer.
+ *  \param  key  a pointer to a EC_KEY object which should be used (or NULL)
+ *  \param  in   pointer to memory with the DER encoded ec parameters
+ *  \param  len  length of the DER encoded ec parameters
+ *  \return a EC_KEY object with the decoded parameters or NULL if an error
+ *          occurred.
+ */
+EC_KEY *d2i_ECParameters(EC_KEY **key, const unsigned char **in, long len);
+
+/** Encodes ec parameter and stores the result in a buffer.
+ *  \param  key  the EC_KEY object with ec paramters to encode
+ *  \param  out  the buffer for the result (if NULL the function returns number
+ *               of bytes needed).
+ *  \return 1 on success and 0 if an error occurred.
+ */
+int i2d_ECParameters(EC_KEY *key, unsigned char **out);
+
+
+/********************************************************************/
+/*         de- and encoding functions for EC public key             */
+/*         (octet string, not DER -- hence 'o2i' and 'i2o')         */
+/********************************************************************/
+
+/** Decodes a ec public key from a octet string.
+ *  \param  key  a pointer to a EC_KEY object which should be used
+ *  \param  in   memory buffer with the encoded public key
+ *  \param  len  length of the encoded public key
+ *  \return EC_KEY object with decoded public key or NULL if an error
+ *          occurred.
+ */
+EC_KEY *o2i_ECPublicKey(EC_KEY **key, const unsigned char **in, long len);
+
+/** Encodes a ec public key in an octet string.
+ *  \param  key  the EC_KEY object with the public key
+ *  \param  out  the buffer for the result (if NULL the function returns number
+ *               of bytes needed).
+ *  \return 1 on success and 0 if an error occurred
+ */
+int i2o_ECPublicKey(EC_KEY *key, unsigned char **out);
+
+#ifndef OPENSSL_NO_BIO
+/** Prints out the ec parameters on human readable form.
+ *  \param  bp   BIO object to which the information is printed
+ *  \param  key  EC_KEY object
+ *  \return 1 on success and 0 if an error occurred
+ */
+int	ECParameters_print(BIO *bp, const EC_KEY *key);
+
+/** Prints out the contents of a EC_KEY object
+ *  \param  bp   BIO object to which the information is printed
+ *  \param  key  EC_KEY object
+ *  \param  off  line offset 
+ *  \return 1 on success and 0 if an error occurred
+ */
+int	EC_KEY_print(BIO *bp, const EC_KEY *key, int off);
+
+#endif
+#ifndef OPENSSL_NO_FP_API
+/** Prints out the ec parameters on human readable form.
+ *  \param  fp   file descriptor to which the information is printed
+ *  \param  key  EC_KEY object
+ *  \return 1 on success and 0 if an error occurred
+ */
+int	ECParameters_print_fp(FILE *fp, const EC_KEY *key);
+
+/** Prints out the contents of a EC_KEY object
+ *  \param  fp   file descriptor to which the information is printed
+ *  \param  key  EC_KEY object
+ *  \param  off  line offset 
+ *  \return 1 on success and 0 if an error occurred
+ */
+int	EC_KEY_print_fp(FILE *fp, const EC_KEY *key, int off);
+
+#endif
+
+#define ECParameters_dup(x) ASN1_dup_of(EC_KEY,i2d_ECParameters,d2i_ECParameters,x)
+
+#ifndef __cplusplus
+#if defined(__SUNPRO_C)
+#  if __SUNPRO_C >= 0x520
+# pragma error_messages (default,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE)
+#  endif
+# endif
+#endif
+
+#define EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid) \
+	EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_PARAMGEN, \
+				EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, nid, NULL)
+
+
+#define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID		(EVP_PKEY_ALG_CTRL + 1)
+
+/* 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.
+ */
+void ERR_load_EC_strings(void);
+
+/* Error codes for the EC functions. */
+
+/* Function codes. */
+#define EC_F_BN_TO_FELEM				 224
+#define EC_F_COMPUTE_WNAF				 143
+#define EC_F_D2I_ECPARAMETERS				 144
+#define EC_F_D2I_ECPKPARAMETERS				 145
+#define EC_F_D2I_ECPRIVATEKEY				 146
+#define EC_F_DO_EC_KEY_PRINT				 221
+#define EC_F_ECKEY_PARAM2TYPE				 223
+#define EC_F_ECKEY_PARAM_DECODE				 212
+#define EC_F_ECKEY_PRIV_DECODE				 213
+#define EC_F_ECKEY_PRIV_ENCODE				 214
+#define EC_F_ECKEY_PUB_DECODE				 215
+#define EC_F_ECKEY_PUB_ENCODE				 216
+#define EC_F_ECKEY_TYPE2PARAM				 220
+#define EC_F_ECPARAMETERS_PRINT				 147
+#define EC_F_ECPARAMETERS_PRINT_FP			 148
+#define EC_F_ECPKPARAMETERS_PRINT			 149
+#define EC_F_ECPKPARAMETERS_PRINT_FP			 150
+#define EC_F_ECP_NIST_MOD_192				 203
+#define EC_F_ECP_NIST_MOD_224				 204
+#define EC_F_ECP_NIST_MOD_256				 205
+#define EC_F_ECP_NIST_MOD_521				 206
+#define EC_F_EC_ASN1_GROUP2CURVE			 153
+#define EC_F_EC_ASN1_GROUP2FIELDID			 154
+#define EC_F_EC_ASN1_GROUP2PARAMETERS			 155
+#define EC_F_EC_ASN1_GROUP2PKPARAMETERS			 156
+#define EC_F_EC_ASN1_PARAMETERS2GROUP			 157
+#define EC_F_EC_ASN1_PKPARAMETERS2GROUP			 158
+#define EC_F_EC_EX_DATA_SET_DATA			 211
+#define EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY		 208
+#define EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT	 159
+#define EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE		 195
+#define EC_F_EC_GF2M_SIMPLE_OCT2POINT			 160
+#define EC_F_EC_GF2M_SIMPLE_POINT2OCT			 161
+#define EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES 162
+#define EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES 163
+#define EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES	 164
+#define EC_F_EC_GFP_MONT_FIELD_DECODE			 133
+#define EC_F_EC_GFP_MONT_FIELD_ENCODE			 134
+#define EC_F_EC_GFP_MONT_FIELD_MUL			 131
+#define EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE		 209
+#define EC_F_EC_GFP_MONT_FIELD_SQR			 132
+#define EC_F_EC_GFP_MONT_GROUP_SET_CURVE		 189
+#define EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP		 135
+#define EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE		 225
+#define EC_F_EC_GFP_NISTP224_POINTS_MUL			 228
+#define EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES 226
+#define EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE		 230
+#define EC_F_EC_GFP_NISTP256_POINTS_MUL			 231
+#define EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES 232
+#define EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE		 233
+#define EC_F_EC_GFP_NISTP521_POINTS_MUL			 234
+#define EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES 235
+#define EC_F_EC_GFP_NIST_FIELD_MUL			 200
+#define EC_F_EC_GFP_NIST_FIELD_SQR			 201
+#define EC_F_EC_GFP_NIST_GROUP_SET_CURVE		 202
+#define EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT	 165
+#define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE		 166
+#define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP		 100
+#define EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR		 101
+#define EC_F_EC_GFP_SIMPLE_MAKE_AFFINE			 102
+#define EC_F_EC_GFP_SIMPLE_OCT2POINT			 103
+#define EC_F_EC_GFP_SIMPLE_POINT2OCT			 104
+#define EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE		 137
+#define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES	 167
+#define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP 105
+#define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES	 168
+#define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP 128
+#define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES	 169
+#define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP 129
+#define EC_F_EC_GROUP_CHECK				 170
+#define EC_F_EC_GROUP_CHECK_DISCRIMINANT		 171
+#define EC_F_EC_GROUP_COPY				 106
+#define EC_F_EC_GROUP_GET0_GENERATOR			 139
+#define EC_F_EC_GROUP_GET_COFACTOR			 140
+#define EC_F_EC_GROUP_GET_CURVE_GF2M			 172
+#define EC_F_EC_GROUP_GET_CURVE_GFP			 130
+#define EC_F_EC_GROUP_GET_DEGREE			 173
+#define EC_F_EC_GROUP_GET_ORDER				 141
+#define EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS		 193
+#define EC_F_EC_GROUP_GET_TRINOMIAL_BASIS		 194
+#define EC_F_EC_GROUP_NEW				 108
+#define EC_F_EC_GROUP_NEW_BY_CURVE_NAME			 174
+#define EC_F_EC_GROUP_NEW_FROM_DATA			 175
+#define EC_F_EC_GROUP_PRECOMPUTE_MULT			 142
+#define EC_F_EC_GROUP_SET_CURVE_GF2M			 176
+#define EC_F_EC_GROUP_SET_CURVE_GFP			 109
+#define EC_F_EC_GROUP_SET_EXTRA_DATA			 110
+#define EC_F_EC_GROUP_SET_GENERATOR			 111
+#define EC_F_EC_KEY_CHECK_KEY				 177
+#define EC_F_EC_KEY_COPY				 178
+#define EC_F_EC_KEY_GENERATE_KEY			 179
+#define EC_F_EC_KEY_NEW					 182
+#define EC_F_EC_KEY_PRINT				 180
+#define EC_F_EC_KEY_PRINT_FP				 181
+#define EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES	 229
+#define EC_F_EC_POINTS_MAKE_AFFINE			 136
+#define EC_F_EC_POINT_ADD				 112
+#define EC_F_EC_POINT_CMP				 113
+#define EC_F_EC_POINT_COPY				 114
+#define EC_F_EC_POINT_DBL				 115
+#define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M	 183
+#define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP	 116
+#define EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP	 117
+#define EC_F_EC_POINT_INVERT				 210
+#define EC_F_EC_POINT_IS_AT_INFINITY			 118
+#define EC_F_EC_POINT_IS_ON_CURVE			 119
+#define EC_F_EC_POINT_MAKE_AFFINE			 120
+#define EC_F_EC_POINT_MUL				 184
+#define EC_F_EC_POINT_NEW				 121
+#define EC_F_EC_POINT_OCT2POINT				 122
+#define EC_F_EC_POINT_POINT2OCT				 123
+#define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M	 185
+#define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP	 124
+#define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M	 186
+#define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP	 125
+#define EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP	 126
+#define EC_F_EC_POINT_SET_TO_INFINITY			 127
+#define EC_F_EC_PRE_COMP_DUP				 207
+#define EC_F_EC_PRE_COMP_NEW				 196
+#define EC_F_EC_WNAF_MUL				 187
+#define EC_F_EC_WNAF_PRECOMPUTE_MULT			 188
+#define EC_F_I2D_ECPARAMETERS				 190
+#define EC_F_I2D_ECPKPARAMETERS				 191
+#define EC_F_I2D_ECPRIVATEKEY				 192
+#define EC_F_I2O_ECPUBLICKEY				 151
+#define EC_F_NISTP224_PRE_COMP_NEW			 227
+#define EC_F_NISTP256_PRE_COMP_NEW			 236
+#define EC_F_NISTP521_PRE_COMP_NEW			 237
+#define EC_F_O2I_ECPUBLICKEY				 152
+#define EC_F_OLD_EC_PRIV_DECODE				 222
+#define EC_F_PKEY_EC_CTRL				 197
+#define EC_F_PKEY_EC_CTRL_STR				 198
+#define EC_F_PKEY_EC_DERIVE				 217
+#define EC_F_PKEY_EC_KEYGEN				 199
+#define EC_F_PKEY_EC_PARAMGEN				 219
+#define EC_F_PKEY_EC_SIGN				 218
+
+/* Reason codes. */
+#define EC_R_ASN1_ERROR					 115
+#define EC_R_ASN1_UNKNOWN_FIELD				 116
+#define EC_R_BIGNUM_OUT_OF_RANGE			 144
+#define EC_R_BUFFER_TOO_SMALL				 100
+#define EC_R_COORDINATES_OUT_OF_RANGE			 146
+#define EC_R_D2I_ECPKPARAMETERS_FAILURE			 117
+#define EC_R_DECODE_ERROR				 142
+#define EC_R_DISCRIMINANT_IS_ZERO			 118
+#define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE		 119
+#define EC_R_FIELD_TOO_LARGE				 143
+#define EC_R_GF2M_NOT_SUPPORTED				 147
+#define EC_R_GROUP2PKPARAMETERS_FAILURE			 120
+#define EC_R_I2D_ECPKPARAMETERS_FAILURE			 121
+#define EC_R_INCOMPATIBLE_OBJECTS			 101
+#define EC_R_INVALID_ARGUMENT				 112
+#define EC_R_INVALID_COMPRESSED_POINT			 110
+#define EC_R_INVALID_COMPRESSION_BIT			 109
+#define EC_R_INVALID_CURVE				 141
+#define EC_R_INVALID_DIGEST_TYPE			 138
+#define EC_R_INVALID_ENCODING				 102
+#define EC_R_INVALID_FIELD				 103
+#define EC_R_INVALID_FORM				 104
+#define EC_R_INVALID_GROUP_ORDER			 122
+#define EC_R_INVALID_PENTANOMIAL_BASIS			 132
+#define EC_R_INVALID_PRIVATE_KEY			 123
+#define EC_R_INVALID_TRINOMIAL_BASIS			 137
+#define EC_R_KEYS_NOT_SET				 140
+#define EC_R_MISSING_PARAMETERS				 124
+#define EC_R_MISSING_PRIVATE_KEY			 125
+#define EC_R_NOT_A_NIST_PRIME				 135
+#define EC_R_NOT_A_SUPPORTED_NIST_PRIME			 136
+#define EC_R_NOT_IMPLEMENTED				 126
+#define EC_R_NOT_INITIALIZED				 111
+#define EC_R_NO_FIELD_MOD				 133
+#define EC_R_NO_PARAMETERS_SET				 139
+#define EC_R_PASSED_NULL_PARAMETER			 134
+#define EC_R_PKPARAMETERS2GROUP_FAILURE			 127
+#define EC_R_POINT_AT_INFINITY				 106
+#define EC_R_POINT_IS_NOT_ON_CURVE			 107
+#define EC_R_SLOT_FULL					 108
+#define EC_R_UNDEFINED_GENERATOR			 113
+#define EC_R_UNDEFINED_ORDER				 128
+#define EC_R_UNKNOWN_GROUP				 129
+#define EC_R_UNKNOWN_ORDER				 114
+#define EC_R_UNSUPPORTED_FIELD				 131
+#define EC_R_WRONG_CURVE_PARAMETERS			 145
+#define EC_R_WRONG_ORDER				 130
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/jni/openssl/crypto/ec/ec2_mult.c b/jni/openssl/crypto/ec/ec2_mult.c
new file mode 100644
index 0000000..26f4a78
--- /dev/null
+++ b/jni/openssl/crypto/ec/ec2_mult.c
@@ -0,0 +1,390 @@
+/* crypto/ec/ec2_mult.c */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
+ * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
+ * to the OpenSSL project.
+ *
+ * The ECC Code is licensed pursuant to the OpenSSL open source
+ * license provided below.
+ *
+ * The software is originally written by Sheueling Chang Shantz and
+ * Douglas Stebila of Sun Microsystems Laboratories.
+ *
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2003 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).
+ *
+ */
+
+#include <openssl/err.h>
+
+#include "ec_lcl.h"
+
+#ifndef OPENSSL_NO_EC2M
+
+
+/* Compute the x-coordinate x/z for the point 2*(x/z) in Montgomery projective 
+ * coordinates.
+ * Uses algorithm Mdouble in appendix of 
+ *     Lopez, J. and Dahab, R.  "Fast multiplication on elliptic curves over 
+ *     GF(2^m) without precomputation" (CHES '99, LNCS 1717).
+ * modified to not require precomputation of c=b^{2^{m-1}}.
+ */
+static int gf2m_Mdouble(const EC_GROUP *group, BIGNUM *x, BIGNUM *z, BN_CTX *ctx)
+	{
+	BIGNUM *t1;
+	int ret = 0;
+	
+	/* Since Mdouble is static we can guarantee that ctx != NULL. */
+	BN_CTX_start(ctx);
+	t1 = BN_CTX_get(ctx);
+	if (t1 == NULL) goto err;
+
+	if (!group->meth->field_sqr(group, x, x, ctx)) goto err;
+	if (!group->meth->field_sqr(group, t1, z, ctx)) goto err;
+	if (!group->meth->field_mul(group, z, x, t1, ctx)) goto err;
+	if (!group->meth->field_sqr(group, x, x, ctx)) goto err;
+	if (!group->meth->field_sqr(group, t1, t1, ctx)) goto err;
+	if (!group->meth->field_mul(group, t1, &group->b, t1, ctx)) goto err;
+	if (!BN_GF2m_add(x, x, t1)) goto err;
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+	return ret;
+	}
+
+/* Compute the x-coordinate x1/z1 for the point (x1/z1)+(x2/x2) in Montgomery 
+ * projective coordinates.
+ * Uses algorithm Madd in appendix of 
+ *     Lopez, J. and Dahab, R.  "Fast multiplication on elliptic curves over 
+ *     GF(2^m) without precomputation" (CHES '99, LNCS 1717).
+ */
+static int gf2m_Madd(const EC_GROUP *group, const BIGNUM *x, BIGNUM *x1, BIGNUM *z1, 
+	const BIGNUM *x2, const BIGNUM *z2, BN_CTX *ctx)
+	{
+	BIGNUM *t1, *t2;
+	int ret = 0;
+	
+	/* Since Madd is static we can guarantee that ctx != NULL. */
+	BN_CTX_start(ctx);
+	t1 = BN_CTX_get(ctx);
+	t2 = BN_CTX_get(ctx);
+	if (t2 == NULL) goto err;
+
+	if (!BN_copy(t1, x)) goto err;
+	if (!group->meth->field_mul(group, x1, x1, z2, ctx)) goto err;
+	if (!group->meth->field_mul(group, z1, z1, x2, ctx)) goto err;
+	if (!group->meth->field_mul(group, t2, x1, z1, ctx)) goto err;
+	if (!BN_GF2m_add(z1, z1, x1)) goto err;
+	if (!group->meth->field_sqr(group, z1, z1, ctx)) goto err;
+	if (!group->meth->field_mul(group, x1, z1, t1, ctx)) goto err;
+	if (!BN_GF2m_add(x1, x1, t2)) goto err;
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+	return ret;
+	}
+
+/* Compute the x, y affine coordinates from the point (x1, z1) (x2, z2) 
+ * using Montgomery point multiplication algorithm Mxy() in appendix of 
+ *     Lopez, J. and Dahab, R.  "Fast multiplication on elliptic curves over 
+ *     GF(2^m) without precomputation" (CHES '99, LNCS 1717).
+ * Returns:
+ *     0 on error
+ *     1 if return value should be the point at infinity
+ *     2 otherwise
+ */
+static int gf2m_Mxy(const EC_GROUP *group, const BIGNUM *x, const BIGNUM *y, BIGNUM *x1, 
+	BIGNUM *z1, BIGNUM *x2, BIGNUM *z2, BN_CTX *ctx)
+	{
+	BIGNUM *t3, *t4, *t5;
+	int ret = 0;
+	
+	if (BN_is_zero(z1))
+		{
+		BN_zero(x2);
+		BN_zero(z2);
+		return 1;
+		}
+	
+	if (BN_is_zero(z2))
+		{
+		if (!BN_copy(x2, x)) return 0;
+		if (!BN_GF2m_add(z2, x, y)) return 0;
+		return 2;
+		}
+		
+	/* Since Mxy is static we can guarantee that ctx != NULL. */
+	BN_CTX_start(ctx);
+	t3 = BN_CTX_get(ctx);
+	t4 = BN_CTX_get(ctx);
+	t5 = BN_CTX_get(ctx);
+	if (t5 == NULL) goto err;
+
+	if (!BN_one(t5)) goto err;
+
+	if (!group->meth->field_mul(group, t3, z1, z2, ctx)) goto err;
+
+	if (!group->meth->field_mul(group, z1, z1, x, ctx)) goto err;
+	if (!BN_GF2m_add(z1, z1, x1)) goto err;
+	if (!group->meth->field_mul(group, z2, z2, x, ctx)) goto err;
+	if (!group->meth->field_mul(group, x1, z2, x1, ctx)) goto err;
+	if (!BN_GF2m_add(z2, z2, x2)) goto err;
+
+	if (!group->meth->field_mul(group, z2, z2, z1, ctx)) goto err;
+	if (!group->meth->field_sqr(group, t4, x, ctx)) goto err;
+	if (!BN_GF2m_add(t4, t4, y)) goto err;
+	if (!group->meth->field_mul(group, t4, t4, t3, ctx)) goto err;
+	if (!BN_GF2m_add(t4, t4, z2)) goto err;
+
+	if (!group->meth->field_mul(group, t3, t3, x, ctx)) goto err;
+	if (!group->meth->field_div(group, t3, t5, t3, ctx)) goto err;
+	if (!group->meth->field_mul(group, t4, t3, t4, ctx)) goto err;
+	if (!group->meth->field_mul(group, x2, x1, t3, ctx)) goto err;
+	if (!BN_GF2m_add(z2, x2, x)) goto err;
+
+	if (!group->meth->field_mul(group, z2, z2, t4, ctx)) goto err;
+	if (!BN_GF2m_add(z2, z2, y)) goto err;
+
+	ret = 2;
+
+ err:
+	BN_CTX_end(ctx);
+	return ret;
+	}
+
+/* Computes scalar*point and stores the result in r.
+ * point can not equal r.
+ * Uses algorithm 2P of
+ *     Lopez, J. and Dahab, R.  "Fast multiplication on elliptic curves over 
+ *     GF(2^m) without precomputation" (CHES '99, LNCS 1717).
+ */
+static int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
+	const EC_POINT *point, BN_CTX *ctx)
+	{
+	BIGNUM *x1, *x2, *z1, *z2;
+	int ret = 0, i;
+	BN_ULONG mask,word;
+
+	if (r == point)
+		{
+		ECerr(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, EC_R_INVALID_ARGUMENT);
+		return 0;
+		}
+	
+	/* if result should be point at infinity */
+	if ((scalar == NULL) || BN_is_zero(scalar) || (point == NULL) || 
+		EC_POINT_is_at_infinity(group, point))
+		{
+		return EC_POINT_set_to_infinity(group, r);
+		}
+
+	/* only support affine coordinates */
+	if (!point->Z_is_one) return 0;
+
+	/* Since point_multiply is static we can guarantee that ctx != NULL. */
+	BN_CTX_start(ctx);
+	x1 = BN_CTX_get(ctx);
+	z1 = BN_CTX_get(ctx);
+	if (z1 == NULL) goto err;
+
+	x2 = &r->X;
+	z2 = &r->Y;
+
+	if (!BN_GF2m_mod_arr(x1, &point->X, group->poly)) goto err; /* x1 = x */
+	if (!BN_one(z1)) goto err; /* z1 = 1 */
+	if (!group->meth->field_sqr(group, z2, x1, ctx)) goto err; /* z2 = x1^2 = x^2 */
+	if (!group->meth->field_sqr(group, x2, z2, ctx)) goto err;
+	if (!BN_GF2m_add(x2, x2, &group->b)) goto err; /* x2 = x^4 + b */
+
+	/* find top most bit and go one past it */
+	i = scalar->top - 1;
+	mask = BN_TBIT;
+	word = scalar->d[i];
+	while (!(word & mask)) mask >>= 1;
+	mask >>= 1;
+	/* if top most bit was at word break, go to next word */
+	if (!mask) 
+		{
+		i--;
+		mask = BN_TBIT;
+		}
+
+	for (; i >= 0; i--)
+		{
+		word = scalar->d[i];
+		while (mask)
+			{
+			if (word & mask)
+				{
+				if (!gf2m_Madd(group, &point->X, x1, z1, x2, z2, ctx)) goto err;
+				if (!gf2m_Mdouble(group, x2, z2, ctx)) goto err;
+				}
+			else
+				{
+				if (!gf2m_Madd(group, &point->X, x2, z2, x1, z1, ctx)) goto err;
+				if (!gf2m_Mdouble(group, x1, z1, ctx)) goto err;
+				}
+			mask >>= 1;
+			}
+		mask = BN_TBIT;
+		}
+
+	/* convert out of "projective" coordinates */
+	i = gf2m_Mxy(group, &point->X, &point->Y, x1, z1, x2, z2, ctx);
+	if (i == 0) goto err;
+	else if (i == 1) 
+		{
+		if (!EC_POINT_set_to_infinity(group, r)) goto err;
+		}
+	else
+		{
+		if (!BN_one(&r->Z)) goto err;
+		r->Z_is_one = 1;
+		}
+
+	/* GF(2^m) field elements should always have BIGNUM::neg = 0 */
+	BN_set_negative(&r->X, 0);
+	BN_set_negative(&r->Y, 0);
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+	return ret;
+	}
+
+
+/* Computes the sum
+ *     scalar*group->generator + scalars[0]*points[0] + ... + scalars[num-1]*points[num-1]
+ * gracefully ignoring NULL scalar values.
+ */
+int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
+	size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx)
+	{
+	BN_CTX *new_ctx = NULL;
+	int ret = 0;
+	size_t i;
+	EC_POINT *p=NULL;
+	EC_POINT *acc = NULL;
+
+	if (ctx == NULL)
+		{
+		ctx = new_ctx = BN_CTX_new();
+		if (ctx == NULL)
+			return 0;
+		}
+
+	/* This implementation is more efficient than the wNAF implementation for 2
+	 * or fewer points.  Use the ec_wNAF_mul implementation for 3 or more points,
+	 * or if we can perform a fast multiplication based on precomputation.
+	 */
+	if ((scalar && (num > 1)) || (num > 2) || (num == 0 && EC_GROUP_have_precompute_mult(group)))
+		{
+		ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
+		goto err;
+		}
+
+	if ((p = EC_POINT_new(group)) == NULL) goto err;
+	if ((acc = EC_POINT_new(group)) == NULL) goto err;
+
+	if (!EC_POINT_set_to_infinity(group, acc)) goto err;
+
+	if (scalar)
+		{
+		if (!ec_GF2m_montgomery_point_multiply(group, p, scalar, group->generator, ctx)) goto err;
+		if (BN_is_negative(scalar))
+			if (!group->meth->invert(group, p, ctx)) goto err;
+		if (!group->meth->add(group, acc, acc, p, ctx)) goto err;
+		}
+
+	for (i = 0; i < num; i++)
+		{
+		if (!ec_GF2m_montgomery_point_multiply(group, p, scalars[i], points[i], ctx)) goto err;
+		if (BN_is_negative(scalars[i]))
+			if (!group->meth->invert(group, p, ctx)) goto err;
+		if (!group->meth->add(group, acc, acc, p, ctx)) goto err;
+		}
+
+	if (!EC_POINT_copy(r, acc)) goto err;
+
+	ret = 1;
+
+  err:
+	if (p) EC_POINT_free(p);
+	if (acc) EC_POINT_free(acc);
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	return ret;
+	}
+
+
+/* Precomputation for point multiplication: fall back to wNAF methods
+ * because ec_GF2m_simple_mul() uses ec_wNAF_mul() if appropriate */
+
+int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
+	{
+	return ec_wNAF_precompute_mult(group, ctx);
+ 	}
+
+int ec_GF2m_have_precompute_mult(const EC_GROUP *group)
+	{
+	return ec_wNAF_have_precompute_mult(group);
+ 	}
+
+#endif
diff --git a/jni/openssl/crypto/ec/ec2_oct.c b/jni/openssl/crypto/ec/ec2_oct.c
new file mode 100644
index 0000000..f1d75e5
--- /dev/null
+++ b/jni/openssl/crypto/ec/ec2_oct.c
@@ -0,0 +1,407 @@
+/* crypto/ec/ec2_oct.c */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
+ * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
+ * to the OpenSSL project.
+ *
+ * The ECC Code is licensed pursuant to the OpenSSL open source
+ * license provided below.
+ *
+ * The software is originally written by Sheueling Chang Shantz and
+ * Douglas Stebila of Sun Microsystems Laboratories.
+ *
+ */
+/* ====================================================================
+ * 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).
+ *
+ */
+
+#include <openssl/err.h>
+
+#include "ec_lcl.h"
+
+#ifndef OPENSSL_NO_EC2M
+
+/* Calculates and sets the affine coordinates of an EC_POINT from the given
+ * compressed coordinates.  Uses algorithm 2.3.4 of SEC 1. 
+ * Note that the simple implementation only uses affine coordinates.
+ *
+ * The method is from the following publication:
+ * 
+ *     Harper, Menezes, Vanstone:
+ *     "Public-Key Cryptosystems with Very Small Key Lengths",
+ *     EUROCRYPT '92, Springer-Verlag LNCS 658,
+ *     published February 1993
+ *
+ * US Patents 6,141,420 and 6,618,483 (Vanstone, Mullin, Agnew) describe
+ * the same method, but claim no priority date earlier than July 29, 1994
+ * (and additionally fail to cite the EUROCRYPT '92 publication as prior art).
+ */
+int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
+	const BIGNUM *x_, int y_bit, BN_CTX *ctx)
+	{
+	BN_CTX *new_ctx = NULL;
+	BIGNUM *tmp, *x, *y, *z;
+	int ret = 0, z0;
+
+	/* clear error queue */
+	ERR_clear_error();
+
+	if (ctx == NULL)
+		{
+		ctx = new_ctx = BN_CTX_new();
+		if (ctx == NULL)
+			return 0;
+		}
+
+	y_bit = (y_bit != 0) ? 1 : 0;
+
+	BN_CTX_start(ctx);
+	tmp = BN_CTX_get(ctx);
+	x = BN_CTX_get(ctx);
+	y = BN_CTX_get(ctx);
+	z = BN_CTX_get(ctx);
+	if (z == NULL) goto err;
+
+	if (!BN_GF2m_mod_arr(x, x_, group->poly)) goto err;
+	if (BN_is_zero(x))
+		{
+		if (!BN_GF2m_mod_sqrt_arr(y, &group->b, group->poly, ctx)) goto err;
+		}
+	else
+		{
+		if (!group->meth->field_sqr(group, tmp, x, ctx)) goto err;
+		if (!group->meth->field_div(group, tmp, &group->b, tmp, ctx)) goto err;
+		if (!BN_GF2m_add(tmp, &group->a, tmp)) goto err;
+		if (!BN_GF2m_add(tmp, x, tmp)) goto err;
+		if (!BN_GF2m_mod_solve_quad_arr(z, tmp, group->poly, ctx))
+			{
+			unsigned long err = ERR_peek_last_error();
+			
+			if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NO_SOLUTION)
+				{
+				ERR_clear_error();
+				ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
+				}
+			else
+				ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
+			goto err;
+			}
+		z0 = (BN_is_odd(z)) ? 1 : 0;
+		if (!group->meth->field_mul(group, y, x, z, ctx)) goto err;
+		if (z0 != y_bit)
+			{
+			if (!BN_GF2m_add(y, y, x)) goto err;
+			}
+		}
+
+	if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	return ret;
+	}
+
+
+/* Converts an EC_POINT to an octet string.  
+ * If buf is NULL, the encoded length will be returned.
+ * If the length len of buf is smaller than required an error will be returned.
+ */
+size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
+	unsigned char *buf, size_t len, BN_CTX *ctx)
+	{
+	size_t ret;
+	BN_CTX *new_ctx = NULL;
+	int used_ctx = 0;
+	BIGNUM *x, *y, *yxi;
+	size_t field_len, i, skip;
+
+	if ((form != POINT_CONVERSION_COMPRESSED)
+		&& (form != POINT_CONVERSION_UNCOMPRESSED)
+		&& (form != POINT_CONVERSION_HYBRID))
+		{
+		ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
+		goto err;
+		}
+
+	if (EC_POINT_is_at_infinity(group, point))
+		{
+		/* encodes to a single 0 octet */
+		if (buf != NULL)
+			{
+			if (len < 1)
+				{
+				ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
+				return 0;
+				}
+			buf[0] = 0;
+			}
+		return 1;
+		}
+
+
+	/* ret := required output buffer length */
+	field_len = (EC_GROUP_get_degree(group) + 7) / 8;
+	ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
+
+	/* if 'buf' is NULL, just return required length */
+	if (buf != NULL)
+		{
+		if (len < ret)
+			{
+			ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
+			goto err;
+			}
+
+		if (ctx == NULL)
+			{
+			ctx = new_ctx = BN_CTX_new();
+			if (ctx == NULL)
+				return 0;
+			}
+
+		BN_CTX_start(ctx);
+		used_ctx = 1;
+		x = BN_CTX_get(ctx);
+		y = BN_CTX_get(ctx);
+		yxi = BN_CTX_get(ctx);
+		if (yxi == NULL) goto err;
+
+		if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
+
+		buf[0] = form;
+		if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x))
+			{
+			if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
+			if (BN_is_odd(yxi)) buf[0]++;
+			}
+
+		i = 1;
+		
+		skip = field_len - BN_num_bytes(x);
+		if (skip > field_len)
+			{
+			ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
+			goto err;
+			}
+		while (skip > 0)
+			{
+			buf[i++] = 0;
+			skip--;
+			}
+		skip = BN_bn2bin(x, buf + i);
+		i += skip;
+		if (i != 1 + field_len)
+			{
+			ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
+			goto err;
+			}
+
+		if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
+			{
+			skip = field_len - BN_num_bytes(y);
+			if (skip > field_len)
+				{
+				ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
+				goto err;
+				}
+			while (skip > 0)
+				{
+				buf[i++] = 0;
+				skip--;
+				}
+			skip = BN_bn2bin(y, buf + i);
+			i += skip;
+			}
+
+		if (i != ret)
+			{
+			ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
+			goto err;
+			}
+		}
+	
+	if (used_ctx)
+		BN_CTX_end(ctx);
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	return ret;
+
+ err:
+	if (used_ctx)
+		BN_CTX_end(ctx);
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	return 0;
+	}
+
+
+/* Converts an octet string representation to an EC_POINT. 
+ * Note that the simple implementation only uses affine coordinates.
+ */
+int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
+	const unsigned char *buf, size_t len, BN_CTX *ctx)
+	{
+	point_conversion_form_t form;
+	int y_bit;
+	BN_CTX *new_ctx = NULL;
+	BIGNUM *x, *y, *yxi;
+	size_t field_len, enc_len;
+	int ret = 0;
+
+	if (len == 0)
+		{
+		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
+		return 0;
+		}
+	form = buf[0];
+	y_bit = form & 1;
+	form = form & ~1U;
+	if ((form != 0)	&& (form != POINT_CONVERSION_COMPRESSED)
+		&& (form != POINT_CONVERSION_UNCOMPRESSED)
+		&& (form != POINT_CONVERSION_HYBRID))
+		{
+		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+		return 0;
+		}
+	if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
+		{
+		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+		return 0;
+		}
+
+	if (form == 0)
+		{
+		if (len != 1)
+			{
+			ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+			return 0;
+			}
+
+		return EC_POINT_set_to_infinity(group, point);
+		}
+	
+	field_len = (EC_GROUP_get_degree(group) + 7) / 8;
+	enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
+
+	if (len != enc_len)
+		{
+		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+		return 0;
+		}
+
+	if (ctx == NULL)
+		{
+		ctx = new_ctx = BN_CTX_new();
+		if (ctx == NULL)
+			return 0;
+		}
+
+	BN_CTX_start(ctx);
+	x = BN_CTX_get(ctx);
+	y = BN_CTX_get(ctx);
+	yxi = BN_CTX_get(ctx);
+	if (yxi == NULL) goto err;
+
+	if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
+	if (BN_ucmp(x, &group->field) >= 0)
+		{
+		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+		goto err;
+		}
+
+	if (form == POINT_CONVERSION_COMPRESSED)
+		{
+		if (!EC_POINT_set_compressed_coordinates_GF2m(group, point, x, y_bit, ctx)) goto err;
+		}
+	else
+		{
+		if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
+		if (BN_ucmp(y, &group->field) >= 0)
+			{
+			ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+			goto err;
+			}
+		if (form == POINT_CONVERSION_HYBRID)
+			{
+			if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
+			if (y_bit != BN_is_odd(yxi))
+				{
+				ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+				goto err;
+				}
+			}
+
+		if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
+		}
+	
+	if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
+		{
+		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
+		goto err;
+		}
+
+	ret = 1;
+	
+ err:
+	BN_CTX_end(ctx);
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	return ret;
+	}
+#endif
diff --git a/jni/openssl/crypto/ec/ec2_smpl.c b/jni/openssl/crypto/ec/ec2_smpl.c
new file mode 100644
index 0000000..e0e59c7
--- /dev/null
+++ b/jni/openssl/crypto/ec/ec2_smpl.c
@@ -0,0 +1,719 @@
+/* crypto/ec/ec2_smpl.c */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
+ * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
+ * to the OpenSSL project.
+ *
+ * The ECC Code is licensed pursuant to the OpenSSL open source
+ * license provided below.
+ *
+ * The software is originally written by Sheueling Chang Shantz and
+ * Douglas Stebila of Sun Microsystems Laboratories.
+ *
+ */
+/* ====================================================================
+ * 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).
+ *
+ */
+
+#include <openssl/err.h>
+
+#include "ec_lcl.h"
+
+#ifndef OPENSSL_NO_EC2M
+
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
+
+const EC_METHOD *EC_GF2m_simple_method(void)
+	{
+#ifdef OPENSSL_FIPS
+	return fips_ec_gf2m_simple_method();
+#else
+	static const EC_METHOD ret = {
+		EC_FLAGS_DEFAULT_OCT,
+		NID_X9_62_characteristic_two_field,
+		ec_GF2m_simple_group_init,
+		ec_GF2m_simple_group_finish,
+		ec_GF2m_simple_group_clear_finish,
+		ec_GF2m_simple_group_copy,
+		ec_GF2m_simple_group_set_curve,
+		ec_GF2m_simple_group_get_curve,
+		ec_GF2m_simple_group_get_degree,
+		ec_GF2m_simple_group_check_discriminant,
+		ec_GF2m_simple_point_init,
+		ec_GF2m_simple_point_finish,
+		ec_GF2m_simple_point_clear_finish,
+		ec_GF2m_simple_point_copy,
+		ec_GF2m_simple_point_set_to_infinity,
+		0 /* set_Jprojective_coordinates_GFp */,
+		0 /* get_Jprojective_coordinates_GFp */,
+		ec_GF2m_simple_point_set_affine_coordinates,
+		ec_GF2m_simple_point_get_affine_coordinates,
+		0,0,0,
+		ec_GF2m_simple_add,
+		ec_GF2m_simple_dbl,
+		ec_GF2m_simple_invert,
+		ec_GF2m_simple_is_at_infinity,
+		ec_GF2m_simple_is_on_curve,
+		ec_GF2m_simple_cmp,
+		ec_GF2m_simple_make_affine,
+		ec_GF2m_simple_points_make_affine,
+
+		/* the following three method functions are defined in ec2_mult.c */
+		ec_GF2m_simple_mul,
+		ec_GF2m_precompute_mult,
+		ec_GF2m_have_precompute_mult,
+
+		ec_GF2m_simple_field_mul,
+		ec_GF2m_simple_field_sqr,
+		ec_GF2m_simple_field_div,
+		0 /* field_encode */,
+		0 /* field_decode */,
+		0 /* field_set_to_one */ };
+
+	return &ret;
+#endif
+	}
+
+
+/* Initialize a GF(2^m)-based EC_GROUP structure.
+ * Note that all other members are handled by EC_GROUP_new.
+ */
+int ec_GF2m_simple_group_init(EC_GROUP *group)
+	{
+	BN_init(&group->field);
+	BN_init(&group->a);
+	BN_init(&group->b);
+	return 1;
+	}
+
+
+/* Free a GF(2^m)-based EC_GROUP structure.
+ * Note that all other members are handled by EC_GROUP_free.
+ */
+void ec_GF2m_simple_group_finish(EC_GROUP *group)
+	{
+	BN_free(&group->field);
+	BN_free(&group->a);
+	BN_free(&group->b);
+	}
+
+
+/* Clear and free a GF(2^m)-based EC_GROUP structure.
+ * Note that all other members are handled by EC_GROUP_clear_free.
+ */
+void ec_GF2m_simple_group_clear_finish(EC_GROUP *group)
+	{
+	BN_clear_free(&group->field);
+	BN_clear_free(&group->a);
+	BN_clear_free(&group->b);
+	group->poly[0] = 0;
+	group->poly[1] = 0;
+	group->poly[2] = 0;
+	group->poly[3] = 0;
+	group->poly[4] = 0;
+	group->poly[5] = -1;
+	}
+
+
+/* Copy a GF(2^m)-based EC_GROUP structure.
+ * Note that all other members are handled by EC_GROUP_copy.
+ */
+int ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
+	{
+	int i;
+	if (!BN_copy(&dest->field, &src->field)) return 0;
+	if (!BN_copy(&dest->a, &src->a)) return 0;
+	if (!BN_copy(&dest->b, &src->b)) return 0;
+	dest->poly[0] = src->poly[0];
+	dest->poly[1] = src->poly[1];
+	dest->poly[2] = src->poly[2];
+	dest->poly[3] = src->poly[3];
+	dest->poly[4] = src->poly[4];
+	dest->poly[5] = src->poly[5];
+	if (bn_wexpand(&dest->a, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) return 0;
+	if (bn_wexpand(&dest->b, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) return 0;
+	for (i = dest->a.top; i < dest->a.dmax; i++) dest->a.d[i] = 0;
+	for (i = dest->b.top; i < dest->b.dmax; i++) dest->b.d[i] = 0;
+	return 1;
+	}
+
+
+/* Set the curve parameters of an EC_GROUP structure. */
+int ec_GF2m_simple_group_set_curve(EC_GROUP *group,
+	const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
+	{
+	int ret = 0, i;
+
+	/* group->field */
+	if (!BN_copy(&group->field, p)) goto err;
+	i = BN_GF2m_poly2arr(&group->field, group->poly, 6) - 1;
+	if ((i != 5) && (i != 3))
+		{
+		ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIELD);
+		goto err;
+		}
+
+	/* group->a */
+	if (!BN_GF2m_mod_arr(&group->a, a, group->poly)) goto err;
+	if(bn_wexpand(&group->a, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) goto err;
+	for (i = group->a.top; i < group->a.dmax; i++) group->a.d[i] = 0;
+	
+	/* group->b */
+	if (!BN_GF2m_mod_arr(&group->b, b, group->poly)) goto err;
+	if(bn_wexpand(&group->b, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) goto err;
+	for (i = group->b.top; i < group->b.dmax; i++) group->b.d[i] = 0;
+		
+	ret = 1;
+  err:
+	return ret;
+	}
+
+
+/* Get the curve parameters of an EC_GROUP structure.
+ * If p, a, or b are NULL then there values will not be set but the method will return with success.
+ */
+int ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
+	{
+	int ret = 0;
+	
+	if (p != NULL)
+		{
+		if (!BN_copy(p, &group->field)) return 0;
+		}
+
+	if (a != NULL)
+		{
+		if (!BN_copy(a, &group->a)) goto err;
+		}
+
+	if (b != NULL)
+		{
+		if (!BN_copy(b, &group->b)) goto err;
+		}
+	
+	ret = 1;
+	
+  err:
+	return ret;
+	}
+
+
+/* Gets the degree of the field.  For a curve over GF(2^m) this is the value m. */
+int ec_GF2m_simple_group_get_degree(const EC_GROUP *group)
+	{
+	return BN_num_bits(&group->field)-1;
+	}
+
+
+/* Checks the discriminant of the curve.
+ * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p) 
+ */
+int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
+	{
+	int ret = 0;
+	BIGNUM *b;
+	BN_CTX *new_ctx = NULL;
+
+	if (ctx == NULL)
+		{
+		ctx = new_ctx = BN_CTX_new();
+		if (ctx == NULL)
+			{
+			ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT, ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+		}
+	BN_CTX_start(ctx);
+	b = BN_CTX_get(ctx);
+	if (b == NULL) goto err;
+
+	if (!BN_GF2m_mod_arr(b, &group->b, group->poly)) goto err;
+	
+	/* check the discriminant:
+	 * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p) 
+	 */
+	if (BN_is_zero(b)) goto err;
+
+	ret = 1;
+
+err:
+	if (ctx != NULL)
+		BN_CTX_end(ctx);
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	return ret;
+	}
+
+
+/* Initializes an EC_POINT. */
+int ec_GF2m_simple_point_init(EC_POINT *point)
+	{
+	BN_init(&point->X);
+	BN_init(&point->Y);
+	BN_init(&point->Z);
+	return 1;
+	}
+
+
+/* Frees an EC_POINT. */
+void ec_GF2m_simple_point_finish(EC_POINT *point)
+	{
+	BN_free(&point->X);
+	BN_free(&point->Y);
+	BN_free(&point->Z);
+	}
+
+
+/* Clears and frees an EC_POINT. */
+void ec_GF2m_simple_point_clear_finish(EC_POINT *point)
+	{
+	BN_clear_free(&point->X);
+	BN_clear_free(&point->Y);
+	BN_clear_free(&point->Z);
+	point->Z_is_one = 0;
+	}
+
+
+/* Copy the contents of one EC_POINT into another.  Assumes dest is initialized. */
+int ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
+	{
+	if (!BN_copy(&dest->X, &src->X)) return 0;
+	if (!BN_copy(&dest->Y, &src->Y)) return 0;
+	if (!BN_copy(&dest->Z, &src->Z)) return 0;
+	dest->Z_is_one = src->Z_is_one;
+
+	return 1;
+	}
+
+
+/* Set an EC_POINT to the point at infinity.  
+ * A point at infinity is represented by having Z=0.
+ */
+int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
+	{
+	point->Z_is_one = 0;
+	BN_zero(&point->Z);
+	return 1;
+	}
+
+
+/* Set the coordinates of an EC_POINT using affine coordinates. 
+ * Note that the simple implementation only uses affine coordinates.
+ */
+int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
+	const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
+	{
+	int ret = 0;	
+	if (x == NULL || y == NULL)
+		{
+		ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER);
+		return 0;
+		}
+
+	if (!BN_copy(&point->X, x)) goto err;
+	BN_set_negative(&point->X, 0);
+	if (!BN_copy(&point->Y, y)) goto err;
+	BN_set_negative(&point->Y, 0);
+	if (!BN_copy(&point->Z, BN_value_one())) goto err;
+	BN_set_negative(&point->Z, 0);
+	point->Z_is_one = 1;
+	ret = 1;
+
+  err:
+	return ret;
+	}
+
+
+/* Gets the affine coordinates of an EC_POINT. 
+ * Note that the simple implementation only uses affine coordinates.
+ */
+int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point,
+	BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
+	{
+	int ret = 0;
+
+	if (EC_POINT_is_at_infinity(group, point))
+		{
+		ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY);
+		return 0;
+		}
+
+	if (BN_cmp(&point->Z, BN_value_one())) 
+		{
+		ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	if (x != NULL)
+		{
+		if (!BN_copy(x, &point->X)) goto err;
+		BN_set_negative(x, 0);
+		}
+	if (y != NULL)
+		{
+		if (!BN_copy(y, &point->Y)) goto err;
+		BN_set_negative(y, 0);
+		}
+	ret = 1;
+		
+ err:
+	return ret;
+	}
+
+/* Computes a + b and stores the result in r.  r could be a or b, a could be b.
+ * Uses algorithm A.10.2 of IEEE P1363.
+ */
+int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
+	{
+	BN_CTX *new_ctx = NULL;
+	BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t;
+	int ret = 0;
+	
+	if (EC_POINT_is_at_infinity(group, a))
+		{
+		if (!EC_POINT_copy(r, b)) return 0;
+		return 1;
+		}
+
+	if (EC_POINT_is_at_infinity(group, b))
+		{
+		if (!EC_POINT_copy(r, a)) return 0;
+		return 1;
+		}
+
+	if (ctx == NULL)
+		{
+		ctx = new_ctx = BN_CTX_new();
+		if (ctx == NULL)
+			return 0;
+		}
+
+	BN_CTX_start(ctx);
+	x0 = BN_CTX_get(ctx);
+	y0 = BN_CTX_get(ctx);
+	x1 = BN_CTX_get(ctx);
+	y1 = BN_CTX_get(ctx);
+	x2 = BN_CTX_get(ctx);
+	y2 = BN_CTX_get(ctx);
+	s = BN_CTX_get(ctx);
+	t = BN_CTX_get(ctx);
+	if (t == NULL) goto err;
+
+	if (a->Z_is_one) 
+		{
+		if (!BN_copy(x0, &a->X)) goto err;
+		if (!BN_copy(y0, &a->Y)) goto err;
+		}
+	else
+		{
+		if (!EC_POINT_get_affine_coordinates_GF2m(group, a, x0, y0, ctx)) goto err;
+		}
+	if (b->Z_is_one) 
+		{
+		if (!BN_copy(x1, &b->X)) goto err;
+		if (!BN_copy(y1, &b->Y)) goto err;
+		}
+	else
+		{
+		if (!EC_POINT_get_affine_coordinates_GF2m(group, b, x1, y1, ctx)) goto err;
+		}
+
+
+	if (BN_GF2m_cmp(x0, x1))
+		{
+		if (!BN_GF2m_add(t, x0, x1)) goto err;
+		if (!BN_GF2m_add(s, y0, y1)) goto err;
+		if (!group->meth->field_div(group, s, s, t, ctx)) goto err;
+		if (!group->meth->field_sqr(group, x2, s, ctx)) goto err;
+		if (!BN_GF2m_add(x2, x2, &group->a)) goto err;
+		if (!BN_GF2m_add(x2, x2, s)) goto err;
+		if (!BN_GF2m_add(x2, x2, t)) goto err;
+		}
+	else
+		{
+		if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1))
+			{
+			if (!EC_POINT_set_to_infinity(group, r)) goto err;
+			ret = 1;
+			goto err;
+			}
+		if (!group->meth->field_div(group, s, y1, x1, ctx)) goto err;
+		if (!BN_GF2m_add(s, s, x1)) goto err;
+		
+		if (!group->meth->field_sqr(group, x2, s, ctx)) goto err;
+		if (!BN_GF2m_add(x2, x2, s)) goto err;
+		if (!BN_GF2m_add(x2, x2, &group->a)) goto err;
+		}
+
+	if (!BN_GF2m_add(y2, x1, x2)) goto err;
+	if (!group->meth->field_mul(group, y2, y2, s, ctx)) goto err;
+	if (!BN_GF2m_add(y2, y2, x2)) goto err;
+	if (!BN_GF2m_add(y2, y2, y1)) goto err;
+
+	if (!EC_POINT_set_affine_coordinates_GF2m(group, r, x2, y2, ctx)) goto err;
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	return ret;
+	}
+
+
+/* Computes 2 * a and stores the result in r.  r could be a.
+ * Uses algorithm A.10.2 of IEEE P1363.
+ */
+int ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
+	{
+	return ec_GF2m_simple_add(group, r, a, a, ctx);
+	}
+
+
+int ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
+	{
+	if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y))
+		/* point is its own inverse */
+		return 1;
+	
+	if (!EC_POINT_make_affine(group, point, ctx)) return 0;
+	return BN_GF2m_add(&point->Y, &point->X, &point->Y);
+	}
+
+
+/* Indicates whether the given point is the point at infinity. */
+int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
+	{
+	return BN_is_zero(&point->Z);
+	}
+
+
+/* Determines whether the given EC_POINT is an actual point on the curve defined
+ * in the EC_GROUP.  A point is valid if it satisfies the Weierstrass equation:
+ *      y^2 + x*y = x^3 + a*x^2 + b.
+ */
+int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
+	{
+	int ret = -1;
+	BN_CTX *new_ctx = NULL;
+	BIGNUM *lh, *y2;
+	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
+	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
+
+	if (EC_POINT_is_at_infinity(group, point))
+		return 1;
+
+	field_mul = group->meth->field_mul;
+	field_sqr = group->meth->field_sqr;	
+
+	/* only support affine coordinates */
+	if (!point->Z_is_one) return -1;
+
+	if (ctx == NULL)
+		{
+		ctx = new_ctx = BN_CTX_new();
+		if (ctx == NULL)
+			return -1;
+		}
+
+	BN_CTX_start(ctx);
+	y2 = BN_CTX_get(ctx);
+	lh = BN_CTX_get(ctx);
+	if (lh == NULL) goto err;
+
+	/* We have a curve defined by a Weierstrass equation
+	 *      y^2 + x*y = x^3 + a*x^2 + b.
+	 *  <=> x^3 + a*x^2 + x*y + b + y^2 = 0
+	 *  <=> ((x + a) * x + y ) * x + b + y^2 = 0
+	 */
+	if (!BN_GF2m_add(lh, &point->X, &group->a)) goto err;
+	if (!field_mul(group, lh, lh, &point->X, ctx)) goto err;
+	if (!BN_GF2m_add(lh, lh, &point->Y)) goto err;
+	if (!field_mul(group, lh, lh, &point->X, ctx)) goto err;
+	if (!BN_GF2m_add(lh, lh, &group->b)) goto err;
+	if (!field_sqr(group, y2, &point->Y, ctx)) goto err;
+	if (!BN_GF2m_add(lh, lh, y2)) goto err;
+	ret = BN_is_zero(lh);
+ err:
+	if (ctx) BN_CTX_end(ctx);
+	if (new_ctx) BN_CTX_free(new_ctx);
+	return ret;
+	}
+
+
+/* Indicates whether two points are equal.
+ * Return values:
+ *  -1   error
+ *   0   equal (in affine coordinates)
+ *   1   not equal
+ */
+int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
+	{
+	BIGNUM *aX, *aY, *bX, *bY;
+	BN_CTX *new_ctx = NULL;
+	int ret = -1;
+
+	if (EC_POINT_is_at_infinity(group, a))
+		{
+		return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
+		}
+
+	if (EC_POINT_is_at_infinity(group, b))
+		return 1;
+	
+	if (a->Z_is_one && b->Z_is_one)
+		{
+		return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
+		}
+
+	if (ctx == NULL)
+		{
+		ctx = new_ctx = BN_CTX_new();
+		if (ctx == NULL)
+			return -1;
+		}
+
+	BN_CTX_start(ctx);
+	aX = BN_CTX_get(ctx);
+	aY = BN_CTX_get(ctx);
+	bX = BN_CTX_get(ctx);
+	bY = BN_CTX_get(ctx);
+	if (bY == NULL) goto err;
+
+	if (!EC_POINT_get_affine_coordinates_GF2m(group, a, aX, aY, ctx)) goto err;
+	if (!EC_POINT_get_affine_coordinates_GF2m(group, b, bX, bY, ctx)) goto err;
+	ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1;
+
+  err:	
+	if (ctx) BN_CTX_end(ctx);
+	if (new_ctx) BN_CTX_free(new_ctx);
+	return ret;
+	}
+
+
+/* Forces the given EC_POINT to internally use affine coordinates. */
+int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
+	{
+	BN_CTX *new_ctx = NULL;
+	BIGNUM *x, *y;
+	int ret = 0;
+
+	if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
+		return 1;
+	
+	if (ctx == NULL)
+		{
+		ctx = new_ctx = BN_CTX_new();
+		if (ctx == NULL)
+			return 0;
+		}
+
+	BN_CTX_start(ctx);
+	x = BN_CTX_get(ctx);
+	y = BN_CTX_get(ctx);
+	if (y == NULL) goto err;
+	
+	if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
+	if (!BN_copy(&point->X, x)) goto err;
+	if (!BN_copy(&point->Y, y)) goto err;
+	if (!BN_one(&point->Z)) goto err;
+	
+	ret = 1;		
+
+  err:
+	if (ctx) BN_CTX_end(ctx);
+	if (new_ctx) BN_CTX_free(new_ctx);
+	return ret;
+	}
+
+
+/* Forces each of the EC_POINTs in the given array to use affine coordinates. */
+int ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
+	{
+	size_t i;
+
+	for (i = 0; i < num; i++)
+		{
+		if (!group->meth->make_affine(group, points[i], ctx)) return 0;
+		}
+
+	return 1;
+	}
+
+
+/* Wrapper to simple binary polynomial field multiplication implementation. */
+int ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
+	{
+	return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx);
+	}
+
+
+/* Wrapper to simple binary polynomial field squaring implementation. */
+int ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
+	{
+	return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx);
+	}
+
+
+/* Wrapper to simple binary polynomial field division implementation. */
+int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
+	{
+	return BN_GF2m_mod_div(r, a, b, &group->field, ctx);
+	}
+
+#endif
diff --git a/jni/openssl/crypto/ec/ec_ameth.c b/jni/openssl/crypto/ec/ec_ameth.c
new file mode 100644
index 0000000..83909c1
--- /dev/null
+++ b/jni/openssl/crypto/ec/ec_ameth.c
@@ -0,0 +1,660 @@
+/* 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,
+	0,
+
+	int_ec_free,
+	ec_pkey_ctrl,
+	old_ec_priv_decode,
+	old_ec_priv_encode
+	};
diff --git a/jni/openssl/crypto/ec/ec_asn1.c b/jni/openssl/crypto/ec/ec_asn1.c
new file mode 100644
index 0000000..175eec5
--- /dev/null
+++ b/jni/openssl/crypto/ec/ec_asn1.c
@@ -0,0 +1,1443 @@
+/* crypto/ec/ec_asn1.c */
+/*
+ * Written by Nils Larsch for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 2000-2003 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 <string.h>
+#include "ec_lcl.h"
+#include <openssl/err.h>
+#include <openssl/asn1t.h>
+#include <openssl/objects.h>
+
+
+int EC_GROUP_get_basis_type(const EC_GROUP *group)
+	{
+	int i=0;
+
+	if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
+		NID_X9_62_characteristic_two_field)
+		/* everything else is currently not supported */
+		return 0;
+
+	while (group->poly[i] != 0)
+		i++;
+
+	if (i == 4)
+		return NID_X9_62_ppBasis;
+	else if (i == 2)
+		return NID_X9_62_tpBasis;
+	else
+		/* everything else is currently not supported */
+		return 0;
+	}
+#ifndef OPENSSL_NO_EC2M
+int EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k)
+	{
+	if (group == NULL)
+		return 0;
+
+	if (EC_GROUP_method_of(group)->group_set_curve != ec_GF2m_simple_group_set_curve
+	    || !((group->poly[0] != 0) && (group->poly[1] != 0) && (group->poly[2] == 0)))
+		{
+		ECerr(EC_F_EC_GROUP_GET_TRINOMIAL_BASIS, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+
+	if (k)
+		*k = group->poly[1];
+
+	return 1;
+	}
+int EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1,
+	unsigned int *k2, unsigned int *k3)
+	{
+	if (group == NULL)
+		return 0;
+
+	if (EC_GROUP_method_of(group)->group_set_curve != ec_GF2m_simple_group_set_curve
+	    || !((group->poly[0] != 0) && (group->poly[1] != 0) && (group->poly[2] != 0) && (group->poly[3] != 0) && (group->poly[4] == 0)))
+		{
+		ECerr(EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+
+	if (k1)
+		*k1 = group->poly[3];
+	if (k2)
+		*k2 = group->poly[2];
+	if (k3)
+		*k3 = group->poly[1];
+
+	return 1;
+	}
+#endif
+
+
+/* some structures needed for the asn1 encoding */
+typedef struct x9_62_pentanomial_st {
+	long k1;
+	long k2;
+	long k3;
+	} X9_62_PENTANOMIAL;
+
+typedef struct x9_62_characteristic_two_st {
+	long m;
+	ASN1_OBJECT  *type;
+	union	{
+		char *ptr;
+		/* NID_X9_62_onBasis */
+		ASN1_NULL    *onBasis;
+		/* NID_X9_62_tpBasis */
+		ASN1_INTEGER *tpBasis;
+		/* NID_X9_62_ppBasis */
+		X9_62_PENTANOMIAL *ppBasis;
+		/* anything else */
+		ASN1_TYPE *other;
+		} p;
+	} X9_62_CHARACTERISTIC_TWO;
+
+typedef struct x9_62_fieldid_st {
+        ASN1_OBJECT *fieldType;
+	union	{
+		char *ptr;
+		/* NID_X9_62_prime_field */
+		ASN1_INTEGER *prime;
+		/* NID_X9_62_characteristic_two_field */
+		X9_62_CHARACTERISTIC_TWO *char_two;
+		/* anything else */
+		ASN1_TYPE *other;
+		} p;
+	} X9_62_FIELDID;
+
+typedef struct x9_62_curve_st {
+        ASN1_OCTET_STRING *a;
+        ASN1_OCTET_STRING *b;
+        ASN1_BIT_STRING   *seed;
+        } X9_62_CURVE;
+
+typedef struct ec_parameters_st {
+        long              version;
+        X9_62_FIELDID     *fieldID;
+        X9_62_CURVE       *curve;
+        ASN1_OCTET_STRING *base;
+        ASN1_INTEGER      *order;
+        ASN1_INTEGER      *cofactor;
+        } ECPARAMETERS;
+
+struct ecpk_parameters_st {
+	int	type;
+	union {
+		ASN1_OBJECT  *named_curve;
+		ECPARAMETERS *parameters;
+		ASN1_NULL    *implicitlyCA;
+	} value;
+	}/* ECPKPARAMETERS */;
+
+/* SEC1 ECPrivateKey */
+typedef struct ec_privatekey_st {
+	long              version;
+	ASN1_OCTET_STRING *privateKey;
+        ECPKPARAMETERS    *parameters;
+	ASN1_BIT_STRING   *publicKey;
+	} EC_PRIVATEKEY;
+
+/* the OpenSSL ASN.1 definitions */
+ASN1_SEQUENCE(X9_62_PENTANOMIAL) = {
+	ASN1_SIMPLE(X9_62_PENTANOMIAL, k1, LONG),
+	ASN1_SIMPLE(X9_62_PENTANOMIAL, k2, LONG),
+	ASN1_SIMPLE(X9_62_PENTANOMIAL, k3, LONG)
+} ASN1_SEQUENCE_END(X9_62_PENTANOMIAL)
+
+DECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL)
+IMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL)
+
+ASN1_ADB_TEMPLATE(char_two_def) = ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.other, ASN1_ANY);
+
+ASN1_ADB(X9_62_CHARACTERISTIC_TWO) = {
+	ADB_ENTRY(NID_X9_62_onBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.onBasis, ASN1_NULL)),
+	ADB_ENTRY(NID_X9_62_tpBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.tpBasis, ASN1_INTEGER)),
+	ADB_ENTRY(NID_X9_62_ppBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.ppBasis, X9_62_PENTANOMIAL))
+} ASN1_ADB_END(X9_62_CHARACTERISTIC_TWO, 0, type, 0, &char_two_def_tt, NULL);
+
+ASN1_SEQUENCE(X9_62_CHARACTERISTIC_TWO) = {
+	ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, m, LONG),
+	ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, type, ASN1_OBJECT),
+	ASN1_ADB_OBJECT(X9_62_CHARACTERISTIC_TWO)
+} ASN1_SEQUENCE_END(X9_62_CHARACTERISTIC_TWO)
+
+DECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO)
+IMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO)
+
+ASN1_ADB_TEMPLATE(fieldID_def) = ASN1_SIMPLE(X9_62_FIELDID, p.other, ASN1_ANY);
+
+ASN1_ADB(X9_62_FIELDID) = {
+	ADB_ENTRY(NID_X9_62_prime_field, ASN1_SIMPLE(X9_62_FIELDID, p.prime, ASN1_INTEGER)),
+	ADB_ENTRY(NID_X9_62_characteristic_two_field, ASN1_SIMPLE(X9_62_FIELDID, p.char_two, X9_62_CHARACTERISTIC_TWO))
+} ASN1_ADB_END(X9_62_FIELDID, 0, fieldType, 0, &fieldID_def_tt, NULL);
+
+ASN1_SEQUENCE(X9_62_FIELDID) = {
+	ASN1_SIMPLE(X9_62_FIELDID, fieldType, ASN1_OBJECT),
+	ASN1_ADB_OBJECT(X9_62_FIELDID)
+} ASN1_SEQUENCE_END(X9_62_FIELDID)
+
+ASN1_SEQUENCE(X9_62_CURVE) = {
+	ASN1_SIMPLE(X9_62_CURVE, a, ASN1_OCTET_STRING),
+	ASN1_SIMPLE(X9_62_CURVE, b, ASN1_OCTET_STRING),
+	ASN1_OPT(X9_62_CURVE, seed, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END(X9_62_CURVE)
+
+ASN1_SEQUENCE(ECPARAMETERS) = {
+	ASN1_SIMPLE(ECPARAMETERS, version, LONG),
+	ASN1_SIMPLE(ECPARAMETERS, fieldID, X9_62_FIELDID),
+	ASN1_SIMPLE(ECPARAMETERS, curve, X9_62_CURVE),
+	ASN1_SIMPLE(ECPARAMETERS, base, ASN1_OCTET_STRING),
+	ASN1_SIMPLE(ECPARAMETERS, order, ASN1_INTEGER),
+	ASN1_OPT(ECPARAMETERS, cofactor, ASN1_INTEGER)
+} ASN1_SEQUENCE_END(ECPARAMETERS)
+
+DECLARE_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS)
+IMPLEMENT_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS)
+
+ASN1_CHOICE(ECPKPARAMETERS) = {
+	ASN1_SIMPLE(ECPKPARAMETERS, value.named_curve, ASN1_OBJECT),
+	ASN1_SIMPLE(ECPKPARAMETERS, value.parameters, ECPARAMETERS),
+	ASN1_SIMPLE(ECPKPARAMETERS, value.implicitlyCA, ASN1_NULL)
+} ASN1_CHOICE_END(ECPKPARAMETERS)
+
+DECLARE_ASN1_FUNCTIONS_const(ECPKPARAMETERS)
+DECLARE_ASN1_ENCODE_FUNCTIONS_const(ECPKPARAMETERS, ECPKPARAMETERS)
+IMPLEMENT_ASN1_FUNCTIONS_const(ECPKPARAMETERS)
+
+ASN1_SEQUENCE(EC_PRIVATEKEY) = {
+	ASN1_SIMPLE(EC_PRIVATEKEY, version, LONG),
+	ASN1_SIMPLE(EC_PRIVATEKEY, privateKey, ASN1_OCTET_STRING),
+	ASN1_EXP_OPT(EC_PRIVATEKEY, parameters, ECPKPARAMETERS, 0),
+	ASN1_EXP_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING, 1)
+} ASN1_SEQUENCE_END(EC_PRIVATEKEY)
+
+DECLARE_ASN1_FUNCTIONS_const(EC_PRIVATEKEY)
+DECLARE_ASN1_ENCODE_FUNCTIONS_const(EC_PRIVATEKEY, EC_PRIVATEKEY)
+IMPLEMENT_ASN1_FUNCTIONS_const(EC_PRIVATEKEY)
+
+/* some declarations of internal function */
+
+/* ec_asn1_group2field() sets the values in a X9_62_FIELDID object */ 
+static int ec_asn1_group2fieldid(const EC_GROUP *, X9_62_FIELDID *);
+/* ec_asn1_group2curve() sets the values in a X9_62_CURVE object */ 
+static int ec_asn1_group2curve(const EC_GROUP *, X9_62_CURVE *);
+/* ec_asn1_parameters2group() creates a EC_GROUP object from a
+ * ECPARAMETERS object */
+static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *); 
+/* ec_asn1_group2parameters() creates a ECPARAMETERS object from a 
+ * EC_GROUP object */
+static ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *,ECPARAMETERS *);
+/* ec_asn1_pkparameters2group() creates a EC_GROUP object from a
+ * ECPKPARAMETERS object */
+static EC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *); 
+/* ec_asn1_group2pkparameters() creates a ECPKPARAMETERS object from a 
+ * EC_GROUP object */
+static ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *, 
+	ECPKPARAMETERS *);
+
+
+/* the function definitions */
+
+static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field)
+	{
+	int			ok=0, nid;
+	BIGNUM			*tmp = NULL;
+	
+	if (group == NULL || field == NULL)
+		return 0;
+
+	/* clear the old values (if necessary) */
+	if (field->fieldType != NULL)
+		ASN1_OBJECT_free(field->fieldType);
+	if (field->p.other != NULL)
+		ASN1_TYPE_free(field->p.other);
+
+	nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group));
+	/* set OID for the field */
+	if ((field->fieldType = OBJ_nid2obj(nid)) == NULL)
+		{
+		ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB);
+		goto err;
+		}
+
+	if (nid == NID_X9_62_prime_field)
+		{
+		if ((tmp = BN_new()) == NULL) 
+			{
+			ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+		/* the parameters are specified by the prime number p */
+		if (!EC_GROUP_get_curve_GFp(group, tmp, NULL, NULL, NULL))
+			{
+			ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB);
+			goto err;
+			}
+		/* set the prime number */
+		field->p.prime = BN_to_ASN1_INTEGER(tmp,NULL);
+		if (field->p.prime == NULL)
+			{
+			ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB);
+			goto err;
+			}
+		}
+	else	/* nid == NID_X9_62_characteristic_two_field */
+#ifdef OPENSSL_NO_EC2M
+		{
+		ECerr(EC_F_EC_ASN1_GROUP2FIELDID, EC_R_GF2M_NOT_SUPPORTED);
+		goto err;
+		}
+#else
+		{
+		int		field_type;
+		X9_62_CHARACTERISTIC_TWO *char_two;
+
+		field->p.char_two = X9_62_CHARACTERISTIC_TWO_new();
+		char_two = field->p.char_two;
+
+		if (char_two == NULL)
+			{
+			ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+	
+		char_two->m = (long)EC_GROUP_get_degree(group);
+
+		field_type = EC_GROUP_get_basis_type(group);
+
+		if (field_type == 0)
+			{
+			ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB);
+			goto err;
+			}
+		/* set base type OID */
+		if ((char_two->type = OBJ_nid2obj(field_type)) == NULL)
+			{
+			ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB);
+			goto err;
+			}
+
+		if (field_type == NID_X9_62_tpBasis)
+			{
+			unsigned int k;
+
+			if (!EC_GROUP_get_trinomial_basis(group, &k))
+				goto err;
+
+			char_two->p.tpBasis = ASN1_INTEGER_new();
+			if (!char_two->p.tpBasis)
+				{
+				ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
+				goto err;
+				}
+			if (!ASN1_INTEGER_set(char_two->p.tpBasis, (long)k))
+				{
+				ECerr(EC_F_EC_ASN1_GROUP2FIELDID,
+					ERR_R_ASN1_LIB);
+				goto err;
+				}
+			}
+		else if (field_type == NID_X9_62_ppBasis)
+			{
+			unsigned int k1, k2, k3;
+
+			if (!EC_GROUP_get_pentanomial_basis(group, &k1, &k2, &k3))
+				goto err;
+
+			char_two->p.ppBasis = X9_62_PENTANOMIAL_new();
+			if (!char_two->p.ppBasis)
+				{
+				ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
+				goto err;
+				}
+
+			/* set k? values */
+			char_two->p.ppBasis->k1 = (long)k1;
+			char_two->p.ppBasis->k2 = (long)k2;
+			char_two->p.ppBasis->k3 = (long)k3;
+			}
+		else /* field_type == NID_X9_62_onBasis */
+			{
+			/* for ONB the parameters are (asn1) NULL */
+			char_two->p.onBasis = ASN1_NULL_new();
+			if (!char_two->p.onBasis)
+				{
+				ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
+				goto err;
+				}
+			}
+		}
+#endif
+
+	ok = 1;
+
+err :	if (tmp)
+		BN_free(tmp);
+	return(ok);
+}
+
+static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
+	{
+	int           ok=0, nid;
+	BIGNUM        *tmp_1=NULL, *tmp_2=NULL;
+	unsigned char *buffer_1=NULL, *buffer_2=NULL,
+	              *a_buf=NULL, *b_buf=NULL;
+	size_t        len_1, len_2;
+	unsigned char char_zero = 0;
+
+	if (!group || !curve || !curve->a || !curve->b)
+		return 0;
+
+	if ((tmp_1 = BN_new()) == NULL || (tmp_2 = BN_new()) == NULL)
+		{
+		ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+
+	nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group));
+
+	/* get a and b */
+	if (nid == NID_X9_62_prime_field)
+		{
+		if (!EC_GROUP_get_curve_GFp(group, NULL, tmp_1, tmp_2, NULL))
+			{
+			ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB);
+			goto err;
+			}
+		}
+#ifndef OPENSSL_NO_EC2M
+	else	/* nid == NID_X9_62_characteristic_two_field */
+		{
+		if (!EC_GROUP_get_curve_GF2m(group, NULL, tmp_1, tmp_2, NULL))
+			{
+			ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB);
+			goto err;
+			}
+		}
+#endif
+	len_1 = (size_t)BN_num_bytes(tmp_1);
+	len_2 = (size_t)BN_num_bytes(tmp_2);
+
+	if (len_1 == 0)
+		{
+		/* len_1 == 0 => a == 0 */
+		a_buf = &char_zero;
+		len_1 = 1;
+		}
+	else
+		{
+		if ((buffer_1 = OPENSSL_malloc(len_1)) == NULL)
+			{
+			ECerr(EC_F_EC_ASN1_GROUP2CURVE,
+			      ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+		if ( (len_1 = BN_bn2bin(tmp_1, buffer_1)) == 0)
+			{
+			ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB);
+			goto err;
+			}
+		a_buf = buffer_1;
+		}
+
+	if (len_2 == 0)
+		{
+		/* len_2 == 0 => b == 0 */
+		b_buf = &char_zero;
+		len_2 = 1;
+		}
+	else
+		{
+		if ((buffer_2 = OPENSSL_malloc(len_2)) == NULL)
+			{
+			ECerr(EC_F_EC_ASN1_GROUP2CURVE,
+			      ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+		if ( (len_2 = BN_bn2bin(tmp_2, buffer_2)) == 0)
+			{
+			ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB);
+			goto err;
+			}
+		b_buf = buffer_2;
+		}
+	
+	/* set a and b */
+	if (!M_ASN1_OCTET_STRING_set(curve->a, a_buf, len_1) ||
+	    !M_ASN1_OCTET_STRING_set(curve->b, b_buf, len_2))
+		{
+		ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB);
+		goto err;
+		}
+	
+	/* set the seed (optional) */
+	if (group->seed)
+		{	
+		if (!curve->seed)
+			if ((curve->seed = ASN1_BIT_STRING_new()) == NULL)
+				{
+				ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
+				goto err;
+				}
+		curve->seed->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
+		curve->seed->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+		if (!ASN1_BIT_STRING_set(curve->seed, group->seed, 
+		                         (int)group->seed_len))
+			{
+			ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB);
+			goto err;
+			}
+		}
+	else
+		{
+		if (curve->seed)
+			{
+			ASN1_BIT_STRING_free(curve->seed);
+			curve->seed = NULL;
+			}
+		}
+
+	ok = 1;
+
+err:	if (buffer_1)
+		OPENSSL_free(buffer_1);
+	if (buffer_2)
+		OPENSSL_free(buffer_2);
+	if (tmp_1)
+		BN_free(tmp_1);
+	if (tmp_2)
+		BN_free(tmp_2);
+	return(ok);
+	}
+
+static ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *group,
+                                              ECPARAMETERS *param)
+	{
+	int	ok=0;
+	size_t  len=0;
+	ECPARAMETERS   *ret=NULL;
+	BIGNUM	       *tmp=NULL;
+	unsigned char  *buffer=NULL;
+	const EC_POINT *point=NULL;
+	point_conversion_form_t form;
+
+	if ((tmp = BN_new()) == NULL)
+		{
+		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+
+	if (param == NULL)
+	{
+		if ((ret = ECPARAMETERS_new()) == NULL)
+			{
+			ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, 
+			      ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+	}
+	else
+		ret = param;
+
+	/* set the version (always one) */
+	ret->version = (long)0x1;
+
+	/* set the fieldID */
+	if (!ec_asn1_group2fieldid(group, ret->fieldID))
+		{
+		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
+		goto err;
+		}
+
+	/* set the curve */
+	if (!ec_asn1_group2curve(group, ret->curve))
+		{
+		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
+		goto err;
+		}
+
+	/* set the base point */
+	if ((point = EC_GROUP_get0_generator(group)) == NULL)
+		{
+		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, EC_R_UNDEFINED_GENERATOR);
+		goto err;
+		}
+
+	form = EC_GROUP_get_point_conversion_form(group);
+
+	len = EC_POINT_point2oct(group, point, form, NULL, len, NULL);
+	if (len == 0)
+		{
+		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
+		goto err;
+		}
+	if ((buffer = OPENSSL_malloc(len)) == NULL)
+		{
+		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+	if (!EC_POINT_point2oct(group, point, form, buffer, len, NULL))
+		{
+		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
+		goto err;
+		}
+	if (ret->base == NULL && (ret->base = ASN1_OCTET_STRING_new()) == NULL)
+		{
+		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+	if (!ASN1_OCTET_STRING_set(ret->base, buffer, len))
+		{
+		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB);
+		goto err;
+		}
+
+	/* set the order */
+	if (!EC_GROUP_get_order(group, tmp, NULL))
+		{
+		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
+		goto err;
+		}
+	ret->order = BN_to_ASN1_INTEGER(tmp, ret->order);
+	if (ret->order == NULL)
+		{
+		ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB);
+		goto err;
+		}
+
+	/* set the cofactor (optional) */
+	if (EC_GROUP_get_cofactor(group, tmp, NULL))
+		{
+		ret->cofactor = BN_to_ASN1_INTEGER(tmp, ret->cofactor);
+		if (ret->cofactor == NULL)
+			{
+			ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB);
+			goto err;
+			}
+		}
+
+	ok = 1;
+
+err :	if(!ok)
+		{
+		if (ret && !param)
+			ECPARAMETERS_free(ret);
+		ret = NULL;
+		}
+	if (tmp)
+		BN_free(tmp);
+	if (buffer)
+		OPENSSL_free(buffer);
+	return(ret);
+	}
+
+ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *group, 
+                                           ECPKPARAMETERS *params)
+	{
+	int            ok = 1, tmp;
+	ECPKPARAMETERS *ret = params;
+
+	if (ret == NULL)
+		{
+		if ((ret = ECPKPARAMETERS_new()) == NULL)
+			{
+			ECerr(EC_F_EC_ASN1_GROUP2PKPARAMETERS, 
+			      ERR_R_MALLOC_FAILURE);
+			return NULL;
+			}
+		}
+	else
+		{
+		if (ret->type == 0 && ret->value.named_curve)
+			ASN1_OBJECT_free(ret->value.named_curve);
+		else if (ret->type == 1 && ret->value.parameters)
+			ECPARAMETERS_free(ret->value.parameters);
+		}
+
+	if (EC_GROUP_get_asn1_flag(group))
+		{
+		/* use the asn1 OID to describe the
+		 * the elliptic curve parameters
+		 */
+		tmp = EC_GROUP_get_curve_name(group);
+		if (tmp)
+			{
+			ret->type = 0;
+			if ((ret->value.named_curve = OBJ_nid2obj(tmp)) == NULL)
+				ok = 0;
+			}
+		else
+			/* we don't kmow the nid => ERROR */
+			ok = 0;
+		}
+	else
+		{	
+		/* use the ECPARAMETERS structure */
+		ret->type = 1;
+		if ((ret->value.parameters = ec_asn1_group2parameters(
+		     group, NULL)) == NULL)
+			ok = 0;
+		}
+
+	if (!ok)
+		{
+		ECPKPARAMETERS_free(ret);
+		return NULL;
+		}
+	return ret;
+	}
+
+static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params)
+	{
+	int			ok = 0, tmp;
+	EC_GROUP		*ret = NULL;
+	BIGNUM			*p = NULL, *a = NULL, *b = NULL;
+	EC_POINT		*point=NULL;
+	long    		field_bits;
+
+	if (!params->fieldID || !params->fieldID->fieldType || 
+	    !params->fieldID->p.ptr)
+		{
+		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
+		goto err;
+		}
+
+	/* now extract the curve parameters a and b */
+	if (!params->curve || !params->curve->a || 
+	    !params->curve->a->data || !params->curve->b ||
+	    !params->curve->b->data)
+		{
+		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
+		goto err;
+		}
+	a = BN_bin2bn(params->curve->a->data, params->curve->a->length, NULL);
+	if (a == NULL)
+		{
+		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB);
+		goto err;
+		}
+	b = BN_bin2bn(params->curve->b->data, params->curve->b->length, NULL);
+	if (b == NULL)
+		{
+		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB);
+		goto err;
+		}
+
+	/* get the field parameters */
+	tmp = OBJ_obj2nid(params->fieldID->fieldType);
+	if (tmp == NID_X9_62_characteristic_two_field)
+#ifdef OPENSSL_NO_EC2M
+		{
+		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_GF2M_NOT_SUPPORTED);
+		goto err;
+		}
+#else
+		{
+		X9_62_CHARACTERISTIC_TWO *char_two;
+
+		char_two = params->fieldID->p.char_two;
+
+		field_bits = char_two->m;
+		if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS)
+			{
+			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_FIELD_TOO_LARGE);
+			goto err;
+			}
+
+		if ((p = BN_new()) == NULL)
+			{
+			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+
+		/* get the base type */
+		tmp = OBJ_obj2nid(char_two->type);
+
+		if (tmp ==  NID_X9_62_tpBasis)
+			{
+			long tmp_long;
+
+			if (!char_two->p.tpBasis)
+				{
+				ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
+				goto err;
+				}
+
+			tmp_long = ASN1_INTEGER_get(char_two->p.tpBasis);
+
+			if (!(char_two->m > tmp_long && tmp_long > 0))
+				{
+				ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_TRINOMIAL_BASIS);
+				goto err;
+				}
+			
+			/* create the polynomial */
+			if (!BN_set_bit(p, (int)char_two->m))
+				goto err;
+			if (!BN_set_bit(p, (int)tmp_long))
+				goto err;
+			if (!BN_set_bit(p, 0))
+				goto err;
+			}
+		else if (tmp == NID_X9_62_ppBasis)
+			{
+			X9_62_PENTANOMIAL *penta;
+
+			penta = char_two->p.ppBasis;
+			if (!penta)
+				{
+				ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
+				goto err;
+				}
+
+			if (!(char_two->m > penta->k3 && penta->k3 > penta->k2 && penta->k2 > penta->k1 && penta->k1 > 0))
+				{
+				ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_PENTANOMIAL_BASIS);
+				goto err;
+				}
+			
+			/* create the polynomial */
+			if (!BN_set_bit(p, (int)char_two->m)) goto err;
+			if (!BN_set_bit(p, (int)penta->k1)) goto err;
+			if (!BN_set_bit(p, (int)penta->k2)) goto err;
+			if (!BN_set_bit(p, (int)penta->k3)) goto err;
+			if (!BN_set_bit(p, 0)) goto err;
+			}
+		else if (tmp == NID_X9_62_onBasis)
+			{
+			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_NOT_IMPLEMENTED);
+			goto err;
+			}
+		else /* error */
+			{
+			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
+			goto err;
+			}
+
+		/* create the EC_GROUP structure */
+		ret = EC_GROUP_new_curve_GF2m(p, a, b, NULL);
+		}
+#endif
+	else if (tmp == NID_X9_62_prime_field)
+		{
+		/* we have a curve over a prime field */
+		/* extract the prime number */
+		if (!params->fieldID->p.prime)
+			{
+			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
+			goto err;
+			}
+		p = ASN1_INTEGER_to_BN(params->fieldID->p.prime, NULL);
+		if (p == NULL)
+			{
+			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB);
+			goto err;
+			}
+
+		if (BN_is_negative(p) || BN_is_zero(p))
+			{
+			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_FIELD);
+			goto err;
+			}
+
+		field_bits = BN_num_bits(p);
+		if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS)
+			{
+			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_FIELD_TOO_LARGE);
+			goto err;
+			}
+
+		/* create the EC_GROUP structure */
+		ret = EC_GROUP_new_curve_GFp(p, a, b, NULL);
+		}
+	else
+		{
+		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_FIELD);
+		goto err;
+		}
+
+	if (ret == NULL)
+		{
+		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB);
+		goto err;
+		}
+
+	/* extract seed (optional) */
+	if (params->curve->seed != NULL)
+		{
+		if (ret->seed != NULL)
+			OPENSSL_free(ret->seed);
+		if (!(ret->seed = OPENSSL_malloc(params->curve->seed->length)))
+			{
+			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, 
+			      ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+		memcpy(ret->seed, params->curve->seed->data, 
+		       params->curve->seed->length);
+		ret->seed_len = params->curve->seed->length;
+		}
+
+	if (!params->order || !params->base || !params->base->data)
+		{
+		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
+		goto err;
+		}
+
+	if ((point = EC_POINT_new(ret)) == NULL) goto err;
+
+	/* set the point conversion form */
+	EC_GROUP_set_point_conversion_form(ret, (point_conversion_form_t)
+				(params->base->data[0] & ~0x01));
+
+	/* extract the ec point */
+	if (!EC_POINT_oct2point(ret, point, params->base->data, 
+		                params->base->length, NULL))
+		{
+		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB);
+		goto err;
+		}
+
+	/* extract the order */
+	if ((a = ASN1_INTEGER_to_BN(params->order, a)) == NULL)
+		{
+		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB);
+		goto err;
+		}
+	if (BN_is_negative(a) || BN_is_zero(a))
+		{
+		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_GROUP_ORDER);
+		goto err;
+		}
+	if (BN_num_bits(a) > (int)field_bits + 1) /* Hasse bound */
+		{
+		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_GROUP_ORDER);
+		goto err;
+		}
+	
+	/* extract the cofactor (optional) */
+	if (params->cofactor == NULL)
+		{
+		if (b)
+			{
+			BN_free(b);
+			b = NULL;
+			}
+		}
+	else
+		if ((b = ASN1_INTEGER_to_BN(params->cofactor, b)) == NULL)
+			{
+			ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB);
+			goto err;
+			}
+	/* set the generator, order and cofactor (if present) */
+	if (!EC_GROUP_set_generator(ret, point, a, b))
+		{
+		ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB);
+		goto err;
+		}
+
+	ok = 1;
+
+err:	if (!ok)
+		{
+		if (ret) 
+			EC_GROUP_clear_free(ret);
+		ret = NULL;
+		}
+
+	if (p)	
+		BN_free(p);
+	if (a)	
+		BN_free(a);
+	if (b)	
+		BN_free(b);
+	if (point)	
+		EC_POINT_free(point);
+	return(ret);
+}
+
+EC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *params)
+	{
+	EC_GROUP *ret=NULL;
+	int      tmp=0;
+
+	if (params == NULL)
+		{
+		ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, 
+		      EC_R_MISSING_PARAMETERS);
+		return NULL;
+		}
+
+	if (params->type == 0)
+		{ /* the curve is given by an OID */
+		tmp = OBJ_obj2nid(params->value.named_curve);
+		if ((ret = EC_GROUP_new_by_curve_name(tmp)) == NULL)
+			{
+			ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, 
+			      EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
+			return NULL;
+			}
+		EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_NAMED_CURVE);
+		}
+	else if (params->type == 1)
+		{ /* the parameters are given by a ECPARAMETERS
+		   * structure */
+		ret = ec_asn1_parameters2group(params->value.parameters);
+		if (!ret)
+			{
+			ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, ERR_R_EC_LIB);
+			return NULL;
+			}
+		EC_GROUP_set_asn1_flag(ret, 0x0);
+		}
+	else if (params->type == 2)
+		{ /* implicitlyCA */
+		return NULL;
+		}
+	else
+		{
+		ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, EC_R_ASN1_ERROR);
+		return NULL;
+		}
+
+	return ret;
+	}
+
+/* EC_GROUP <-> DER encoding of ECPKPARAMETERS */
+
+EC_GROUP *d2i_ECPKParameters(EC_GROUP **a, const unsigned char **in, long len)
+	{
+	EC_GROUP	*group  = NULL;
+	ECPKPARAMETERS	*params = NULL;
+
+	if ((params = d2i_ECPKPARAMETERS(NULL, in, len)) == NULL)
+		{
+		ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_D2I_ECPKPARAMETERS_FAILURE);
+		ECPKPARAMETERS_free(params);
+		return NULL;
+		}
+	
+	if ((group = ec_asn1_pkparameters2group(params)) == NULL)
+		{
+		ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_PKPARAMETERS2GROUP_FAILURE);
+		ECPKPARAMETERS_free(params);
+		return NULL; 
+		}
+
+	
+	if (a && *a)
+		EC_GROUP_clear_free(*a);
+	if (a)
+		*a = group;
+
+	ECPKPARAMETERS_free(params);
+	return(group);
+	}
+
+int i2d_ECPKParameters(const EC_GROUP *a, unsigned char **out)
+	{
+	int		ret=0;
+	ECPKPARAMETERS	*tmp = ec_asn1_group2pkparameters(a, NULL);
+	if (tmp == NULL)
+		{
+		ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_GROUP2PKPARAMETERS_FAILURE);
+		return 0;
+		}
+	if ((ret = i2d_ECPKPARAMETERS(tmp, out)) == 0)
+		{
+		ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_I2D_ECPKPARAMETERS_FAILURE);
+		ECPKPARAMETERS_free(tmp);
+		return 0;
+		}	
+	ECPKPARAMETERS_free(tmp);
+	return(ret);
+	}
+
+/* some EC_KEY functions */
+
+EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
+	{
+	int             ok=0;
+	EC_KEY          *ret=NULL;
+	EC_PRIVATEKEY   *priv_key=NULL;
+
+	if ((priv_key = EC_PRIVATEKEY_new()) == NULL)
+		{
+		ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
+		return NULL;
+		}
+
+	if ((priv_key = d2i_EC_PRIVATEKEY(&priv_key, in, len)) == NULL)
+		{
+		ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
+		EC_PRIVATEKEY_free(priv_key);
+		return NULL;
+		}
+
+	if (a == NULL || *a == NULL)
+		{
+		if ((ret = EC_KEY_new()) == NULL)	
+			{
+			ECerr(EC_F_D2I_ECPRIVATEKEY,
+                                 ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+		if (a)
+			*a = ret;
+		}
+	else
+		ret = *a;
+
+	if (priv_key->parameters)
+		{
+		if (ret->group)
+			EC_GROUP_clear_free(ret->group);
+		ret->group = ec_asn1_pkparameters2group(priv_key->parameters);
+		}
+
+	if (ret->group == NULL)
+		{
+		ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
+		goto err;
+		}
+
+	ret->version = priv_key->version;
+
+	if (priv_key->privateKey)
+		{
+		ret->priv_key = BN_bin2bn(
+			M_ASN1_STRING_data(priv_key->privateKey),
+			M_ASN1_STRING_length(priv_key->privateKey),
+			ret->priv_key);
+		if (ret->priv_key == NULL)
+			{
+			ECerr(EC_F_D2I_ECPRIVATEKEY,
+                              ERR_R_BN_LIB);
+			goto err;
+			}
+		}
+	else
+		{
+		ECerr(EC_F_D2I_ECPRIVATEKEY, 
+                      EC_R_MISSING_PRIVATE_KEY);
+		goto err;
+		}
+
+	if (priv_key->publicKey)
+		{
+		const unsigned char *pub_oct;
+		size_t pub_oct_len;
+
+		if (ret->pub_key)
+			EC_POINT_clear_free(ret->pub_key);
+		ret->pub_key = EC_POINT_new(ret->group);
+		if (ret->pub_key == NULL)
+			{
+			ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
+			goto err;
+			}
+		pub_oct     = M_ASN1_STRING_data(priv_key->publicKey);
+		pub_oct_len = M_ASN1_STRING_length(priv_key->publicKey);
+		/* save the point conversion form */
+		ret->conv_form = (point_conversion_form_t)(pub_oct[0] & ~0x01);
+		if (!EC_POINT_oct2point(ret->group, ret->pub_key,
+			pub_oct, pub_oct_len, NULL))
+			{
+			ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
+			goto err;
+			}
+		}
+
+	ok = 1;
+err:
+	if (!ok)
+		{
+		if (ret)
+			EC_KEY_free(ret);
+		ret = NULL;
+		}
+
+	if (priv_key)
+		EC_PRIVATEKEY_free(priv_key);
+
+	return(ret);
+	}
+
+int	i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)
+	{
+	int             ret=0, ok=0;
+	unsigned char   *buffer=NULL;
+	size_t          buf_len=0, tmp_len;
+	EC_PRIVATEKEY   *priv_key=NULL;
+
+	if (a == NULL || a->group == NULL || a->priv_key == NULL)
+		{
+		ECerr(EC_F_I2D_ECPRIVATEKEY,
+                      ERR_R_PASSED_NULL_PARAMETER);
+		goto err;
+		}
+
+	if ((priv_key = EC_PRIVATEKEY_new()) == NULL)
+		{
+		ECerr(EC_F_I2D_ECPRIVATEKEY,
+                      ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+
+	priv_key->version = a->version;
+
+	buf_len = (size_t)BN_num_bytes(a->priv_key);
+	buffer = OPENSSL_malloc(buf_len);
+	if (buffer == NULL)
+		{
+		ECerr(EC_F_I2D_ECPRIVATEKEY,
+                      ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+	
+	if (!BN_bn2bin(a->priv_key, buffer))
+		{
+		ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_BN_LIB);
+		goto err;
+		}
+
+	if (!M_ASN1_OCTET_STRING_set(priv_key->privateKey, buffer, buf_len))
+		{
+		ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB);
+		goto err;
+		}	
+
+	if (!(a->enc_flag & EC_PKEY_NO_PARAMETERS))
+		{
+		if ((priv_key->parameters = ec_asn1_group2pkparameters(
+			a->group, priv_key->parameters)) == NULL)
+			{
+			ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
+			goto err;
+			}
+		}
+
+	if (!(a->enc_flag & EC_PKEY_NO_PUBKEY))
+		{
+		priv_key->publicKey = M_ASN1_BIT_STRING_new();
+		if (priv_key->publicKey == NULL)
+			{
+			ECerr(EC_F_I2D_ECPRIVATEKEY,
+				ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+
+		tmp_len = EC_POINT_point2oct(a->group, a->pub_key, 
+				a->conv_form, NULL, 0, NULL);
+
+		if (tmp_len > buf_len)
+			{
+			unsigned char *tmp_buffer = OPENSSL_realloc(buffer, tmp_len);
+			if (!tmp_buffer)
+				{
+				ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
+				goto err;
+				}
+			buffer = tmp_buffer;
+			buf_len = tmp_len;
+			}
+
+		if (!EC_POINT_point2oct(a->group, a->pub_key, 
+			a->conv_form, buffer, buf_len, NULL))
+			{
+			ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
+			goto err;
+			}
+
+		priv_key->publicKey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
+		priv_key->publicKey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+		if (!M_ASN1_BIT_STRING_set(priv_key->publicKey, buffer, 
+				buf_len))
+			{
+			ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB);
+			goto err;
+			}
+		}
+
+	if ((ret = i2d_EC_PRIVATEKEY(priv_key, out)) == 0)
+		{
+		ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
+		goto err;
+		}
+	ok=1;
+err:
+	if (buffer)
+		OPENSSL_free(buffer);
+	if (priv_key)
+		EC_PRIVATEKEY_free(priv_key);
+	return(ok?ret:0);
+	}
+
+int i2d_ECParameters(EC_KEY *a, unsigned char **out)
+	{
+	if (a == NULL)
+		{
+		ECerr(EC_F_I2D_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER);
+		return 0;
+		}
+	return i2d_ECPKParameters(a->group, out);
+	}
+
+EC_KEY *d2i_ECParameters(EC_KEY **a, const unsigned char **in, long len)
+	{
+	EC_KEY   *ret;
+
+	if (in == NULL || *in == NULL)
+		{
+		ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER);
+		return NULL;
+		}
+
+	if (a == NULL || *a == NULL)
+		{
+		if ((ret = EC_KEY_new()) == NULL)
+			{
+			ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_MALLOC_FAILURE);
+			return NULL;
+			}
+		if (a)
+			*a = ret;
+		}
+	else
+		ret = *a;
+
+	if (!d2i_ECPKParameters(&ret->group, in, len))
+		{
+		ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_EC_LIB);
+		return NULL;
+		}
+
+	return ret;
+	}
+
+EC_KEY *o2i_ECPublicKey(EC_KEY **a, const unsigned char **in, long len)
+	{
+	EC_KEY *ret=NULL;
+
+	if (a == NULL || (*a) == NULL || (*a)->group == NULL)
+		{
+		/* sorry, but a EC_GROUP-structur is necessary
+                 * to set the public key */
+		ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER);
+		return 0;
+		}
+	ret = *a;
+	if (ret->pub_key == NULL && 
+		(ret->pub_key = EC_POINT_new(ret->group)) == NULL)
+		{
+		ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_MALLOC_FAILURE);
+		return 0;
+		}
+	if (!EC_POINT_oct2point(ret->group, ret->pub_key, *in, len, NULL))
+		{
+		ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_EC_LIB);
+		return 0;
+		}
+	/* save the point conversion form */
+	ret->conv_form = (point_conversion_form_t)(*in[0] & ~0x01);
+	*in += len;
+	return ret;
+	}
+
+int i2o_ECPublicKey(EC_KEY *a, unsigned char **out)
+	{
+        size_t buf_len=0;
+	int new_buffer = 0;
+
+        if (a == NULL) 
+		{
+		ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER);
+		return 0;
+		}
+
+        buf_len = EC_POINT_point2oct(a->group, a->pub_key, 
+                              a->conv_form, NULL, 0, NULL);
+
+	if (out == NULL || buf_len == 0)
+	/* out == NULL => just return the length of the octet string */
+		return buf_len;
+
+	if (*out == NULL)
+		{
+		if ((*out = OPENSSL_malloc(buf_len)) == NULL)
+			{
+			ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_MALLOC_FAILURE);
+			return 0;
+			}
+		new_buffer = 1;
+		}
+        if (!EC_POINT_point2oct(a->group, a->pub_key, a->conv_form,
+				*out, buf_len, NULL))
+		{
+		ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_EC_LIB);
+		OPENSSL_free(*out);
+		*out = NULL;
+		return 0;
+		}
+	if (!new_buffer)
+		*out += buf_len;
+	return buf_len;
+	}
diff --git a/jni/openssl/crypto/ec/ec_check.c b/jni/openssl/crypto/ec/ec_check.c
new file mode 100644
index 0000000..0e316b4
--- /dev/null
+++ b/jni/openssl/crypto/ec/ec_check.c
@@ -0,0 +1,123 @@
+/* crypto/ec/ec_check.c */
+/* ====================================================================
+ * Copyright (c) 1998-2002 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).
+ *
+ */
+
+#include "ec_lcl.h"
+#include <openssl/err.h>
+
+int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx)
+	{
+	int ret = 0;
+	BIGNUM *order;
+	BN_CTX *new_ctx = NULL;
+	EC_POINT *point = NULL;
+
+	if (ctx == NULL)
+		{
+		ctx = new_ctx = BN_CTX_new();
+		if (ctx == NULL)
+			{
+			ECerr(EC_F_EC_GROUP_CHECK, ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+		}
+	BN_CTX_start(ctx);
+	if ((order = BN_CTX_get(ctx)) == NULL) goto err;
+
+	/* check the discriminant */
+	if (!EC_GROUP_check_discriminant(group, ctx))
+		{
+		ECerr(EC_F_EC_GROUP_CHECK, EC_R_DISCRIMINANT_IS_ZERO);
+		goto err;
+		}
+
+	/* check the generator */
+	if (group->generator == NULL)
+		{
+		ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_GENERATOR);
+		goto err;
+		}
+	if (!EC_POINT_is_on_curve(group, group->generator, ctx))
+		{
+		ECerr(EC_F_EC_GROUP_CHECK, EC_R_POINT_IS_NOT_ON_CURVE);
+		goto err;
+		}
+
+	/* check the order of the generator */
+	if ((point = EC_POINT_new(group)) == NULL) goto err;
+	if (!EC_GROUP_get_order(group, order, ctx)) goto err; 
+	if (BN_is_zero(order))
+		{
+		ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_ORDER);
+		goto err;
+		}
+	
+	if (!EC_POINT_mul(group, point, order, NULL, NULL, ctx)) goto err;
+	if (!EC_POINT_is_at_infinity(group, point))
+		{
+		ECerr(EC_F_EC_GROUP_CHECK, EC_R_INVALID_GROUP_ORDER);
+		goto err;
+		}
+
+	ret = 1;
+
+err:
+	if (ctx != NULL)
+		BN_CTX_end(ctx);
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	if (point)
+		EC_POINT_free(point);
+	return ret;
+	}
diff --git a/jni/openssl/crypto/ec/ec_curve.c b/jni/openssl/crypto/ec/ec_curve.c
new file mode 100644
index 0000000..c72fb26
--- /dev/null
+++ b/jni/openssl/crypto/ec/ec_curve.c
@@ -0,0 +1,2100 @@
+/* crypto/ec/ec_curve.c */
+/*
+ * Written by Nils Larsch for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2010 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 of the attached software ("Contribution") are developed by 
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * The elliptic curve binary polynomial software is originally written by 
+ * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
+ *
+ */
+
+#include "ec_lcl.h"
+#include <openssl/err.h>
+#include <openssl/obj_mac.h>
+#include <openssl/opensslconf.h>
+
+typedef struct {
+	int	field_type,	/* either NID_X9_62_prime_field or
+				 * NID_X9_62_characteristic_two_field */
+		seed_len,
+		param_len;
+	unsigned int cofactor;	/* promoted to BN_ULONG */
+} EC_CURVE_DATA;
+
+/* the nist prime curves */
+static const struct { EC_CURVE_DATA h; unsigned char data[20+24*6]; }
+	_EC_NIST_PRIME_192 = {
+	{ NID_X9_62_prime_field,20,24,1 },
+	{ 0x30,0x45,0xAE,0x6F,0xC8,0x42,0x2F,0x64,0xED,0x57,	/* seed */
+	  0x95,0x28,0xD3,0x81,0x20,0xEA,0xE1,0x21,0x96,0xD5,
+
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* p */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* a */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFC,
+	  0x64,0x21,0x05,0x19,0xE5,0x9C,0x80,0xE7,0x0F,0xA7,	/* b */
+	  0xE9,0xAB,0x72,0x24,0x30,0x49,0xFE,0xB8,0xDE,0xEC,
+	  0xC1,0x46,0xB9,0xB1,
+	  0x18,0x8D,0xA8,0x0E,0xB0,0x30,0x90,0xF6,0x7C,0xBF,	/* x */
+	  0x20,0xEB,0x43,0xA1,0x88,0x00,0xF4,0xFF,0x0A,0xFD,
+	  0x82,0xFF,0x10,0x12,
+	  0x07,0x19,0x2b,0x95,0xff,0xc8,0xda,0x78,0x63,0x10,	/* y */
+	  0x11,0xed,0x6b,0x24,0xcd,0xd5,0x73,0xf9,0x77,0xa1,
+	  0x1e,0x79,0x48,0x11,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* order */
+	  0xFF,0xFF,0x99,0xDE,0xF8,0x36,0x14,0x6B,0xC9,0xB1,
+	  0xB4,0xD2,0x28,0x31 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+28*6]; }
+	_EC_NIST_PRIME_224 = {
+	{ NID_X9_62_prime_field,20,28,1 },
+	{ 0xBD,0x71,0x34,0x47,0x99,0xD5,0xC7,0xFC,0xDC,0x45,	/* seed */
+	  0xB5,0x9F,0xA3,0xB9,0xAB,0x8F,0x6A,0x94,0x8B,0xC5,
+
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* p */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* a */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
+	  0xB4,0x05,0x0A,0x85,0x0C,0x04,0xB3,0xAB,0xF5,0x41,	/* b */
+	  0x32,0x56,0x50,0x44,0xB0,0xB7,0xD7,0xBF,0xD8,0xBA,
+	  0x27,0x0B,0x39,0x43,0x23,0x55,0xFF,0xB4,
+	  0xB7,0x0E,0x0C,0xBD,0x6B,0xB4,0xBF,0x7F,0x32,0x13,	/* x */
+	  0x90,0xB9,0x4A,0x03,0xC1,0xD3,0x56,0xC2,0x11,0x22,
+	  0x34,0x32,0x80,0xD6,0x11,0x5C,0x1D,0x21,
+	  0xbd,0x37,0x63,0x88,0xb5,0xf7,0x23,0xfb,0x4c,0x22,	/* y */
+	  0xdf,0xe6,0xcd,0x43,0x75,0xa0,0x5a,0x07,0x47,0x64,
+	  0x44,0xd5,0x81,0x99,0x85,0x00,0x7e,0x34,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* order */
+	  0xFF,0xFF,0xFF,0xFF,0x16,0xA2,0xE0,0xB8,0xF0,0x3E,
+	  0x13,0xDD,0x29,0x45,0x5C,0x5C,0x2A,0x3D }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+48*6]; }
+	_EC_NIST_PRIME_384 = {
+	{ NID_X9_62_prime_field,20,48,1 },
+	{ 0xA3,0x35,0x92,0x6A,0xA3,0x19,0xA2,0x7A,0x1D,0x00,	/* seed */
+	  0x89,0x6A,0x67,0x73,0xA4,0x82,0x7A,0xCD,0xAC,0x73,
+
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* p */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* a */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFC,
+	  0xB3,0x31,0x2F,0xA7,0xE2,0x3E,0xE7,0xE4,0x98,0x8E,	/* b */
+	  0x05,0x6B,0xE3,0xF8,0x2D,0x19,0x18,0x1D,0x9C,0x6E,
+	  0xFE,0x81,0x41,0x12,0x03,0x14,0x08,0x8F,0x50,0x13,
+	  0x87,0x5A,0xC6,0x56,0x39,0x8D,0x8A,0x2E,0xD1,0x9D,
+	  0x2A,0x85,0xC8,0xED,0xD3,0xEC,0x2A,0xEF,
+	  0xAA,0x87,0xCA,0x22,0xBE,0x8B,0x05,0x37,0x8E,0xB1,	/* x */
+	  0xC7,0x1E,0xF3,0x20,0xAD,0x74,0x6E,0x1D,0x3B,0x62,
+	  0x8B,0xA7,0x9B,0x98,0x59,0xF7,0x41,0xE0,0x82,0x54,
+	  0x2A,0x38,0x55,0x02,0xF2,0x5D,0xBF,0x55,0x29,0x6C,
+	  0x3A,0x54,0x5E,0x38,0x72,0x76,0x0A,0xB7,
+	  0x36,0x17,0xde,0x4a,0x96,0x26,0x2c,0x6f,0x5d,0x9e,	/* y */
+	  0x98,0xbf,0x92,0x92,0xdc,0x29,0xf8,0xf4,0x1d,0xbd,
+	  0x28,0x9a,0x14,0x7c,0xe9,0xda,0x31,0x13,0xb5,0xf0,
+	  0xb8,0xc0,0x0a,0x60,0xb1,0xce,0x1d,0x7e,0x81,0x9d,
+	  0x7a,0x43,0x1d,0x7c,0x90,0xea,0x0e,0x5f,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* order */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0xC7,0x63,0x4D,0x81,0xF4,0x37,
+	  0x2D,0xDF,0x58,0x1A,0x0D,0xB2,0x48,0xB0,0xA7,0x7A,
+	  0xEC,0xEC,0x19,0x6A,0xCC,0xC5,0x29,0x73 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+66*6]; }
+	_EC_NIST_PRIME_521 = {
+	{ NID_X9_62_prime_field,20,66,1 },
+	{ 0xD0,0x9E,0x88,0x00,0x29,0x1C,0xB8,0x53,0x96,0xCC,	/* seed */
+	  0x67,0x17,0x39,0x32,0x84,0xAA,0xA0,0xDA,0x64,0xBA,
+
+	  0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* p */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* a */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,
+	  0x00,0x51,0x95,0x3E,0xB9,0x61,0x8E,0x1C,0x9A,0x1F,	/* b */
+	  0x92,0x9A,0x21,0xA0,0xB6,0x85,0x40,0xEE,0xA2,0xDA,
+	  0x72,0x5B,0x99,0xB3,0x15,0xF3,0xB8,0xB4,0x89,0x91,
+	  0x8E,0xF1,0x09,0xE1,0x56,0x19,0x39,0x51,0xEC,0x7E,
+	  0x93,0x7B,0x16,0x52,0xC0,0xBD,0x3B,0xB1,0xBF,0x07,
+	  0x35,0x73,0xDF,0x88,0x3D,0x2C,0x34,0xF1,0xEF,0x45,
+	  0x1F,0xD4,0x6B,0x50,0x3F,0x00,
+	  0x00,0xC6,0x85,0x8E,0x06,0xB7,0x04,0x04,0xE9,0xCD,	/* x */
+	  0x9E,0x3E,0xCB,0x66,0x23,0x95,0xB4,0x42,0x9C,0x64,
+	  0x81,0x39,0x05,0x3F,0xB5,0x21,0xF8,0x28,0xAF,0x60,
+	  0x6B,0x4D,0x3D,0xBA,0xA1,0x4B,0x5E,0x77,0xEF,0xE7,
+	  0x59,0x28,0xFE,0x1D,0xC1,0x27,0xA2,0xFF,0xA8,0xDE,
+	  0x33,0x48,0xB3,0xC1,0x85,0x6A,0x42,0x9B,0xF9,0x7E,
+	  0x7E,0x31,0xC2,0xE5,0xBD,0x66,
+	  0x01,0x18,0x39,0x29,0x6a,0x78,0x9a,0x3b,0xc0,0x04,	/* y */
+	  0x5c,0x8a,0x5f,0xb4,0x2c,0x7d,0x1b,0xd9,0x98,0xf5,
+	  0x44,0x49,0x57,0x9b,0x44,0x68,0x17,0xaf,0xbd,0x17,
+	  0x27,0x3e,0x66,0x2c,0x97,0xee,0x72,0x99,0x5e,0xf4,
+	  0x26,0x40,0xc5,0x50,0xb9,0x01,0x3f,0xad,0x07,0x61,
+	  0x35,0x3c,0x70,0x86,0xa2,0x72,0xc2,0x40,0x88,0xbe,
+	  0x94,0x76,0x9f,0xd1,0x66,0x50,
+	  0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* order */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFA,0x51,0x86,0x87,0x83,0xBF,0x2F,
+	  0x96,0x6B,0x7F,0xCC,0x01,0x48,0xF7,0x09,0xA5,0xD0,
+	  0x3B,0xB5,0xC9,0xB8,0x89,0x9C,0x47,0xAE,0xBB,0x6F,
+	  0xB7,0x1E,0x91,0x38,0x64,0x09 }
+	};
+
+/* the x9.62 prime curves (minus the nist prime curves) */
+static const struct { EC_CURVE_DATA h; unsigned char data[20+24*6]; }
+	_EC_X9_62_PRIME_192V2 = {
+	{ NID_X9_62_prime_field,20,24,1 },
+	{ 0x31,0xA9,0x2E,0xE2,0x02,0x9F,0xD1,0x0D,0x90,0x1B,	/* seed */
+	  0x11,0x3E,0x99,0x07,0x10,0xF0,0xD2,0x1A,0xC6,0xB6,
+
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* p */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* a */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFC,
+	  0xCC,0x22,0xD6,0xDF,0xB9,0x5C,0x6B,0x25,0xE4,0x9C,	/* b */
+	  0x0D,0x63,0x64,0xA4,0xE5,0x98,0x0C,0x39,0x3A,0xA2,
+	  0x16,0x68,0xD9,0x53,
+	  0xEE,0xA2,0xBA,0xE7,0xE1,0x49,0x78,0x42,0xF2,0xDE,	/* x */
+	  0x77,0x69,0xCF,0xE9,0xC9,0x89,0xC0,0x72,0xAD,0x69,
+	  0x6F,0x48,0x03,0x4A,
+	  0x65,0x74,0xd1,0x1d,0x69,0xb6,0xec,0x7a,0x67,0x2b,	/* y */
+	  0xb8,0x2a,0x08,0x3d,0xf2,0xf2,0xb0,0x84,0x7d,0xe9,
+	  0x70,0xb2,0xde,0x15,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* order */
+	  0xFF,0xFE,0x5F,0xB1,0xA7,0x24,0xDC,0x80,0x41,0x86,
+	  0x48,0xD8,0xDD,0x31 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+24*6]; }
+	_EC_X9_62_PRIME_192V3 = {
+	{ NID_X9_62_prime_field,20,24,1 },
+	{ 0xC4,0x69,0x68,0x44,0x35,0xDE,0xB3,0x78,0xC4,0xB6,	/* seed */
+	  0x5C,0xA9,0x59,0x1E,0x2A,0x57,0x63,0x05,0x9A,0x2E,
+
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* p */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* a */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFC,
+	  0x22,0x12,0x3D,0xC2,0x39,0x5A,0x05,0xCA,0xA7,0x42,	/* b */
+	  0x3D,0xAE,0xCC,0xC9,0x47,0x60,0xA7,0xD4,0x62,0x25,
+	  0x6B,0xD5,0x69,0x16,
+	  0x7D,0x29,0x77,0x81,0x00,0xC6,0x5A,0x1D,0xA1,0x78,	/* x */
+	  0x37,0x16,0x58,0x8D,0xCE,0x2B,0x8B,0x4A,0xEE,0x8E,
+	  0x22,0x8F,0x18,0x96,
+	  0x38,0xa9,0x0f,0x22,0x63,0x73,0x37,0x33,0x4b,0x49,	/* y */
+	  0xdc,0xb6,0x6a,0x6d,0xc8,0xf9,0x97,0x8a,0xca,0x76,
+	  0x48,0xa9,0x43,0xb0,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* order */
+	  0xFF,0xFF,0x7A,0x62,0xD0,0x31,0xC8,0x3F,0x42,0x94,
+	  0xF6,0x40,0xEC,0x13 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+30*6]; }
+	_EC_X9_62_PRIME_239V1 = {
+	{ NID_X9_62_prime_field,20,30,1 },
+	{ 0xE4,0x3B,0xB4,0x60,0xF0,0xB8,0x0C,0xC0,0xC0,0xB0,	/* seed */
+	  0x75,0x79,0x8E,0x94,0x80,0x60,0xF8,0x32,0x1B,0x7D,
+
+	  0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* p */
+	  0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,
+	  0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,
+
+	  0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* a */
+	  0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,
+	  0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFC,
+
+	  0x6B,0x01,0x6C,0x3B,0xDC,0xF1,0x89,0x41,0xD0,0xD6,	/* b */
+	  0x54,0x92,0x14,0x75,0xCA,0x71,0xA9,0xDB,0x2F,0xB2,
+	  0x7D,0x1D,0x37,0x79,0x61,0x85,0xC2,0x94,0x2C,0x0A,
+
+	  0x0F,0xFA,0x96,0x3C,0xDC,0xA8,0x81,0x6C,0xCC,0x33,	/* x */
+	  0xB8,0x64,0x2B,0xED,0xF9,0x05,0xC3,0xD3,0x58,0x57,
+	  0x3D,0x3F,0x27,0xFB,0xBD,0x3B,0x3C,0xB9,0xAA,0xAF,
+
+	  0x7d,0xeb,0xe8,0xe4,0xe9,0x0a,0x5d,0xae,0x6e,0x40,	/* y */
+	  0x54,0xca,0x53,0x0b,0xa0,0x46,0x54,0xb3,0x68,0x18,
+	  0xce,0x22,0x6b,0x39,0xfc,0xcb,0x7b,0x02,0xf1,0xae,
+
+	  0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* order */
+	  0xFF,0xFF,0x7F,0xFF,0xFF,0x9E,0x5E,0x9A,0x9F,0x5D,
+	  0x90,0x71,0xFB,0xD1,0x52,0x26,0x88,0x90,0x9D,0x0B }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+30*6]; }
+	_EC_X9_62_PRIME_239V2 = {
+	{ NID_X9_62_prime_field,20,30,1 },
+	{ 0xE8,0xB4,0x01,0x16,0x04,0x09,0x53,0x03,0xCA,0x3B,	/* seed */
+	  0x80,0x99,0x98,0x2B,0xE0,0x9F,0xCB,0x9A,0xE6,0x16,
+
+	  0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* p */
+	  0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,
+	  0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,
+
+	  0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* a */
+	  0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,
+	  0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFC,
+
+	  0x61,0x7F,0xAB,0x68,0x32,0x57,0x6C,0xBB,0xFE,0xD5,	/* b */
+	  0x0D,0x99,0xF0,0x24,0x9C,0x3F,0xEE,0x58,0xB9,0x4B,
+	  0xA0,0x03,0x8C,0x7A,0xE8,0x4C,0x8C,0x83,0x2F,0x2C,
+
+	  0x38,0xAF,0x09,0xD9,0x87,0x27,0x70,0x51,0x20,0xC9,	/* x */
+	  0x21,0xBB,0x5E,0x9E,0x26,0x29,0x6A,0x3C,0xDC,0xF2,
+	  0xF3,0x57,0x57,0xA0,0xEA,0xFD,0x87,0xB8,0x30,0xE7,
+
+	  0x5b,0x01,0x25,0xe4,0xdb,0xea,0x0e,0xc7,0x20,0x6d,	/* y */
+	  0xa0,0xfc,0x01,0xd9,0xb0,0x81,0x32,0x9f,0xb5,0x55,
+	  0xde,0x6e,0xf4,0x60,0x23,0x7d,0xff,0x8b,0xe4,0xba,
+
+	  0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* order */
+	  0xFF,0xFF,0x80,0x00,0x00,0xCF,0xA7,0xE8,0x59,0x43,
+	  0x77,0xD4,0x14,0xC0,0x38,0x21,0xBC,0x58,0x20,0x63 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+30*6]; }
+	_EC_X9_62_PRIME_239V3 = {
+	{ NID_X9_62_prime_field,20,30,1 },
+	{ 0x7D,0x73,0x74,0x16,0x8F,0xFE,0x34,0x71,0xB6,0x0A,	/* seed */
+	  0x85,0x76,0x86,0xA1,0x94,0x75,0xD3,0xBF,0xA2,0xFF,
+
+	  0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* p */
+	  0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,
+	  0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,
+
+	  0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* a */
+	  0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,
+	  0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFC,
+
+	  0x25,0x57,0x05,0xFA,0x2A,0x30,0x66,0x54,0xB1,0xF4,	/* b */
+	  0xCB,0x03,0xD6,0xA7,0x50,0xA3,0x0C,0x25,0x01,0x02,
+	  0xD4,0x98,0x87,0x17,0xD9,0xBA,0x15,0xAB,0x6D,0x3E,
+
+	  0x67,0x68,0xAE,0x8E,0x18,0xBB,0x92,0xCF,0xCF,0x00,	/* x */
+	  0x5C,0x94,0x9A,0xA2,0xC6,0xD9,0x48,0x53,0xD0,0xE6,
+	  0x60,0xBB,0xF8,0x54,0xB1,0xC9,0x50,0x5F,0xE9,0x5A,
+
+	  0x16,0x07,0xe6,0x89,0x8f,0x39,0x0c,0x06,0xbc,0x1d,	/* y */
+	  0x55,0x2b,0xad,0x22,0x6f,0x3b,0x6f,0xcf,0xe4,0x8b,
+	  0x6e,0x81,0x84,0x99,0xaf,0x18,0xe3,0xed,0x6c,0xf3,
+
+	  0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* order */
+	  0xFF,0xFF,0x7F,0xFF,0xFF,0x97,0x5D,0xEB,0x41,0xB3,
+	  0xA6,0x05,0x7C,0x3C,0x43,0x21,0x46,0x52,0x65,0x51 }
+	};
+
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+32*6]; }
+	_EC_X9_62_PRIME_256V1 = {
+	{ NID_X9_62_prime_field,20,32,1 },
+	{ 0xC4,0x9D,0x36,0x08,0x86,0xE7,0x04,0x93,0x6A,0x66,	/* seed */
+	  0x78,0xE1,0x13,0x9D,0x26,0xB7,0x81,0x9F,0x7E,0x90,
+
+	  0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,0x00,0x00,	/* a */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFC,
+	  0x5A,0xC6,0x35,0xD8,0xAA,0x3A,0x93,0xE7,0xB3,0xEB,	/* b */
+	  0xBD,0x55,0x76,0x98,0x86,0xBC,0x65,0x1D,0x06,0xB0,
+	  0xCC,0x53,0xB0,0xF6,0x3B,0xCE,0x3C,0x3E,0x27,0xD2,
+	  0x60,0x4B,
+	  0x6B,0x17,0xD1,0xF2,0xE1,0x2C,0x42,0x47,0xF8,0xBC,	/* x */
+	  0xE6,0xE5,0x63,0xA4,0x40,0xF2,0x77,0x03,0x7D,0x81,
+	  0x2D,0xEB,0x33,0xA0,0xF4,0xA1,0x39,0x45,0xD8,0x98,
+	  0xC2,0x96,
+	  0x4f,0xe3,0x42,0xe2,0xfe,0x1a,0x7f,0x9b,0x8e,0xe7,	/* y */
+	  0xeb,0x4a,0x7c,0x0f,0x9e,0x16,0x2b,0xce,0x33,0x57,
+	  0x6b,0x31,0x5e,0xce,0xcb,0xb6,0x40,0x68,0x37,0xbf,
+	  0x51,0xf5,
+	  0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFF,	/* order */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBC,0xE6,0xFA,0xAD,
+	  0xA7,0x17,0x9E,0x84,0xF3,0xB9,0xCA,0xC2,0xFC,0x63,
+	  0x25,0x51 }
+	};
+
+/* the secg prime curves (minus the nist and x9.62 prime curves) */
+static const struct { EC_CURVE_DATA h; unsigned char data[20+14*6]; }
+	_EC_SECG_PRIME_112R1 = {
+	{ NID_X9_62_prime_field,20,14,1 },
+	{ 0x00,0xF5,0x0B,0x02,0x8E,0x4D,0x69,0x6E,0x67,0x68,	/* seed */
+	  0x75,0x61,0x51,0x75,0x29,0x04,0x72,0x78,0x3F,0xB1,
+
+	  0xDB,0x7C,0x2A,0xBF,0x62,0xE3,0x5E,0x66,0x80,0x76,	/* p */
+	  0xBE,0xAD,0x20,0x8B,
+	  0xDB,0x7C,0x2A,0xBF,0x62,0xE3,0x5E,0x66,0x80,0x76,	/* a */
+	  0xBE,0xAD,0x20,0x88,
+	  0x65,0x9E,0xF8,0xBA,0x04,0x39,0x16,0xEE,0xDE,0x89,	/* b */
+	  0x11,0x70,0x2B,0x22,
+	  0x09,0x48,0x72,0x39,0x99,0x5A,0x5E,0xE7,0x6B,0x55,	/* x */
+	  0xF9,0xC2,0xF0,0x98,
+	  0xa8,0x9c,0xe5,0xaf,0x87,0x24,0xc0,0xa2,0x3e,0x0e,	/* y */
+	  0x0f,0xf7,0x75,0x00,
+	  0xDB,0x7C,0x2A,0xBF,0x62,0xE3,0x5E,0x76,0x28,0xDF,	/* order */
+	  0xAC,0x65,0x61,0xC5 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+14*6]; }
+	_EC_SECG_PRIME_112R2 = {
+	{ NID_X9_62_prime_field,20,14,4 },
+	{ 0x00,0x27,0x57,0xA1,0x11,0x4D,0x69,0x6E,0x67,0x68,	/* seed */
+	  0x75,0x61,0x51,0x75,0x53,0x16,0xC0,0x5E,0x0B,0xD4,
+
+	  0xDB,0x7C,0x2A,0xBF,0x62,0xE3,0x5E,0x66,0x80,0x76,	/* p */
+	  0xBE,0xAD,0x20,0x8B,
+	  0x61,0x27,0xC2,0x4C,0x05,0xF3,0x8A,0x0A,0xAA,0xF6,	/* a */
+	  0x5C,0x0E,0xF0,0x2C,
+	  0x51,0xDE,0xF1,0x81,0x5D,0xB5,0xED,0x74,0xFC,0xC3,	/* b */
+	  0x4C,0x85,0xD7,0x09,
+	  0x4B,0xA3,0x0A,0xB5,0xE8,0x92,0xB4,0xE1,0x64,0x9D,	/* x */
+	  0xD0,0x92,0x86,0x43,
+	  0xad,0xcd,0x46,0xf5,0x88,0x2e,0x37,0x47,0xde,0xf3,	/* y */
+	  0x6e,0x95,0x6e,0x97,
+	  0x36,0xDF,0x0A,0xAF,0xD8,0xB8,0xD7,0x59,0x7C,0xA1,	/* order */
+	  0x05,0x20,0xD0,0x4B }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+16*6]; }
+	_EC_SECG_PRIME_128R1 = {
+	{ NID_X9_62_prime_field,20,16,1 },
+	{ 0x00,0x0E,0x0D,0x4D,0x69,0x6E,0x67,0x68,0x75,0x61,	/* seed */
+	  0x51,0x75,0x0C,0xC0,0x3A,0x44,0x73,0xD0,0x36,0x79,
+
+	  0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* p */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* a */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,
+	  0xE8,0x75,0x79,0xC1,0x10,0x79,0xF4,0x3D,0xD8,0x24,	/* b */
+	  0x99,0x3C,0x2C,0xEE,0x5E,0xD3,
+	  0x16,0x1F,0xF7,0x52,0x8B,0x89,0x9B,0x2D,0x0C,0x28,	/* x */
+	  0x60,0x7C,0xA5,0x2C,0x5B,0x86,
+	  0xcf,0x5a,0xc8,0x39,0x5b,0xaf,0xeb,0x13,0xc0,0x2d,	/* y */
+	  0xa2,0x92,0xdd,0xed,0x7a,0x83,
+	  0xFF,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x75,0xA3,	/* order */
+	  0x0D,0x1B,0x90,0x38,0xA1,0x15 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+16*6]; }
+	_EC_SECG_PRIME_128R2 = {
+	{ NID_X9_62_prime_field,20,16,4 },
+	{ 0x00,0x4D,0x69,0x6E,0x67,0x68,0x75,0x61,0x51,0x75,	/* seed */
+	  0x12,0xD8,0xF0,0x34,0x31,0xFC,0xE6,0x3B,0x88,0xF4,
+
+	  0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* p */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xD6,0x03,0x19,0x98,0xD1,0xB3,0xBB,0xFE,0xBF,0x59,	/* a */
+	  0xCC,0x9B,0xBF,0xF9,0xAE,0xE1,
+	  0x5E,0xEE,0xFC,0xA3,0x80,0xD0,0x29,0x19,0xDC,0x2C,	/* b */
+	  0x65,0x58,0xBB,0x6D,0x8A,0x5D,
+	  0x7B,0x6A,0xA5,0xD8,0x5E,0x57,0x29,0x83,0xE6,0xFB,	/* x */
+	  0x32,0xA7,0xCD,0xEB,0xC1,0x40,
+	  0x27,0xb6,0x91,0x6a,0x89,0x4d,0x3a,0xee,0x71,0x06,	/* y */
+	  0xfe,0x80,0x5f,0xc3,0x4b,0x44,
+	  0x3F,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xBE,0x00,	/* order */
+	  0x24,0x72,0x06,0x13,0xB5,0xA3 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[0+21*6]; }
+	_EC_SECG_PRIME_160K1 = {
+	{ NID_X9_62_prime_field,0,21,1 },
+	{							/* no seed */
+	  0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* p */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xAC,
+	  0x73,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* a */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* b */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x07,
+	  0x00,0x3B,0x4C,0x38,0x2C,0xE3,0x7A,0xA1,0x92,0xA4,	/* x */
+	  0x01,0x9E,0x76,0x30,0x36,0xF4,0xF5,0xDD,0x4D,0x7E,
+	  0xBB,
+	  0x00,0x93,0x8c,0xf9,0x35,0x31,0x8f,0xdc,0xed,0x6b,	/* y */
+	  0xc2,0x82,0x86,0x53,0x17,0x33,0xc3,0xf0,0x3c,0x4f,
+	  0xee,
+	  0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* order */
+	  0x01,0xB8,0xFA,0x16,0xDF,0xAB,0x9A,0xCA,0x16,0xB6,
+	  0xB3 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+21*6]; }
+	_EC_SECG_PRIME_160R1 = {
+	{ NID_X9_62_prime_field,20,21,1 },
+	{ 0x10,0x53,0xCD,0xE4,0x2C,0x14,0xD6,0x96,0xE6,0x76,	/* seed */
+	  0x87,0x56,0x15,0x17,0x53,0x3B,0xF3,0xF8,0x33,0x45,
+
+	  0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* p */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,
+	  0xFF,
+	  0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* a */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,
+	  0xFC,
+	  0x00,0x1C,0x97,0xBE,0xFC,0x54,0xBD,0x7A,0x8B,0x65,	/* b */
+	  0xAC,0xF8,0x9F,0x81,0xD4,0xD4,0xAD,0xC5,0x65,0xFA,
+	  0x45,
+	  0x00,0x4A,0x96,0xB5,0x68,0x8E,0xF5,0x73,0x28,0x46,	/* x */
+	  0x64,0x69,0x89,0x68,0xC3,0x8B,0xB9,0x13,0xCB,0xFC,
+	  0x82,
+	  0x00,0x23,0xa6,0x28,0x55,0x31,0x68,0x94,0x7d,0x59,	/* y */
+	  0xdc,0xc9,0x12,0x04,0x23,0x51,0x37,0x7a,0xc5,0xfb,
+	  0x32,
+	  0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* order */
+	  0x01,0xF4,0xC8,0xF9,0x27,0xAE,0xD3,0xCA,0x75,0x22,
+	  0x57 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+21*6]; }
+	_EC_SECG_PRIME_160R2 = {
+	{ NID_X9_62_prime_field,20,21,1 },
+	{ 0xB9,0x9B,0x99,0xB0,0x99,0xB3,0x23,0xE0,0x27,0x09,	/* seed */
+	  0xA4,0xD6,0x96,0xE6,0x76,0x87,0x56,0x15,0x17,0x51,
+
+	  0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* p */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xAC,
+	  0x73,
+	  0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* a */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xAC,
+	  0x70,
+	  0x00,0xB4,0xE1,0x34,0xD3,0xFB,0x59,0xEB,0x8B,0xAB,	/* b */
+	  0x57,0x27,0x49,0x04,0x66,0x4D,0x5A,0xF5,0x03,0x88,
+	  0xBA,
+	  0x00,0x52,0xDC,0xB0,0x34,0x29,0x3A,0x11,0x7E,0x1F,	/* x */
+	  0x4F,0xF1,0x1B,0x30,0xF7,0x19,0x9D,0x31,0x44,0xCE,
+	  0x6D,
+	  0x00,0xfe,0xaf,0xfe,0xf2,0xe3,0x31,0xf2,0x96,0xe0,	/* y */
+	  0x71,0xfa,0x0d,0xf9,0x98,0x2c,0xfe,0xa7,0xd4,0x3f,
+	  0x2e,
+	  0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* order */
+	  0x00,0x35,0x1E,0xE7,0x86,0xA8,0x18,0xF3,0xA1,0xA1,
+	  0x6B }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[0+24*6]; }
+	_EC_SECG_PRIME_192K1 = {
+	{ NID_X9_62_prime_field,0,24,1 },
+	{							/* no seed */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* p */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
+	  0xFF,0xFF,0xEE,0x37,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* a */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* b */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x03,
+	  0xDB,0x4F,0xF1,0x0E,0xC0,0x57,0xE9,0xAE,0x26,0xB0,	/* x */
+	  0x7D,0x02,0x80,0xB7,0xF4,0x34,0x1D,0xA5,0xD1,0xB1,
+	  0xEA,0xE0,0x6C,0x7D,
+	  0x9b,0x2f,0x2f,0x6d,0x9c,0x56,0x28,0xa7,0x84,0x41,	/* y */
+	  0x63,0xd0,0x15,0xbe,0x86,0x34,0x40,0x82,0xaa,0x88,
+	  0xd9,0x5e,0x2f,0x9d,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* order */
+	  0xFF,0xFE,0x26,0xF2,0xFC,0x17,0x0F,0x69,0x46,0x6A,
+	  0x74,0xDE,0xFD,0x8D }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[0+29*6]; }
+	_EC_SECG_PRIME_224K1 = {
+	{ NID_X9_62_prime_field,0,29,1 },
+	{							/* no seed */
+	  0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* p */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xE5,0x6D,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* a */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* b */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,
+	  0x00,0xA1,0x45,0x5B,0x33,0x4D,0xF0,0x99,0xDF,0x30,	/* x */
+	  0xFC,0x28,0xA1,0x69,0xA4,0x67,0xE9,0xE4,0x70,0x75,
+	  0xA9,0x0F,0x7E,0x65,0x0E,0xB6,0xB7,0xA4,0x5C,
+	  0x00,0x7e,0x08,0x9f,0xed,0x7f,0xba,0x34,0x42,0x82,	/* y */
+	  0xca,0xfb,0xd6,0xf7,0xe3,0x19,0xf7,0xc0,0xb0,0xbd,
+	  0x59,0xe2,0xca,0x4b,0xdb,0x55,0x6d,0x61,0xa5,
+	  0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* order */
+	  0x00,0x00,0x00,0x00,0x01,0xDC,0xE8,0xD2,0xEC,0x61,
+	  0x84,0xCA,0xF0,0xA9,0x71,0x76,0x9F,0xB1,0xF7 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[0+32*6]; }
+	_EC_SECG_PRIME_256K1 = {
+	{ NID_X9_62_prime_field,0,32,1 },
+	{							/* no seed */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* p */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,
+	  0xFC,0x2F,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* a */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* b */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x07,
+	  0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,	/* x */
+	  0x62,0x95,0xCE,0x87,0x0B,0x07,0x02,0x9B,0xFC,0xDB,
+	  0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8,
+	  0x17,0x98,
+	  0x48,0x3a,0xda,0x77,0x26,0xa3,0xc4,0x65,0x5d,0xa4,	/* y */
+	  0xfb,0xfc,0x0e,0x11,0x08,0xa8,0xfd,0x17,0xb4,0x48,
+	  0xa6,0x85,0x54,0x19,0x9c,0x47,0xd0,0x8f,0xfb,0x10,
+	  0xd4,0xb8,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* order */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,
+	  0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E,0x8C,0xD0,0x36,
+	  0x41,0x41 }
+	};
+
+/* some wap/wtls curves */
+static const struct { EC_CURVE_DATA h; unsigned char data[0+15*6]; }
+	_EC_WTLS_8 = {
+	{ NID_X9_62_prime_field,0,15,1 },
+	{							/* no seed */
+	  0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* p */
+	  0xFF,0xFF,0xFF,0xFD,0xE7,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* a */
+	  0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* b */
+	  0x00,0x00,0x00,0x00,0x03,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* x */
+	  0x00,0x00,0x00,0x00,0x01,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* y */
+	  0x00,0x00,0x00,0x00,0x02,
+	  0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xEC,0xEA,	/* order */
+	  0x55,0x1A,0xD8,0x37,0xE9 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[0+21*6]; }
+	_EC_WTLS_9 = {
+	{ NID_X9_62_prime_field,0,21,1 },
+	{							/* no seed */
+	  0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* p */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x80,
+	  0x8F,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* a */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* b */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x03,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* x */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x01,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* y */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x02,
+	  0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* order */
+	  0x01,0xCD,0xC9,0x8A,0xE0,0xE2,0xDE,0x57,0x4A,0xBF,
+	  0x33 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[0+28*6]; }
+	_EC_WTLS_12 = {
+	{ NID_X9_62_prime_field,0,28,1 },
+	{							/* no seed */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* p */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* a */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
+	  0xB4,0x05,0x0A,0x85,0x0C,0x04,0xB3,0xAB,0xF5,0x41,	/* b */
+	  0x32,0x56,0x50,0x44,0xB0,0xB7,0xD7,0xBF,0xD8,0xBA,
+	  0x27,0x0B,0x39,0x43,0x23,0x55,0xFF,0xB4,
+	  0xB7,0x0E,0x0C,0xBD,0x6B,0xB4,0xBF,0x7F,0x32,0x13,	/* x */
+	  0x90,0xB9,0x4A,0x03,0xC1,0xD3,0x56,0xC2,0x11,0x22,
+	  0x34,0x32,0x80,0xD6,0x11,0x5C,0x1D,0x21,
+	  0xbd,0x37,0x63,0x88,0xb5,0xf7,0x23,0xfb,0x4c,0x22,	/* y */
+	  0xdf,0xe6,0xcd,0x43,0x75,0xa0,0x5a,0x07,0x47,0x64,
+	  0x44,0xd5,0x81,0x99,0x85,0x00,0x7e,0x34,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* order */
+	  0xFF,0xFF,0xFF,0xFF,0x16,0xA2,0xE0,0xB8,0xF0,0x3E,
+	  0x13,0xDD,0x29,0x45,0x5C,0x5C,0x2A,0x3D }
+	};
+
+#ifndef OPENSSL_NO_EC2M
+
+/* characteristic two curves */
+static const struct { EC_CURVE_DATA h; unsigned char data[20+15*6]; }
+	_EC_SECG_CHAR2_113R1 = {
+	{ NID_X9_62_characteristic_two_field,20,15,2 },
+	{ 0x10,0xE7,0x23,0xAB,0x14,0xD6,0x96,0xE6,0x76,0x87,	/* seed */
+	  0x56,0x15,0x17,0x56,0xFE,0xBF,0x8F,0xCB,0x49,0xA9,
+
+	  0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x02,0x01,
+	  0x00,0x30,0x88,0x25,0x0C,0xA6,0xE7,0xC7,0xFE,0x64,	/* a */
+	  0x9C,0xE8,0x58,0x20,0xF7,
+	  0x00,0xE8,0xBE,0xE4,0xD3,0xE2,0x26,0x07,0x44,0x18,	/* b */
+	  0x8B,0xE0,0xE9,0xC7,0x23,
+	  0x00,0x9D,0x73,0x61,0x6F,0x35,0xF4,0xAB,0x14,0x07,	/* x */
+	  0xD7,0x35,0x62,0xC1,0x0F,
+	  0x00,0xA5,0x28,0x30,0x27,0x79,0x58,0xEE,0x84,0xD1,	/* y */
+	  0x31,0x5E,0xD3,0x18,0x86,
+	  0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD9,0xCC,	/* order */
+	  0xEC,0x8A,0x39,0xE5,0x6F }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+15*6]; }
+	_EC_SECG_CHAR2_113R2 = {
+	{ NID_X9_62_characteristic_two_field,20,15,2 },
+	{ 0x10,0xC0,0xFB,0x15,0x76,0x08,0x60,0xDE,0xF1,0xEE,	/* seed */
+	  0xF4,0xD6,0x96,0xE6,0x76,0x87,0x56,0x15,0x17,0x5D,
+
+	  0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x02,0x01,
+	  0x00,0x68,0x99,0x18,0xDB,0xEC,0x7E,0x5A,0x0D,0xD6,	/* a */
+	  0xDF,0xC0,0xAA,0x55,0xC7,
+	  0x00,0x95,0xE9,0xA9,0xEC,0x9B,0x29,0x7B,0xD4,0xBF,	/* b */
+	  0x36,0xE0,0x59,0x18,0x4F,
+	  0x01,0xA5,0x7A,0x6A,0x7B,0x26,0xCA,0x5E,0xF5,0x2F,	/* x */
+	  0xCD,0xB8,0x16,0x47,0x97,
+	  0x00,0xB3,0xAD,0xC9,0x4E,0xD1,0xFE,0x67,0x4C,0x06,	/* y */
+	  0xE6,0x95,0xBA,0xBA,0x1D,
+	  0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x08,0x78,	/* order */
+	  0x9B,0x24,0x96,0xAF,0x93 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+17*6]; }
+	_EC_SECG_CHAR2_131R1 = {
+	{ NID_X9_62_characteristic_two_field,20,17,2 },
+	{ 0x4D,0x69,0x6E,0x67,0x68,0x75,0x61,0x51,0x75,0x98,	/* seed */
+	  0x5B,0xD3,0xAD,0xBA,0xDA,0x21,0xB4,0x3A,0x97,0xE2,
+
+	  0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x01,0x0D,
+	  0x07,0xA1,0x1B,0x09,0xA7,0x6B,0x56,0x21,0x44,0x41,	/* a */
+	  0x8F,0xF3,0xFF,0x8C,0x25,0x70,0xB8,
+	  0x02,0x17,0xC0,0x56,0x10,0x88,0x4B,0x63,0xB9,0xC6,	/* b */
+	  0xC7,0x29,0x16,0x78,0xF9,0xD3,0x41,
+	  0x00,0x81,0xBA,0xF9,0x1F,0xDF,0x98,0x33,0xC4,0x0F,	/* x */
+	  0x9C,0x18,0x13,0x43,0x63,0x83,0x99,
+	  0x07,0x8C,0x6E,0x7E,0xA3,0x8C,0x00,0x1F,0x73,0xC8,	/* y */
+	  0x13,0x4B,0x1B,0x4E,0xF9,0xE1,0x50,
+	  0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x31,	/* order */
+	  0x23,0x95,0x3A,0x94,0x64,0xB5,0x4D }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+17*6]; }
+	_EC_SECG_CHAR2_131R2 = {
+	{ NID_X9_62_characteristic_two_field,20,17,2 },
+	{ 0x98,0x5B,0xD3,0xAD,0xBA,0xD4,0xD6,0x96,0xE6,0x76,	/* seed */
+	  0x87,0x56,0x15,0x17,0x5A,0x21,0xB4,0x3A,0x97,0xE3,
+
+	  0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x01,0x0D,
+	  0x03,0xE5,0xA8,0x89,0x19,0xD7,0xCA,0xFC,0xBF,0x41,	/* a */
+	  0x5F,0x07,0xC2,0x17,0x65,0x73,0xB2,
+	  0x04,0xB8,0x26,0x6A,0x46,0xC5,0x56,0x57,0xAC,0x73,	/* b */
+	  0x4C,0xE3,0x8F,0x01,0x8F,0x21,0x92,
+	  0x03,0x56,0xDC,0xD8,0xF2,0xF9,0x50,0x31,0xAD,0x65,	/* x */
+	  0x2D,0x23,0x95,0x1B,0xB3,0x66,0xA8,
+	  0x06,0x48,0xF0,0x6D,0x86,0x79,0x40,0xA5,0x36,0x6D,	/* y */
+	  0x9E,0x26,0x5D,0xE9,0xEB,0x24,0x0F,
+	  0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x69,	/* order */
+	  0x54,0xA2,0x33,0x04,0x9B,0xA9,0x8F }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[0+21*6]; }
+	_EC_NIST_CHAR2_163K = {
+	{ NID_X9_62_characteristic_two_field,0,21,2 },
+	{							/* no seed */
+	  0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0xC9,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* a */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x01,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* b */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x01,
+	  0x02,0xFE,0x13,0xC0,0x53,0x7B,0xBC,0x11,0xAC,0xAA,	/* x */
+	  0x07,0xD7,0x93,0xDE,0x4E,0x6D,0x5E,0x5C,0x94,0xEE,
+	  0xE8,
+	  0x02,0x89,0x07,0x0F,0xB0,0x5D,0x38,0xFF,0x58,0x32,	/* y */
+	  0x1F,0x2E,0x80,0x05,0x36,0xD5,0x38,0xCC,0xDA,0xA3,
+	  0xD9,
+	  0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* order */
+	  0x02,0x01,0x08,0xA2,0xE0,0xCC,0x0D,0x99,0xF8,0xA5,
+	  0xEF }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[0+21*6]; }
+	_EC_SECG_CHAR2_163R1 = {
+	{ NID_X9_62_characteristic_two_field,0,21,2 },
+	{							/* no seed */
+#if 0
+/* The algorithm used to derive the curve parameters from
+ * the seed used here is slightly different than the
+ * algorithm described in X9.62 . */
+	  0x24,0xB7,0xB1,0x37,0xC8,0xA1,0x4D,0x69,0x6E,0x67,
+	  0x68,0x75,0x61,0x51,0x75,0x6F,0xD0,0xDA,0x2E,0x5C,
+#endif
+	  0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0xC9,
+	  0x07,0xB6,0x88,0x2C,0xAA,0xEF,0xA8,0x4F,0x95,0x54,	/* a */
+	  0xFF,0x84,0x28,0xBD,0x88,0xE2,0x46,0xD2,0x78,0x2A,
+	  0xE2,
+	  0x07,0x13,0x61,0x2D,0xCD,0xDC,0xB4,0x0A,0xAB,0x94,	/* b */
+	  0x6B,0xDA,0x29,0xCA,0x91,0xF7,0x3A,0xF9,0x58,0xAF,
+	  0xD9,
+	  0x03,0x69,0x97,0x96,0x97,0xAB,0x43,0x89,0x77,0x89,	/* x */
+	  0x56,0x67,0x89,0x56,0x7F,0x78,0x7A,0x78,0x76,0xA6,
+	  0x54,
+	  0x00,0x43,0x5E,0xDB,0x42,0xEF,0xAF,0xB2,0x98,0x9D,	/* y */
+	  0x51,0xFE,0xFC,0xE3,0xC8,0x09,0x88,0xF4,0x1F,0xF8,
+	  0x83,
+	  0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* order */
+	  0xFF,0x48,0xAA,0xB6,0x89,0xC2,0x9C,0xA7,0x10,0x27,
+	  0x9B }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[0+21*6]; }
+	_EC_NIST_CHAR2_163B = {
+	{ NID_X9_62_characteristic_two_field,0,21,2 },
+	{							/* no seed */
+#if 0
+/* The seed here was used to created the curve parameters in normal
+ * basis representation (and not the polynomial representation used here) */
+	  0x85,0xE2,0x5B,0xFE,0x5C,0x86,0x22,0x6C,0xDB,0x12,
+	  0x01,0x6F,0x75,0x53,0xF9,0xD0,0xE6,0x93,0xA2,0x68,
+#endif
+	  0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0xC9,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* a */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x01,
+	  0x02,0x0A,0x60,0x19,0x07,0xB8,0xC9,0x53,0xCA,0x14,	/* b */
+	  0x81,0xEB,0x10,0x51,0x2F,0x78,0x74,0x4A,0x32,0x05,
+	  0xFD,
+	  0x03,0xF0,0xEB,0xA1,0x62,0x86,0xA2,0xD5,0x7E,0xA0,	/* x */
+	  0x99,0x11,0x68,0xD4,0x99,0x46,0x37,0xE8,0x34,0x3E,
+	  0x36,
+	  0x00,0xD5,0x1F,0xBC,0x6C,0x71,0xA0,0x09,0x4F,0xA2,	/* y */
+	  0xCD,0xD5,0x45,0xB1,0x1C,0x5C,0x0C,0x79,0x73,0x24,
+	  0xF1,
+	  0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* order */
+	  0x02,0x92,0xFE,0x77,0xE7,0x0C,0x12,0xA4,0x23,0x4C,
+	  0x33 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+25*6]; }
+	_EC_SECG_CHAR2_193R1 = {
+	{ NID_X9_62_characteristic_two_field,20,25,2 },
+	{ 0x10,0x3F,0xAE,0xC7,0x4D,0x69,0x6E,0x67,0x68,0x75,	/* seed */
+	  0x61,0x51,0x75,0x77,0x7F,0xC5,0xB1,0x91,0xEF,0x30,
+
+	  0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x80,0x01,
+	  0x00,0x17,0x85,0x8F,0xEB,0x7A,0x98,0x97,0x51,0x69,	/* a */
+	  0xE1,0x71,0xF7,0x7B,0x40,0x87,0xDE,0x09,0x8A,0xC8,
+	  0xA9,0x11,0xDF,0x7B,0x01,
+	  0x00,0xFD,0xFB,0x49,0xBF,0xE6,0xC3,0xA8,0x9F,0xAC,	/* b */
+	  0xAD,0xAA,0x7A,0x1E,0x5B,0xBC,0x7C,0xC1,0xC2,0xE5,
+	  0xD8,0x31,0x47,0x88,0x14,
+	  0x01,0xF4,0x81,0xBC,0x5F,0x0F,0xF8,0x4A,0x74,0xAD,	/* x */
+	  0x6C,0xDF,0x6F,0xDE,0xF4,0xBF,0x61,0x79,0x62,0x53,
+	  0x72,0xD8,0xC0,0xC5,0xE1,
+	  0x00,0x25,0xE3,0x99,0xF2,0x90,0x37,0x12,0xCC,0xF3,	/* y */
+	  0xEA,0x9E,0x3A,0x1A,0xD1,0x7F,0xB0,0xB3,0x20,0x1B,
+	  0x6A,0xF7,0xCE,0x1B,0x05,
+	  0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* order */
+	  0x00,0x00,0x00,0xC7,0xF3,0x4A,0x77,0x8F,0x44,0x3A,
+	  0xCC,0x92,0x0E,0xBA,0x49 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+25*6]; }
+	_EC_SECG_CHAR2_193R2 = {
+	{ NID_X9_62_characteristic_two_field,20,25,2 },
+	{ 0x10,0xB7,0xB4,0xD6,0x96,0xE6,0x76,0x87,0x56,0x15,	/* seed */
+	  0x17,0x51,0x37,0xC8,0xA1,0x6F,0xD0,0xDA,0x22,0x11,
+
+	  0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x80,0x01,
+	  0x01,0x63,0xF3,0x5A,0x51,0x37,0xC2,0xCE,0x3E,0xA6,	/* a */
+	  0xED,0x86,0x67,0x19,0x0B,0x0B,0xC4,0x3E,0xCD,0x69,
+	  0x97,0x77,0x02,0x70,0x9B,
+	  0x00,0xC9,0xBB,0x9E,0x89,0x27,0xD4,0xD6,0x4C,0x37,	/* b */
+	  0x7E,0x2A,0xB2,0x85,0x6A,0x5B,0x16,0xE3,0xEF,0xB7,
+	  0xF6,0x1D,0x43,0x16,0xAE,
+	  0x00,0xD9,0xB6,0x7D,0x19,0x2E,0x03,0x67,0xC8,0x03,	/* x */
+	  0xF3,0x9E,0x1A,0x7E,0x82,0xCA,0x14,0xA6,0x51,0x35,
+	  0x0A,0xAE,0x61,0x7E,0x8F,
+	  0x01,0xCE,0x94,0x33,0x56,0x07,0xC3,0x04,0xAC,0x29,	/* y */
+	  0xE7,0xDE,0xFB,0xD9,0xCA,0x01,0xF5,0x96,0xF9,0x27,
+	  0x22,0x4C,0xDE,0xCF,0x6C,
+	  0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* order */
+	  0x00,0x00,0x01,0x5A,0xAB,0x56,0x1B,0x00,0x54,0x13,
+	  0xCC,0xD4,0xEE,0x99,0xD5 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[0+30*6]; }
+	_EC_NIST_CHAR2_233K = {
+	{ NID_X9_62_characteristic_two_field,0,30,4 },
+	{							/* no seed */
+	  0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* a */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* b */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+
+	  0x01,0x72,0x32,0xBA,0x85,0x3A,0x7E,0x73,0x1A,0xF1,	/* x */
+	  0x29,0xF2,0x2F,0xF4,0x14,0x95,0x63,0xA4,0x19,0xC2,
+	  0x6B,0xF5,0x0A,0x4C,0x9D,0x6E,0xEF,0xAD,0x61,0x26,
+
+	  0x01,0xDB,0x53,0x7D,0xEC,0xE8,0x19,0xB7,0xF7,0x0F,	/* y */
+	  0x55,0x5A,0x67,0xC4,0x27,0xA8,0xCD,0x9B,0xF1,0x8A,
+	  0xEB,0x9B,0x56,0xE0,0xC1,0x10,0x56,0xFA,0xE6,0xA3,
+
+	  0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* order */
+	  0x00,0x00,0x00,0x00,0x00,0x06,0x9D,0x5B,0xB9,0x15,
+	  0xBC,0xD4,0x6E,0xFB,0x1A,0xD5,0xF1,0x73,0xAB,0xDF }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+30*6]; }
+	_EC_NIST_CHAR2_233B = {
+	{ NID_X9_62_characteristic_two_field,20,30,2 },
+	{ 0x74,0xD5,0x9F,0xF0,0x7F,0x6B,0x41,0x3D,0x0E,0xA1,	/* seed */
+	  0x4B,0x34,0x4B,0x20,0xA2,0xDB,0x04,0x9B,0x50,0xC3,
+
+	  0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* a */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+
+	  0x00,0x66,0x64,0x7E,0xDE,0x6C,0x33,0x2C,0x7F,0x8C,	/* b */
+	  0x09,0x23,0xBB,0x58,0x21,0x3B,0x33,0x3B,0x20,0xE9,
+	  0xCE,0x42,0x81,0xFE,0x11,0x5F,0x7D,0x8F,0x90,0xAD,
+
+	  0x00,0xFA,0xC9,0xDF,0xCB,0xAC,0x83,0x13,0xBB,0x21,	/* x */
+	  0x39,0xF1,0xBB,0x75,0x5F,0xEF,0x65,0xBC,0x39,0x1F,
+	  0x8B,0x36,0xF8,0xF8,0xEB,0x73,0x71,0xFD,0x55,0x8B,
+
+	  0x01,0x00,0x6A,0x08,0xA4,0x19,0x03,0x35,0x06,0x78,	/* y */
+	  0xE5,0x85,0x28,0xBE,0xBF,0x8A,0x0B,0xEF,0xF8,0x67,
+	  0xA7,0xCA,0x36,0x71,0x6F,0x7E,0x01,0xF8,0x10,0x52,
+
+	  0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* order */
+	  0x00,0x00,0x00,0x00,0x00,0x13,0xE9,0x74,0xE7,0x2F,
+	  0x8A,0x69,0x22,0x03,0x1D,0x26,0x03,0xCF,0xE0,0xD7 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[0+30*6]; }
+	_EC_SECG_CHAR2_239K1 = {
+	{ NID_X9_62_characteristic_two_field,0,30,4 },
+	{							/* no seed */
+	  0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* a */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* b */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+
+	  0x29,0xA0,0xB6,0xA8,0x87,0xA9,0x83,0xE9,0x73,0x09,	/* x */
+	  0x88,0xA6,0x87,0x27,0xA8,0xB2,0xD1,0x26,0xC4,0x4C,
+	  0xC2,0xCC,0x7B,0x2A,0x65,0x55,0x19,0x30,0x35,0xDC,
+
+	  0x76,0x31,0x08,0x04,0xF1,0x2E,0x54,0x9B,0xDB,0x01,	/* y */
+	  0x1C,0x10,0x30,0x89,0xE7,0x35,0x10,0xAC,0xB2,0x75,
+	  0xFC,0x31,0x2A,0x5D,0xC6,0xB7,0x65,0x53,0xF0,0xCA,
+
+	  0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* order */
+	  0x00,0x00,0x00,0x00,0x00,0x5A,0x79,0xFE,0xC6,0x7C,
+	  0xB6,0xE9,0x1F,0x1C,0x1D,0xA8,0x00,0xE4,0x78,0xA5 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[0+36*6]; }
+	_EC_NIST_CHAR2_283K = {
+	{ NID_X9_62_characteristic_two_field,0,36,4 },
+	{							/* no seed */
+	  0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x10,0xA1,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* a */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* b */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x01,
+	  0x05,0x03,0x21,0x3F,0x78,0xCA,0x44,0x88,0x3F,0x1A,	/* x */
+	  0x3B,0x81,0x62,0xF1,0x88,0xE5,0x53,0xCD,0x26,0x5F,
+	  0x23,0xC1,0x56,0x7A,0x16,0x87,0x69,0x13,0xB0,0xC2,
+	  0xAC,0x24,0x58,0x49,0x28,0x36,
+	  0x01,0xCC,0xDA,0x38,0x0F,0x1C,0x9E,0x31,0x8D,0x90,	/* y */
+	  0xF9,0x5D,0x07,0xE5,0x42,0x6F,0xE8,0x7E,0x45,0xC0,
+	  0xE8,0x18,0x46,0x98,0xE4,0x59,0x62,0x36,0x4E,0x34,
+	  0x11,0x61,0x77,0xDD,0x22,0x59,
+	  0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* order */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE9,0xAE,
+	  0x2E,0xD0,0x75,0x77,0x26,0x5D,0xFF,0x7F,0x94,0x45,
+	  0x1E,0x06,0x1E,0x16,0x3C,0x61 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+36*6]; }
+	_EC_NIST_CHAR2_283B = {
+	{ NID_X9_62_characteristic_two_field,20,36,2 },
+	{ 0x77,0xE2,0xB0,0x73,0x70,0xEB,0x0F,0x83,0x2A,0x6D,	/* no seed */
+	  0xD5,0xB6,0x2D,0xFC,0x88,0xCD,0x06,0xBB,0x84,0xBE,
+
+	  0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x10,0xA1,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* a */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x01,
+	  0x02,0x7B,0x68,0x0A,0xC8,0xB8,0x59,0x6D,0xA5,0xA4,	/* b */
+	  0xAF,0x8A,0x19,0xA0,0x30,0x3F,0xCA,0x97,0xFD,0x76,
+	  0x45,0x30,0x9F,0xA2,0xA5,0x81,0x48,0x5A,0xF6,0x26,
+	  0x3E,0x31,0x3B,0x79,0xA2,0xF5,
+	  0x05,0xF9,0x39,0x25,0x8D,0xB7,0xDD,0x90,0xE1,0x93,	/* x */
+	  0x4F,0x8C,0x70,0xB0,0xDF,0xEC,0x2E,0xED,0x25,0xB8,
+	  0x55,0x7E,0xAC,0x9C,0x80,0xE2,0xE1,0x98,0xF8,0xCD,
+	  0xBE,0xCD,0x86,0xB1,0x20,0x53,
+	  0x03,0x67,0x68,0x54,0xFE,0x24,0x14,0x1C,0xB9,0x8F,	/* y */
+	  0xE6,0xD4,0xB2,0x0D,0x02,0xB4,0x51,0x6F,0xF7,0x02,
+	  0x35,0x0E,0xDD,0xB0,0x82,0x67,0x79,0xC8,0x13,0xF0,
+	  0xDF,0x45,0xBE,0x81,0x12,0xF4,
+	  0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* order */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0x90,
+	  0x39,0x96,0x60,0xFC,0x93,0x8A,0x90,0x16,0x5B,0x04,
+	  0x2A,0x7C,0xEF,0xAD,0xB3,0x07 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[0+52*6]; }
+	_EC_NIST_CHAR2_409K = {
+	{ NID_X9_62_characteristic_two_field,0,52,4 },
+	{							/* no seed */
+	  0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x01,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* a */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* b */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x01,
+	  0x00,0x60,0xF0,0x5F,0x65,0x8F,0x49,0xC1,0xAD,0x3A,	/* x */
+	  0xB1,0x89,0x0F,0x71,0x84,0x21,0x0E,0xFD,0x09,0x87,
+	  0xE3,0x07,0xC8,0x4C,0x27,0xAC,0xCF,0xB8,0xF9,0xF6,
+	  0x7C,0xC2,0xC4,0x60,0x18,0x9E,0xB5,0xAA,0xAA,0x62,
+	  0xEE,0x22,0x2E,0xB1,0xB3,0x55,0x40,0xCF,0xE9,0x02,
+	  0x37,0x46,
+	  0x01,0xE3,0x69,0x05,0x0B,0x7C,0x4E,0x42,0xAC,0xBA,	/* y */
+	  0x1D,0xAC,0xBF,0x04,0x29,0x9C,0x34,0x60,0x78,0x2F,
+	  0x91,0x8E,0xA4,0x27,0xE6,0x32,0x51,0x65,0xE9,0xEA,
+	  0x10,0xE3,0xDA,0x5F,0x6C,0x42,0xE9,0xC5,0x52,0x15,
+	  0xAA,0x9C,0xA2,0x7A,0x58,0x63,0xEC,0x48,0xD8,0xE0,
+	  0x28,0x6B,
+	  0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* order */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x5F,0x83,0xB2,
+	  0xD4,0xEA,0x20,0x40,0x0E,0xC4,0x55,0x7D,0x5E,0xD3,
+	  0xE3,0xE7,0xCA,0x5B,0x4B,0x5C,0x83,0xB8,0xE0,0x1E,
+	  0x5F,0xCF }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+52*6]; }
+	_EC_NIST_CHAR2_409B = {
+	{ NID_X9_62_characteristic_two_field,20,52,2 },
+	{ 0x40,0x99,0xB5,0xA4,0x57,0xF9,0xD6,0x9F,0x79,0x21,	/* seed */
+	  0x3D,0x09,0x4C,0x4B,0xCD,0x4D,0x42,0x62,0x21,0x0B,
+
+	  0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x01,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* a */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x01,
+	  0x00,0x21,0xA5,0xC2,0xC8,0xEE,0x9F,0xEB,0x5C,0x4B,	/* b */
+	  0x9A,0x75,0x3B,0x7B,0x47,0x6B,0x7F,0xD6,0x42,0x2E,
+	  0xF1,0xF3,0xDD,0x67,0x47,0x61,0xFA,0x99,0xD6,0xAC,
+	  0x27,0xC8,0xA9,0xA1,0x97,0xB2,0x72,0x82,0x2F,0x6C,
+	  0xD5,0x7A,0x55,0xAA,0x4F,0x50,0xAE,0x31,0x7B,0x13,
+	  0x54,0x5F,
+	  0x01,0x5D,0x48,0x60,0xD0,0x88,0xDD,0xB3,0x49,0x6B,	/* x */
+	  0x0C,0x60,0x64,0x75,0x62,0x60,0x44,0x1C,0xDE,0x4A,
+	  0xF1,0x77,0x1D,0x4D,0xB0,0x1F,0xFE,0x5B,0x34,0xE5,
+	  0x97,0x03,0xDC,0x25,0x5A,0x86,0x8A,0x11,0x80,0x51,
+	  0x56,0x03,0xAE,0xAB,0x60,0x79,0x4E,0x54,0xBB,0x79,
+	  0x96,0xA7,
+	  0x00,0x61,0xB1,0xCF,0xAB,0x6B,0xE5,0xF3,0x2B,0xBF,	/* y */
+	  0xA7,0x83,0x24,0xED,0x10,0x6A,0x76,0x36,0xB9,0xC5,
+	  0xA7,0xBD,0x19,0x8D,0x01,0x58,0xAA,0x4F,0x54,0x88,
+	  0xD0,0x8F,0x38,0x51,0x4F,0x1F,0xDF,0x4B,0x4F,0x40,
+	  0xD2,0x18,0x1B,0x36,0x81,0xC3,0x64,0xBA,0x02,0x73,
+	  0xC7,0x06,
+	  0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* order */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xE2,0xAA,0xD6,
+	  0xA6,0x12,0xF3,0x33,0x07,0xBE,0x5F,0xA4,0x7C,0x3C,
+	  0x9E,0x05,0x2F,0x83,0x81,0x64,0xCD,0x37,0xD9,0xA2,
+	  0x11,0x73 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[0+72*6]; }
+	_EC_NIST_CHAR2_571K = {
+	{ NID_X9_62_characteristic_two_field,0,72,4 },
+	{							/* no seed */
+	  0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x04,0x25,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* a */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* b */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x01,
+	  0x02,0x6E,0xB7,0xA8,0x59,0x92,0x3F,0xBC,0x82,0x18,	/* x */
+	  0x96,0x31,0xF8,0x10,0x3F,0xE4,0xAC,0x9C,0xA2,0x97,
+	  0x00,0x12,0xD5,0xD4,0x60,0x24,0x80,0x48,0x01,0x84,
+	  0x1C,0xA4,0x43,0x70,0x95,0x84,0x93,0xB2,0x05,0xE6,
+	  0x47,0xDA,0x30,0x4D,0xB4,0xCE,0xB0,0x8C,0xBB,0xD1,
+	  0xBA,0x39,0x49,0x47,0x76,0xFB,0x98,0x8B,0x47,0x17,
+	  0x4D,0xCA,0x88,0xC7,0xE2,0x94,0x52,0x83,0xA0,0x1C,
+	  0x89,0x72,
+	  0x03,0x49,0xDC,0x80,0x7F,0x4F,0xBF,0x37,0x4F,0x4A,	/* y */
+	  0xEA,0xDE,0x3B,0xCA,0x95,0x31,0x4D,0xD5,0x8C,0xEC,
+	  0x9F,0x30,0x7A,0x54,0xFF,0xC6,0x1E,0xFC,0x00,0x6D,
+	  0x8A,0x2C,0x9D,0x49,0x79,0xC0,0xAC,0x44,0xAE,0xA7,
+	  0x4F,0xBE,0xBB,0xB9,0xF7,0x72,0xAE,0xDC,0xB6,0x20,
+	  0xB0,0x1A,0x7B,0xA7,0xAF,0x1B,0x32,0x04,0x30,0xC8,
+	  0x59,0x19,0x84,0xF6,0x01,0xCD,0x4C,0x14,0x3E,0xF1,
+	  0xC7,0xA3,
+	  0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* order */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x18,0x50,0xE1,
+	  0xF1,0x9A,0x63,0xE4,0xB3,0x91,0xA8,0xDB,0x91,0x7F,
+	  0x41,0x38,0xB6,0x30,0xD8,0x4B,0xE5,0xD6,0x39,0x38,
+	  0x1E,0x91,0xDE,0xB4,0x5C,0xFE,0x77,0x8F,0x63,0x7C,
+	  0x10,0x01 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+72*6]; }
+	_EC_NIST_CHAR2_571B = {
+	{ NID_X9_62_characteristic_two_field,20,72,2 },
+	{ 0x2A,0xA0,0x58,0xF7,0x3A,0x0E,0x33,0xAB,0x48,0x6B,	/* seed */
+	  0x0F,0x61,0x04,0x10,0xC5,0x3A,0x7F,0x13,0x23,0x10,
+
+	  0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x04,0x25,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* a */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x01,
+	  0x02,0xF4,0x0E,0x7E,0x22,0x21,0xF2,0x95,0xDE,0x29,	/* b */
+	  0x71,0x17,0xB7,0xF3,0xD6,0x2F,0x5C,0x6A,0x97,0xFF,
+	  0xCB,0x8C,0xEF,0xF1,0xCD,0x6B,0xA8,0xCE,0x4A,0x9A,
+	  0x18,0xAD,0x84,0xFF,0xAB,0xBD,0x8E,0xFA,0x59,0x33,
+	  0x2B,0xE7,0xAD,0x67,0x56,0xA6,0x6E,0x29,0x4A,0xFD,
+	  0x18,0x5A,0x78,0xFF,0x12,0xAA,0x52,0x0E,0x4D,0xE7,
+	  0x39,0xBA,0xCA,0x0C,0x7F,0xFE,0xFF,0x7F,0x29,0x55,
+	  0x72,0x7A,
+	  0x03,0x03,0x00,0x1D,0x34,0xB8,0x56,0x29,0x6C,0x16,	/* x */
+	  0xC0,0xD4,0x0D,0x3C,0xD7,0x75,0x0A,0x93,0xD1,0xD2,
+	  0x95,0x5F,0xA8,0x0A,0xA5,0xF4,0x0F,0xC8,0xDB,0x7B,
+	  0x2A,0xBD,0xBD,0xE5,0x39,0x50,0xF4,0xC0,0xD2,0x93,
+	  0xCD,0xD7,0x11,0xA3,0x5B,0x67,0xFB,0x14,0x99,0xAE,
+	  0x60,0x03,0x86,0x14,0xF1,0x39,0x4A,0xBF,0xA3,0xB4,
+	  0xC8,0x50,0xD9,0x27,0xE1,0xE7,0x76,0x9C,0x8E,0xEC,
+	  0x2D,0x19,
+	  0x03,0x7B,0xF2,0x73,0x42,0xDA,0x63,0x9B,0x6D,0xCC,	/* y */
+	  0xFF,0xFE,0xB7,0x3D,0x69,0xD7,0x8C,0x6C,0x27,0xA6,
+	  0x00,0x9C,0xBB,0xCA,0x19,0x80,0xF8,0x53,0x39,0x21,
+	  0xE8,0xA6,0x84,0x42,0x3E,0x43,0xBA,0xB0,0x8A,0x57,
+	  0x62,0x91,0xAF,0x8F,0x46,0x1B,0xB2,0xA8,0xB3,0x53,
+	  0x1D,0x2F,0x04,0x85,0xC1,0x9B,0x16,0xE2,0xF1,0x51,
+	  0x6E,0x23,0xDD,0x3C,0x1A,0x48,0x27,0xAF,0x1B,0x8A,
+	  0xC1,0x5B,
+	  0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* order */
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+	  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x61,0xCE,0x18,
+	  0xFF,0x55,0x98,0x73,0x08,0x05,0x9B,0x18,0x68,0x23,
+	  0x85,0x1E,0xC7,0xDD,0x9C,0xA1,0x16,0x1D,0xE9,0x3D,
+	  0x51,0x74,0xD6,0x6E,0x83,0x82,0xE9,0xBB,0x2F,0xE8,
+	  0x4E,0x47 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+21*6]; }
+	_EC_X9_62_CHAR2_163V1 = {
+	{ NID_X9_62_characteristic_two_field,20,21,2 },
+	{ 0xD2,0xC0,0xFB,0x15,0x76,0x08,0x60,0xDE,0xF1,0xEE,
+	  0xF4,0xD6,0x96,0xE6,0x76,0x87,0x56,0x15,0x17,0x54,	/* seed */
+
+	  0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+	  0x07,
+	  0x07,0x25,0x46,0xB5,0x43,0x52,0x34,0xA4,0x22,0xE0,	/* a */
+	  0x78,0x96,0x75,0xF4,0x32,0xC8,0x94,0x35,0xDE,0x52,
+	  0x42,
+	  0x00,0xC9,0x51,0x7D,0x06,0xD5,0x24,0x0D,0x3C,0xFF,	/* b */
+	  0x38,0xC7,0x4B,0x20,0xB6,0xCD,0x4D,0x6F,0x9D,0xD4,
+	  0xD9,
+	  0x07,0xAF,0x69,0x98,0x95,0x46,0x10,0x3D,0x79,0x32,	/* x */
+	  0x9F,0xCC,0x3D,0x74,0x88,0x0F,0x33,0xBB,0xE8,0x03,
+	  0xCB,
+	  0x01,0xEC,0x23,0x21,0x1B,0x59,0x66,0xAD,0xEA,0x1D,	/* y */
+	  0x3F,0x87,0xF7,0xEA,0x58,0x48,0xAE,0xF0,0xB7,0xCA,
+	  0x9F,
+	  0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* order */
+	  0x01,0xE6,0x0F,0xC8,0x82,0x1C,0xC7,0x4D,0xAE,0xAF,
+	  0xC1 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+21*6]; }
+	_EC_X9_62_CHAR2_163V2 = {
+	{ NID_X9_62_characteristic_two_field,20,21,2 },
+	{ 0x53,0x81,0x4C,0x05,0x0D,0x44,0xD6,0x96,0xE6,0x76,	/* seed */
+	  0x87,0x56,0x15,0x17,0x58,0x0C,0xA4,0xE2,0x9F,0xFD,
+
+	  0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+	  0x07,
+	  0x01,0x08,0xB3,0x9E,0x77,0xC4,0xB1,0x08,0xBE,0xD9,	/* a */
+	  0x81,0xED,0x0E,0x89,0x0E,0x11,0x7C,0x51,0x1C,0xF0,
+	  0x72,
+	  0x06,0x67,0xAC,0xEB,0x38,0xAF,0x4E,0x48,0x8C,0x40,	/* b */
+	  0x74,0x33,0xFF,0xAE,0x4F,0x1C,0x81,0x16,0x38,0xDF,
+	  0x20,
+	  0x00,0x24,0x26,0x6E,0x4E,0xB5,0x10,0x6D,0x0A,0x96,	/* x */
+	  0x4D,0x92,0xC4,0x86,0x0E,0x26,0x71,0xDB,0x9B,0x6C,
+	  0xC5,
+	  0x07,0x9F,0x68,0x4D,0xDF,0x66,0x84,0xC5,0xCD,0x25,	/* y */
+	  0x8B,0x38,0x90,0x02,0x1B,0x23,0x86,0xDF,0xD1,0x9F,
+	  0xC5,
+	  0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* order */
+	  0xFD,0xF6,0x4D,0xE1,0x15,0x1A,0xDB,0xB7,0x8F,0x10,
+	  0xA7 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+21*6]; }
+	_EC_X9_62_CHAR2_163V3 = {
+	{ NID_X9_62_characteristic_two_field,20,21,2 },
+	{ 0x50,0xCB,0xF1,0xD9,0x5C,0xA9,0x4D,0x69,0x6E,0x67,	/* seed */
+	  0x68,0x75,0x61,0x51,0x75,0xF1,0x6A,0x36,0xA3,0xB8,
+
+	  0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+	  0x07,
+	  0x07,0xA5,0x26,0xC6,0x3D,0x3E,0x25,0xA2,0x56,0xA0,	/* a */
+	  0x07,0x69,0x9F,0x54,0x47,0xE3,0x2A,0xE4,0x56,0xB5,
+	  0x0E,
+	  0x03,0xF7,0x06,0x17,0x98,0xEB,0x99,0xE2,0x38,0xFD,	/* b */
+	  0x6F,0x1B,0xF9,0x5B,0x48,0xFE,0xEB,0x48,0x54,0x25,
+	  0x2B,
+	  0x02,0xF9,0xF8,0x7B,0x7C,0x57,0x4D,0x0B,0xDE,0xCF,	/* x */
+	  0x8A,0x22,0xE6,0x52,0x47,0x75,0xF9,0x8C,0xDE,0xBD,
+	  0xCB,
+	  0x05,0xB9,0x35,0x59,0x0C,0x15,0x5E,0x17,0xEA,0x48,	/* y */
+	  0xEB,0x3F,0xF3,0x71,0x8B,0x89,0x3D,0xF5,0x9A,0x05,
+	  0xD0,
+	  0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* order */
+	  0xFE,0x1A,0xEE,0x14,0x0F,0x11,0x0A,0xFF,0x96,0x13,
+	  0x09 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[0+23*6]; }
+	_EC_X9_62_CHAR2_176V1 = {
+	{ NID_X9_62_characteristic_two_field,0,23,0xFF6E },
+	{							/* no seed */
+	  0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,
+	  0x00,0x00,0x07,
+	  0x00,0xE4,0xE6,0xDB,0x29,0x95,0x06,0x5C,0x40,0x7D,	/* a */
+	  0x9D,0x39,0xB8,0xD0,0x96,0x7B,0x96,0x70,0x4B,0xA8,
+	  0xE9,0xC9,0x0B,
+	  0x00,0x5D,0xDA,0x47,0x0A,0xBE,0x64,0x14,0xDE,0x8E,	/* b */
+	  0xC1,0x33,0xAE,0x28,0xE9,0xBB,0xD7,0xFC,0xEC,0x0A,
+	  0xE0,0xFF,0xF2,
+	  0x00,0x8D,0x16,0xC2,0x86,0x67,0x98,0xB6,0x00,0xF9,	/* x */
+	  0xF0,0x8B,0xB4,0xA8,0xE8,0x60,0xF3,0x29,0x8C,0xE0,
+	  0x4A,0x57,0x98,
+	  0x00,0x6F,0xA4,0x53,0x9C,0x2D,0xAD,0xDD,0xD6,0xBA,	/* y */
+	  0xB5,0x16,0x7D,0x61,0xB4,0x36,0xE1,0xD9,0x2B,0xB1,
+	  0x6A,0x56,0x2C,
+	  0x00,0x00,0x01,0x00,0x92,0x53,0x73,0x97,0xEC,0xA4,	/* order */
+	  0xF6,0x14,0x57,0x99,0xD6,0x2B,0x0A,0x19,0xCE,0x06,
+	  0xFE,0x26,0xAD }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+24*6]; }
+	_EC_X9_62_CHAR2_191V1 = {
+	{ NID_X9_62_characteristic_two_field,20,24,2 },
+	{ 0x4E,0x13,0xCA,0x54,0x27,0x44,0xD6,0x96,0xE6,0x76,	/* seed */
+	  0x87,0x56,0x15,0x17,0x55,0x2F,0x27,0x9A,0x8C,0x84,
+
+	  0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x02,0x01,
+	  0x28,0x66,0x53,0x7B,0x67,0x67,0x52,0x63,0x6A,0x68,	/* a */
+	  0xF5,0x65,0x54,0xE1,0x26,0x40,0x27,0x6B,0x64,0x9E,
+	  0xF7,0x52,0x62,0x67,
+	  0x2E,0x45,0xEF,0x57,0x1F,0x00,0x78,0x6F,0x67,0xB0,	/* b */
+	  0x08,0x1B,0x94,0x95,0xA3,0xD9,0x54,0x62,0xF5,0xDE,
+	  0x0A,0xA1,0x85,0xEC,
+	  0x36,0xB3,0xDA,0xF8,0xA2,0x32,0x06,0xF9,0xC4,0xF2,	/* x */
+	  0x99,0xD7,0xB2,0x1A,0x9C,0x36,0x91,0x37,0xF2,0xC8,
+	  0x4A,0xE1,0xAA,0x0D,
+	  0x76,0x5B,0xE7,0x34,0x33,0xB3,0xF9,0x5E,0x33,0x29,	/* y */
+	  0x32,0xE7,0x0E,0xA2,0x45,0xCA,0x24,0x18,0xEA,0x0E,
+	  0xF9,0x80,0x18,0xFB,
+	  0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* order */
+	  0x00,0x00,0x04,0xA2,0x0E,0x90,0xC3,0x90,0x67,0xC8,
+	  0x93,0xBB,0xB9,0xA5 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+24*6]; }
+	_EC_X9_62_CHAR2_191V2 = {
+	{ NID_X9_62_characteristic_two_field,20,24,4 },
+	{ 0x08,0x71,0xEF,0x2F,0xEF,0x24,0xD6,0x96,0xE6,0x76,	/* seed */
+	  0x87,0x56,0x15,0x17,0x58,0xBE,0xE0,0xD9,0x5C,0x15,
+
+	  0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x02,0x01,
+	  0x40,0x10,0x28,0x77,0x4D,0x77,0x77,0xC7,0xB7,0x66,	/* a */
+	  0x6D,0x13,0x66,0xEA,0x43,0x20,0x71,0x27,0x4F,0x89,
+	  0xFF,0x01,0xE7,0x18,
+	  0x06,0x20,0x04,0x8D,0x28,0xBC,0xBD,0x03,0xB6,0x24,	/* b */
+	  0x9C,0x99,0x18,0x2B,0x7C,0x8C,0xD1,0x97,0x00,0xC3,
+	  0x62,0xC4,0x6A,0x01,
+	  0x38,0x09,0xB2,0xB7,0xCC,0x1B,0x28,0xCC,0x5A,0x87,	/* x */
+	  0x92,0x6A,0xAD,0x83,0xFD,0x28,0x78,0x9E,0x81,0xE2,
+	  0xC9,0xE3,0xBF,0x10,
+	  0x17,0x43,0x43,0x86,0x62,0x6D,0x14,0xF3,0xDB,0xF0,	/* y */
+	  0x17,0x60,0xD9,0x21,0x3A,0x3E,0x1C,0xF3,0x7A,0xEC,
+	  0x43,0x7D,0x66,0x8A,
+	  0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* order */
+	  0x00,0x00,0x50,0x50,0x8C,0xB8,0x9F,0x65,0x28,0x24,
+	  0xE0,0x6B,0x81,0x73 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+24*6]; }
+	_EC_X9_62_CHAR2_191V3 = {
+	{ NID_X9_62_characteristic_two_field,20,24,6 },
+	{ 0xE0,0x53,0x51,0x2D,0xC6,0x84,0xD6,0x96,0xE6,0x76,	/* seed */
+	  0x87,0x56,0x15,0x17,0x50,0x67,0xAE,0x78,0x6D,0x1F,
+
+	  0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x02,0x01,
+	  0x6C,0x01,0x07,0x47,0x56,0x09,0x91,0x22,0x22,0x10,	/* a */
+	  0x56,0x91,0x1C,0x77,0xD7,0x7E,0x77,0xA7,0x77,0xE7,
+	  0xE7,0xE7,0x7F,0xCB,
+	  0x71,0xFE,0x1A,0xF9,0x26,0xCF,0x84,0x79,0x89,0xEF,	/* b */
+	  0xEF,0x8D,0xB4,0x59,0xF6,0x63,0x94,0xD9,0x0F,0x32,
+	  0xAD,0x3F,0x15,0xE8,
+	  0x37,0x5D,0x4C,0xE2,0x4F,0xDE,0x43,0x44,0x89,0xDE,	/* x */
+	  0x87,0x46,0xE7,0x17,0x86,0x01,0x50,0x09,0xE6,0x6E,
+	  0x38,0xA9,0x26,0xDD,
+	  0x54,0x5A,0x39,0x17,0x61,0x96,0x57,0x5D,0x98,0x59,	/* y */
+	  0x99,0x36,0x6E,0x6A,0xD3,0x4C,0xE0,0xA7,0x7C,0xD7,
+	  0x12,0x7B,0x06,0xBE,
+	  0x15,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,	/* order */
+	  0x55,0x55,0x61,0x0C,0x0B,0x19,0x68,0x12,0xBF,0xB6,
+	  0x28,0x8A,0x3E,0xA3 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[0+27*6]; }
+	_EC_X9_62_CHAR2_208W1 = {
+	{ NID_X9_62_characteristic_two_field,0,27,0xFE48 },
+	{							/* no seed */
+	  0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* a */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0xC8,0x61,0x9E,0xD4,0x5A,0x62,0xE6,0x21,0x2E,	/* b */
+	  0x11,0x60,0x34,0x9E,0x2B,0xFA,0x84,0x44,0x39,0xFA,
+	  0xFC,0x2A,0x3F,0xD1,0x63,0x8F,0x9E,
+	  0x00,0x89,0xFD,0xFB,0xE4,0xAB,0xE1,0x93,0xDF,0x95,	/* x */
+	  0x59,0xEC,0xF0,0x7A,0xC0,0xCE,0x78,0x55,0x4E,0x27,
+	  0x84,0xEB,0x8C,0x1E,0xD1,0xA5,0x7A,
+	  0x00,0x0F,0x55,0xB5,0x1A,0x06,0xE7,0x8E,0x9A,0xC3,	/* y */
+	  0x8A,0x03,0x5F,0xF5,0x20,0xD8,0xB0,0x17,0x81,0xBE,
+	  0xB1,0xA6,0xBB,0x08,0x61,0x7D,0xE3,
+	  0x00,0x00,0x01,0x01,0xBA,0xF9,0x5C,0x97,0x23,0xC5,	/* order */
+	  0x7B,0x6C,0x21,0xDA,0x2E,0xFF,0x2D,0x5E,0xD5,0x88,
+	  0xBD,0xD5,0x71,0x7E,0x21,0x2F,0x9D }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+30*6]; }
+	_EC_X9_62_CHAR2_239V1 = {
+	{ NID_X9_62_characteristic_two_field,20,30,4 },
+	{ 0xD3,0x4B,0x9A,0x4D,0x69,0x6E,0x67,0x68,0x75,0x61,	/* seed */
+	  0x51,0x75,0xCA,0x71,0xB9,0x20,0xBF,0xEF,0xB0,0x5D,
+
+	  0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,
+
+	  0x32,0x01,0x08,0x57,0x07,0x7C,0x54,0x31,0x12,0x3A,	/* a */
+	  0x46,0xB8,0x08,0x90,0x67,0x56,0xF5,0x43,0x42,0x3E,
+	  0x8D,0x27,0x87,0x75,0x78,0x12,0x57,0x78,0xAC,0x76,
+
+	  0x79,0x04,0x08,0xF2,0xEE,0xDA,0xF3,0x92,0xB0,0x12,	/* b */
+	  0xED,0xEF,0xB3,0x39,0x2F,0x30,0xF4,0x32,0x7C,0x0C,
+	  0xA3,0xF3,0x1F,0xC3,0x83,0xC4,0x22,0xAA,0x8C,0x16,
+
+	  0x57,0x92,0x70,0x98,0xFA,0x93,0x2E,0x7C,0x0A,0x96,	/* x */
+	  0xD3,0xFD,0x5B,0x70,0x6E,0xF7,0xE5,0xF5,0xC1,0x56,
+	  0xE1,0x6B,0x7E,0x7C,0x86,0x03,0x85,0x52,0xE9,0x1D,
+
+	  0x61,0xD8,0xEE,0x50,0x77,0xC3,0x3F,0xEC,0xF6,0xF1,	/* y */
+	  0xA1,0x6B,0x26,0x8D,0xE4,0x69,0xC3,0xC7,0x74,0x4E,
+	  0xA9,0xA9,0x71,0x64,0x9F,0xC7,0xA9,0x61,0x63,0x05,
+
+	  0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* order */
+	  0x00,0x00,0x00,0x00,0x00,0x0F,0x4D,0x42,0xFF,0xE1,
+	  0x49,0x2A,0x49,0x93,0xF1,0xCA,0xD6,0x66,0xE4,0x47 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+30*6]; }
+	_EC_X9_62_CHAR2_239V2 = {
+	{ NID_X9_62_characteristic_two_field,20,30,6 },
+	{ 0x2A,0xA6,0x98,0x2F,0xDF,0xA4,0xD6,0x96,0xE6,0x76,	/* seed */
+	  0x87,0x56,0x15,0x17,0x5D,0x26,0x67,0x27,0x27,0x7D,
+
+	  0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,
+
+	  0x42,0x30,0x01,0x77,0x57,0xA7,0x67,0xFA,0xE4,0x23,	/* a */
+	  0x98,0x56,0x9B,0x74,0x63,0x25,0xD4,0x53,0x13,0xAF,
+	  0x07,0x66,0x26,0x64,0x79,0xB7,0x56,0x54,0xE6,0x5F,
+
+	  0x50,0x37,0xEA,0x65,0x41,0x96,0xCF,0xF0,0xCD,0x82,	/* b */
+	  0xB2,0xC1,0x4A,0x2F,0xCF,0x2E,0x3F,0xF8,0x77,0x52,
+	  0x85,0xB5,0x45,0x72,0x2F,0x03,0xEA,0xCD,0xB7,0x4B,
+
+	  0x28,0xF9,0xD0,0x4E,0x90,0x00,0x69,0xC8,0xDC,0x47,	/* x */
+	  0xA0,0x85,0x34,0xFE,0x76,0xD2,0xB9,0x00,0xB7,0xD7,
+	  0xEF,0x31,0xF5,0x70,0x9F,0x20,0x0C,0x4C,0xA2,0x05,
+
+	  0x56,0x67,0x33,0x4C,0x45,0xAF,0xF3,0xB5,0xA0,0x3B,	/* y */
+	  0xAD,0x9D,0xD7,0x5E,0x2C,0x71,0xA9,0x93,0x62,0x56,
+	  0x7D,0x54,0x53,0xF7,0xFA,0x6E,0x22,0x7E,0xC8,0x33,
+
+	  0x15,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,	/* order */
+	  0x55,0x55,0x55,0x55,0x55,0x3C,0x6F,0x28,0x85,0x25,
+	  0x9C,0x31,0xE3,0xFC,0xDF,0x15,0x46,0x24,0x52,0x2D }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+30*6]; }
+	_EC_X9_62_CHAR2_239V3 = {
+	{ NID_X9_62_characteristic_two_field,20,30,0xA },
+	{ 0x9E,0x07,0x6F,0x4D,0x69,0x6E,0x67,0x68,0x75,0x61,	/* seed */
+	  0x51,0x75,0xE1,0x1E,0x9F,0xDD,0x77,0xF9,0x20,0x41,
+
+	  0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,
+
+	  0x01,0x23,0x87,0x74,0x66,0x6A,0x67,0x76,0x6D,0x66,	/* a */
+	  0x76,0xF7,0x78,0xE6,0x76,0xB6,0x69,0x99,0x17,0x66,
+	  0x66,0xE6,0x87,0x66,0x6D,0x87,0x66,0xC6,0x6A,0x9F,
+
+	  0x6A,0x94,0x19,0x77,0xBA,0x9F,0x6A,0x43,0x51,0x99,	/* b */
+	  0xAC,0xFC,0x51,0x06,0x7E,0xD5,0x87,0xF5,0x19,0xC5,
+	  0xEC,0xB5,0x41,0xB8,0xE4,0x41,0x11,0xDE,0x1D,0x40,
+
+	  0x70,0xF6,0xE9,0xD0,0x4D,0x28,0x9C,0x4E,0x89,0x91,	/* x */
+	  0x3C,0xE3,0x53,0x0B,0xFD,0xE9,0x03,0x97,0x7D,0x42,
+	  0xB1,0x46,0xD5,0x39,0xBF,0x1B,0xDE,0x4E,0x9C,0x92,
+
+	  0x2E,0x5A,0x0E,0xAF,0x6E,0x5E,0x13,0x05,0xB9,0x00,	/* y */
+	  0x4D,0xCE,0x5C,0x0E,0xD7,0xFE,0x59,0xA3,0x56,0x08,
+	  0xF3,0x38,0x37,0xC8,0x16,0xD8,0x0B,0x79,0xF4,0x61,
+
+	  0x0C,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,	/* order */
+	  0xCC,0xCC,0xCC,0xCC,0xCC,0xAC,0x49,0x12,0xD2,0xD9,
+	  0xDF,0x90,0x3E,0xF9,0x88,0x8B,0x8A,0x0E,0x4C,0xFF }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[0+35*6]; }
+	_EC_X9_62_CHAR2_272W1 = {
+	{ NID_X9_62_characteristic_two_field,0,35,0xFF06 },
+	{							/* no seed */
+	  0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x0B,
+	  0x00,0x91,0xA0,0x91,0xF0,0x3B,0x5F,0xBA,0x4A,0xB2,	/* a */
+	  0xCC,0xF4,0x9C,0x4E,0xDD,0x22,0x0F,0xB0,0x28,0x71,
+	  0x2D,0x42,0xBE,0x75,0x2B,0x2C,0x40,0x09,0x4D,0xBA,
+	  0xCD,0xB5,0x86,0xFB,0x20,
+	  0x00,0x71,0x67,0xEF,0xC9,0x2B,0xB2,0xE3,0xCE,0x7C,	/* b */
+	  0x8A,0xAA,0xFF,0x34,0xE1,0x2A,0x9C,0x55,0x70,0x03,
+	  0xD7,0xC7,0x3A,0x6F,0xAF,0x00,0x3F,0x99,0xF6,0xCC,
+	  0x84,0x82,0xE5,0x40,0xF7,
+	  0x00,0x61,0x08,0xBA,0xBB,0x2C,0xEE,0xBC,0xF7,0x87,	/* x */
+	  0x05,0x8A,0x05,0x6C,0xBE,0x0C,0xFE,0x62,0x2D,0x77,
+	  0x23,0xA2,0x89,0xE0,0x8A,0x07,0xAE,0x13,0xEF,0x0D,
+	  0x10,0xD1,0x71,0xDD,0x8D,
+	  0x00,0x10,0xC7,0x69,0x57,0x16,0x85,0x1E,0xEF,0x6B,	/* y */
+	  0xA7,0xF6,0x87,0x2E,0x61,0x42,0xFB,0xD2,0x41,0xB8,
+	  0x30,0xFF,0x5E,0xFC,0xAC,0xEC,0xCA,0xB0,0x5E,0x02,
+	  0x00,0x5D,0xDE,0x9D,0x23,
+	  0x00,0x00,0x01,0x00,0xFA,0xF5,0x13,0x54,0xE0,0xE3,	/* order */
+	  0x9E,0x48,0x92,0xDF,0x6E,0x31,0x9C,0x72,0xC8,0x16,
+	  0x16,0x03,0xFA,0x45,0xAA,0x7B,0x99,0x8A,0x16,0x7B,
+	  0x8F,0x1E,0x62,0x95,0x21 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[0+39*6]; }
+	_EC_X9_62_CHAR2_304W1 = {
+	{ NID_X9_62_characteristic_two_field,0,39,0xFE2E },
+	{							/* no seed */
+	  0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x07,
+	  0x00,0xFD,0x0D,0x69,0x31,0x49,0xA1,0x18,0xF6,0x51,	/* a */
+	  0xE6,0xDC,0xE6,0x80,0x20,0x85,0x37,0x7E,0x5F,0x88,
+	  0x2D,0x1B,0x51,0x0B,0x44,0x16,0x00,0x74,0xC1,0x28,
+	  0x80,0x78,0x36,0x5A,0x03,0x96,0xC8,0xE6,0x81,
+	  0x00,0xBD,0xDB,0x97,0xE5,0x55,0xA5,0x0A,0x90,0x8E,	/* b */
+	  0x43,0xB0,0x1C,0x79,0x8E,0xA5,0xDA,0xA6,0x78,0x8F,
+	  0x1E,0xA2,0x79,0x4E,0xFC,0xF5,0x71,0x66,0xB8,0xC1,
+	  0x40,0x39,0x60,0x1E,0x55,0x82,0x73,0x40,0xBE,
+	  0x00,0x19,0x7B,0x07,0x84,0x5E,0x9B,0xE2,0xD9,0x6A,	/* x */
+	  0xDB,0x0F,0x5F,0x3C,0x7F,0x2C,0xFF,0xBD,0x7A,0x3E,
+	  0xB8,0xB6,0xFE,0xC3,0x5C,0x7F,0xD6,0x7F,0x26,0xDD,
+	  0xF6,0x28,0x5A,0x64,0x4F,0x74,0x0A,0x26,0x14,
+	  0x00,0xE1,0x9F,0xBE,0xB7,0x6E,0x0D,0xA1,0x71,0x51,	/* y */
+	  0x7E,0xCF,0x40,0x1B,0x50,0x28,0x9B,0xF0,0x14,0x10,
+	  0x32,0x88,0x52,0x7A,0x9B,0x41,0x6A,0x10,0x5E,0x80,
+	  0x26,0x0B,0x54,0x9F,0xDC,0x1B,0x92,0xC0,0x3B,
+	  0x00,0x00,0x01,0x01,0xD5,0x56,0x57,0x2A,0xAB,0xAC,	/* order */
+	  0x80,0x01,0x01,0xD5,0x56,0x57,0x2A,0xAB,0xAC,0x80,
+	  0x01,0x02,0x2D,0x5C,0x91,0xDD,0x17,0x3F,0x8F,0xB5,
+	  0x61,0xDA,0x68,0x99,0x16,0x44,0x43,0x05,0x1D }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[20+45*6]; }
+	_EC_X9_62_CHAR2_359V1 = {
+	{ NID_X9_62_characteristic_two_field,20,45,0x4C },
+	{ 0x2B,0x35,0x49,0x20,0xB7,0x24,0xD6,0x96,0xE6,0x76,	/* seed */
+	  0x87,0x56,0x15,0x17,0x58,0x5B,0xA1,0x33,0x2D,0xC6,
+
+	  0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x01,
+	  0x56,0x67,0x67,0x6A,0x65,0x4B,0x20,0x75,0x4F,0x35,	/* a */
+	  0x6E,0xA9,0x20,0x17,0xD9,0x46,0x56,0x7C,0x46,0x67,
+	  0x55,0x56,0xF1,0x95,0x56,0xA0,0x46,0x16,0xB5,0x67,
+	  0xD2,0x23,0xA5,0xE0,0x56,0x56,0xFB,0x54,0x90,0x16,
+	  0xA9,0x66,0x56,0xA5,0x57,
+	  0x24,0x72,0xE2,0xD0,0x19,0x7C,0x49,0x36,0x3F,0x1F,	/* b */
+	  0xE7,0xF5,0xB6,0xDB,0x07,0x5D,0x52,0xB6,0x94,0x7D,
+	  0x13,0x5D,0x8C,0xA4,0x45,0x80,0x5D,0x39,0xBC,0x34,
+	  0x56,0x26,0x08,0x96,0x87,0x74,0x2B,0x63,0x29,0xE7,
+	  0x06,0x80,0x23,0x19,0x88,
+	  0x3C,0x25,0x8E,0xF3,0x04,0x77,0x67,0xE7,0xED,0xE0,	/* x */
+	  0xF1,0xFD,0xAA,0x79,0xDA,0xEE,0x38,0x41,0x36,0x6A,
+	  0x13,0x2E,0x16,0x3A,0xCE,0xD4,0xED,0x24,0x01,0xDF,
+	  0x9C,0x6B,0xDC,0xDE,0x98,0xE8,0xE7,0x07,0xC0,0x7A,
+	  0x22,0x39,0xB1,0xB0,0x97,
+	  0x53,0xD7,0xE0,0x85,0x29,0x54,0x70,0x48,0x12,0x1E,	/* y */
+	  0x9C,0x95,0xF3,0x79,0x1D,0xD8,0x04,0x96,0x39,0x48,
+	  0xF3,0x4F,0xAE,0x7B,0xF4,0x4E,0xA8,0x23,0x65,0xDC,
+	  0x78,0x68,0xFE,0x57,0xE4,0xAE,0x2D,0xE2,0x11,0x30,
+	  0x5A,0x40,0x71,0x04,0xBD,
+	  0x01,0xAF,0x28,0x6B,0xCA,0x1A,0xF2,0x86,0xBC,0xA1,	/* order */
+	  0xAF,0x28,0x6B,0xCA,0x1A,0xF2,0x86,0xBC,0xA1,0xAF,
+	  0x28,0x6B,0xC9,0xFB,0x8F,0x6B,0x85,0xC5,0x56,0x89,
+	  0x2C,0x20,0xA7,0xEB,0x96,0x4F,0xE7,0x71,0x9E,0x74,
+	  0xF4,0x90,0x75,0x8D,0x3B }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[0+47*6]; }
+	_EC_X9_62_CHAR2_368W1 = {
+	{ NID_X9_62_characteristic_two_field,0,47,0xFF70 },
+	{							/* no seed */
+	  0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+	  0x00,0xE0,0xD2,0xEE,0x25,0x09,0x52,0x06,0xF5,0xE2,	/* a */
+	  0xA4,0xF9,0xED,0x22,0x9F,0x1F,0x25,0x6E,0x79,0xA0,
+	  0xE2,0xB4,0x55,0x97,0x0D,0x8D,0x0D,0x86,0x5B,0xD9,
+	  0x47,0x78,0xC5,0x76,0xD6,0x2F,0x0A,0xB7,0x51,0x9C,
+	  0xCD,0x2A,0x1A,0x90,0x6A,0xE3,0x0D,
+	  0x00,0xFC,0x12,0x17,0xD4,0x32,0x0A,0x90,0x45,0x2C,	/* b */
+	  0x76,0x0A,0x58,0xED,0xCD,0x30,0xC8,0xDD,0x06,0x9B,
+	  0x3C,0x34,0x45,0x38,0x37,0xA3,0x4E,0xD5,0x0C,0xB5,
+	  0x49,0x17,0xE1,0xC2,0x11,0x2D,0x84,0xD1,0x64,0xF4,
+	  0x44,0xF8,0xF7,0x47,0x86,0x04,0x6A,
+	  0x00,0x10,0x85,0xE2,0x75,0x53,0x81,0xDC,0xCC,0xE3,	/* x */
+	  0xC1,0x55,0x7A,0xFA,0x10,0xC2,0xF0,0xC0,0xC2,0x82,
+	  0x56,0x46,0xC5,0xB3,0x4A,0x39,0x4C,0xBC,0xFA,0x8B,
+	  0xC1,0x6B,0x22,0xE7,0xE7,0x89,0xE9,0x27,0xBE,0x21,
+	  0x6F,0x02,0xE1,0xFB,0x13,0x6A,0x5F,
+	  0x00,0x7B,0x3E,0xB1,0xBD,0xDC,0xBA,0x62,0xD5,0xD8,	/* y */
+	  0xB2,0x05,0x9B,0x52,0x57,0x97,0xFC,0x73,0x82,0x2C,
+	  0x59,0x05,0x9C,0x62,0x3A,0x45,0xFF,0x38,0x43,0xCE,
+	  0xE8,0xF8,0x7C,0xD1,0x85,0x5A,0xDA,0xA8,0x1E,0x2A,
+	  0x07,0x50,0xB8,0x0F,0xDA,0x23,0x10,
+	  0x00,0x00,0x01,0x00,0x90,0x51,0x2D,0xA9,0xAF,0x72,	/* order */
+	  0xB0,0x83,0x49,0xD9,0x8A,0x5D,0xD4,0xC7,0xB0,0x53,
+	  0x2E,0xCA,0x51,0xCE,0x03,0xE2,0xD1,0x0F,0x3B,0x7A,
+	  0xC5,0x79,0xBD,0x87,0xE9,0x09,0xAE,0x40,0xA6,0xF1,
+	  0x31,0xE9,0xCF,0xCE,0x5B,0xD9,0x67 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[0+54*6]; }
+	_EC_X9_62_CHAR2_431R1 = {
+	{ NID_X9_62_characteristic_two_field,0,54,0x2760 },
+	{							/* no seed */
+	  0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x01,
+	  0x1A,0x82,0x7E,0xF0,0x0D,0xD6,0xFC,0x0E,0x23,0x4C,	/* a */
+	  0xAF,0x04,0x6C,0x6A,0x5D,0x8A,0x85,0x39,0x5B,0x23,
+	  0x6C,0xC4,0xAD,0x2C,0xF3,0x2A,0x0C,0xAD,0xBD,0xC9,
+	  0xDD,0xF6,0x20,0xB0,0xEB,0x99,0x06,0xD0,0x95,0x7F,
+	  0x6C,0x6F,0xEA,0xCD,0x61,0x54,0x68,0xDF,0x10,0x4D,
+	  0xE2,0x96,0xCD,0x8F,
+	  0x10,0xD9,0xB4,0xA3,0xD9,0x04,0x7D,0x8B,0x15,0x43,	/* b */
+	  0x59,0xAB,0xFB,0x1B,0x7F,0x54,0x85,0xB0,0x4C,0xEB,
+	  0x86,0x82,0x37,0xDD,0xC9,0xDE,0xDA,0x98,0x2A,0x67,
+	  0x9A,0x5A,0x91,0x9B,0x62,0x6D,0x4E,0x50,0xA8,0xDD,
+	  0x73,0x1B,0x10,0x7A,0x99,0x62,0x38,0x1F,0xB5,0xD8,
+	  0x07,0xBF,0x26,0x18,
+	  0x12,0x0F,0xC0,0x5D,0x3C,0x67,0xA9,0x9D,0xE1,0x61,	/* x */
+	  0xD2,0xF4,0x09,0x26,0x22,0xFE,0xCA,0x70,0x1B,0xE4,
+	  0xF5,0x0F,0x47,0x58,0x71,0x4E,0x8A,0x87,0xBB,0xF2,
+	  0xA6,0x58,0xEF,0x8C,0x21,0xE7,0xC5,0xEF,0xE9,0x65,
+	  0x36,0x1F,0x6C,0x29,0x99,0xC0,0xC2,0x47,0xB0,0xDB,
+	  0xD7,0x0C,0xE6,0xB7,
+	  0x20,0xD0,0xAF,0x89,0x03,0xA9,0x6F,0x8D,0x5F,0xA2,	/* y */
+	  0xC2,0x55,0x74,0x5D,0x3C,0x45,0x1B,0x30,0x2C,0x93,
+	  0x46,0xD9,0xB7,0xE4,0x85,0xE7,0xBC,0xE4,0x1F,0x6B,
+	  0x59,0x1F,0x3E,0x8F,0x6A,0xDD,0xCB,0xB0,0xBC,0x4C,
+	  0x2F,0x94,0x7A,0x7D,0xE1,0xA8,0x9B,0x62,0x5D,0x6A,
+	  0x59,0x8B,0x37,0x60,
+	  0x00,0x03,0x40,0x34,0x03,0x40,0x34,0x03,0x40,0x34,	/* order */
+	  0x03,0x40,0x34,0x03,0x40,0x34,0x03,0x40,0x34,0x03,
+	  0x40,0x34,0x03,0x40,0x34,0x03,0x40,0x34,0x03,0x23,
+	  0xC3,0x13,0xFA,0xB5,0x05,0x89,0x70,0x3B,0x5E,0xC6,
+	  0x8D,0x35,0x87,0xFE,0xC6,0x0D,0x16,0x1C,0xC1,0x49,
+	  0xC1,0xAD,0x4A,0x91 }
+	};
+
+static const struct { EC_CURVE_DATA h; unsigned char data[0+15*6]; }
+	_EC_WTLS_1 = {
+	{ NID_X9_62_characteristic_two_field,0,15,2 },
+	{							/* no seed */
+	  0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x02,0x01,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* a */
+	  0x00,0x00,0x00,0x00,0x01,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* b */
+	  0x00,0x00,0x00,0x00,0x01,
+	  0x01,0x66,0x79,0x79,0xA4,0x0B,0xA4,0x97,0xE5,0xD5,	/* x */
+	  0xC2,0x70,0x78,0x06,0x17,
+	  0x00,0xF4,0x4B,0x4A,0xF1,0xEC,0xC2,0x63,0x0E,0x08,	/* y */
+	  0x78,0x5C,0xEB,0xCC,0x15,
+	  0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xBF,	/* order */
+	  0x91,0xAF,0x6D,0xEA,0x73 }
+	};
+
+/* IPSec curves */
+/* NOTE: The of curves over a extension field of non prime degree
+ * is not recommended (Weil-descent).
+ * As the group order is not a prime this curve is not suitable
+ * for ECDSA.
+ */
+static const struct { EC_CURVE_DATA h; unsigned char data[0+20*6]; }
+	_EC_IPSEC_155_ID3 = {
+	{ NID_X9_62_characteristic_two_field,0,20,3 },
+	{							/* no seed */
+	  0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* a */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* b */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x33,0x8f,
+
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* x */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7b,
+
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* y */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xc8,
+
+	  0x02,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,	/* order */
+	  0xC7,0xF3,0xC7,0x88,0x1B,0xD0,0x86,0x8F,0xA8,0x6C }
+	};
+
+/* NOTE: The of curves over a extension field of non prime degree
+ * is not recommended (Weil-descent).
+ * As the group order is not a prime this curve is not suitable
+ * for ECDSA.
+ */
+static const struct { EC_CURVE_DATA h; unsigned char data[0+24*6]; }
+	_EC_IPSEC_185_ID4 = {
+	{ NID_X9_62_characteristic_two_field,0,24,2 },
+	{							/* no seed */
+	  0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* p */
+	  0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x01,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* a */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* b */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x1e,0xe9,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* x */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x18,
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,	/* y */
+	  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+	  0x00,0x00,0x00,0x0d,
+	  0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,	/* order */
+	  0xFF,0xFF,0xED,0xF9,0x7C,0x44,0xDB,0x9F,0x24,0x20,
+	  0xBA,0xFC,0xA7,0x5E }
+	};
+
+#endif
+
+typedef struct _ec_list_element_st {
+	int	nid;
+	const EC_CURVE_DATA *data;
+	const EC_METHOD *(*meth)(void);
+	const char *comment;
+	} ec_list_element;
+
+static const ec_list_element curve_list[] = {
+	/* prime field curves */
+	/* secg curves */
+	{ NID_secp112r1, &_EC_SECG_PRIME_112R1.h, 0, "SECG/WTLS curve over a 112 bit prime field" },
+	{ NID_secp112r2, &_EC_SECG_PRIME_112R2.h, 0, "SECG curve over a 112 bit prime field" },
+	{ NID_secp128r1, &_EC_SECG_PRIME_128R1.h, 0, "SECG curve over a 128 bit prime field" },
+	{ NID_secp128r2, &_EC_SECG_PRIME_128R2.h, 0, "SECG curve over a 128 bit prime field" },
+	{ NID_secp160k1, &_EC_SECG_PRIME_160K1.h, 0, "SECG curve over a 160 bit prime field" },
+	{ NID_secp160r1, &_EC_SECG_PRIME_160R1.h, 0, "SECG curve over a 160 bit prime field" },
+	{ NID_secp160r2, &_EC_SECG_PRIME_160R2.h, 0, "SECG/WTLS curve over a 160 bit prime field" },
+	/* SECG secp192r1 is the same as X9.62 prime192v1 and hence omitted */
+	{ NID_secp192k1, &_EC_SECG_PRIME_192K1.h, 0, "SECG curve over a 192 bit prime field" },
+	{ NID_secp224k1, &_EC_SECG_PRIME_224K1.h, 0, "SECG curve over a 224 bit prime field" },
+#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
+	{ NID_secp224r1, &_EC_NIST_PRIME_224.h, EC_GFp_nistp224_method, "NIST/SECG curve over a 224 bit prime field" },
+#else
+	{ NID_secp224r1, &_EC_NIST_PRIME_224.h, 0, "NIST/SECG curve over a 224 bit prime field" },
+#endif
+	{ NID_secp256k1, &_EC_SECG_PRIME_256K1.h, 0, "SECG curve over a 256 bit prime field" },
+	/* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */
+	{ NID_secp384r1, &_EC_NIST_PRIME_384.h, 0, "NIST/SECG curve over a 384 bit prime field" },
+#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
+	{ NID_secp521r1, &_EC_NIST_PRIME_521.h, EC_GFp_nistp521_method, "NIST/SECG curve over a 521 bit prime field" },
+#else
+	{ NID_secp521r1, &_EC_NIST_PRIME_521.h, 0, "NIST/SECG curve over a 521 bit prime field" },
+#endif
+	/* X9.62 curves */
+	{ NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0, "NIST/X9.62/SECG curve over a 192 bit prime field" },
+	{ NID_X9_62_prime192v2, &_EC_X9_62_PRIME_192V2.h, 0, "X9.62 curve over a 192 bit prime field" },
+	{ NID_X9_62_prime192v3, &_EC_X9_62_PRIME_192V3.h, 0, "X9.62 curve over a 192 bit prime field" },
+	{ NID_X9_62_prime239v1, &_EC_X9_62_PRIME_239V1.h, 0, "X9.62 curve over a 239 bit prime field" },
+	{ NID_X9_62_prime239v2, &_EC_X9_62_PRIME_239V2.h, 0, "X9.62 curve over a 239 bit prime field" },
+	{ NID_X9_62_prime239v3, &_EC_X9_62_PRIME_239V3.h, 0, "X9.62 curve over a 239 bit prime field" },
+#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
+	{ NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h, EC_GFp_nistp256_method, "X9.62/SECG curve over a 256 bit prime field" },
+#else
+	{ NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h, 0, "X9.62/SECG curve over a 256 bit prime field" },
+#endif
+#ifndef OPENSSL_NO_EC2M
+	/* characteristic two field curves */
+	/* NIST/SECG curves */
+	{ NID_sect113r1, &_EC_SECG_CHAR2_113R1.h, 0, "SECG curve over a 113 bit binary field" },
+	{ NID_sect113r2, &_EC_SECG_CHAR2_113R2.h, 0, "SECG curve over a 113 bit binary field" },
+	{ NID_sect131r1, &_EC_SECG_CHAR2_131R1.h, 0, "SECG/WTLS curve over a 131 bit binary field" },
+	{ NID_sect131r2, &_EC_SECG_CHAR2_131R2.h, 0, "SECG curve over a 131 bit binary field" },
+	{ NID_sect163k1, &_EC_NIST_CHAR2_163K.h, 0, "NIST/SECG/WTLS curve over a 163 bit binary field" },
+	{ NID_sect163r1, &_EC_SECG_CHAR2_163R1.h, 0, "SECG curve over a 163 bit binary field" },
+	{ NID_sect163r2, &_EC_NIST_CHAR2_163B.h, 0, "NIST/SECG curve over a 163 bit binary field" },
+	{ NID_sect193r1, &_EC_SECG_CHAR2_193R1.h, 0, "SECG curve over a 193 bit binary field" },
+	{ NID_sect193r2, &_EC_SECG_CHAR2_193R2.h, 0, "SECG curve over a 193 bit binary field" },
+	{ NID_sect233k1, &_EC_NIST_CHAR2_233K.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field" },
+	{ NID_sect233r1, &_EC_NIST_CHAR2_233B.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field" },
+	{ NID_sect239k1, &_EC_SECG_CHAR2_239K1.h, 0, "SECG curve over a 239 bit binary field" },
+	{ NID_sect283k1, &_EC_NIST_CHAR2_283K.h, 0, "NIST/SECG curve over a 283 bit binary field" },
+	{ NID_sect283r1, &_EC_NIST_CHAR2_283B.h, 0, "NIST/SECG curve over a 283 bit binary field" },
+	{ NID_sect409k1, &_EC_NIST_CHAR2_409K.h, 0, "NIST/SECG curve over a 409 bit binary field" },
+	{ NID_sect409r1, &_EC_NIST_CHAR2_409B.h, 0, "NIST/SECG curve over a 409 bit binary field" },
+	{ NID_sect571k1, &_EC_NIST_CHAR2_571K.h, 0, "NIST/SECG curve over a 571 bit binary field" },
+	{ NID_sect571r1, &_EC_NIST_CHAR2_571B.h, 0, "NIST/SECG curve over a 571 bit binary field" },
+	/* X9.62 curves */
+	{ NID_X9_62_c2pnb163v1, &_EC_X9_62_CHAR2_163V1.h, 0, "X9.62 curve over a 163 bit binary field" },
+	{ NID_X9_62_c2pnb163v2, &_EC_X9_62_CHAR2_163V2.h, 0, "X9.62 curve over a 163 bit binary field" },
+	{ NID_X9_62_c2pnb163v3, &_EC_X9_62_CHAR2_163V3.h, 0, "X9.62 curve over a 163 bit binary field" },
+	{ NID_X9_62_c2pnb176v1, &_EC_X9_62_CHAR2_176V1.h, 0, "X9.62 curve over a 176 bit binary field" },
+	{ NID_X9_62_c2tnb191v1, &_EC_X9_62_CHAR2_191V1.h, 0, "X9.62 curve over a 191 bit binary field" },
+	{ NID_X9_62_c2tnb191v2, &_EC_X9_62_CHAR2_191V2.h, 0, "X9.62 curve over a 191 bit binary field" },
+	{ NID_X9_62_c2tnb191v3, &_EC_X9_62_CHAR2_191V3.h, 0, "X9.62 curve over a 191 bit binary field" },
+	{ NID_X9_62_c2pnb208w1, &_EC_X9_62_CHAR2_208W1.h, 0, "X9.62 curve over a 208 bit binary field" },
+	{ NID_X9_62_c2tnb239v1, &_EC_X9_62_CHAR2_239V1.h, 0, "X9.62 curve over a 239 bit binary field" },
+	{ NID_X9_62_c2tnb239v2, &_EC_X9_62_CHAR2_239V2.h, 0, "X9.62 curve over a 239 bit binary field" },
+	{ NID_X9_62_c2tnb239v3, &_EC_X9_62_CHAR2_239V3.h, 0, "X9.62 curve over a 239 bit binary field" },
+	{ NID_X9_62_c2pnb272w1, &_EC_X9_62_CHAR2_272W1.h, 0, "X9.62 curve over a 272 bit binary field" },
+	{ NID_X9_62_c2pnb304w1, &_EC_X9_62_CHAR2_304W1.h, 0, "X9.62 curve over a 304 bit binary field" },
+	{ NID_X9_62_c2tnb359v1, &_EC_X9_62_CHAR2_359V1.h, 0, "X9.62 curve over a 359 bit binary field" },
+	{ NID_X9_62_c2pnb368w1, &_EC_X9_62_CHAR2_368W1.h, 0, "X9.62 curve over a 368 bit binary field" },
+	{ NID_X9_62_c2tnb431r1, &_EC_X9_62_CHAR2_431R1.h, 0, "X9.62 curve over a 431 bit binary field" },
+	/* the WAP/WTLS curves
+	 * [unlike SECG, spec has its own OIDs for curves from X9.62] */
+	{ NID_wap_wsg_idm_ecid_wtls1, &_EC_WTLS_1.h, 0, "WTLS curve over a 113 bit binary field" },
+	{ NID_wap_wsg_idm_ecid_wtls3, &_EC_NIST_CHAR2_163K.h, 0, "NIST/SECG/WTLS curve over a 163 bit binary field" },
+	{ NID_wap_wsg_idm_ecid_wtls4, &_EC_SECG_CHAR2_113R1.h, 0, "SECG curve over a 113 bit binary field" },
+	{ NID_wap_wsg_idm_ecid_wtls5, &_EC_X9_62_CHAR2_163V1.h, 0, "X9.62 curve over a 163 bit binary field" },
+#endif
+	{ NID_wap_wsg_idm_ecid_wtls6, &_EC_SECG_PRIME_112R1.h, 0, "SECG/WTLS curve over a 112 bit prime field" },
+	{ NID_wap_wsg_idm_ecid_wtls7, &_EC_SECG_PRIME_160R2.h, 0, "SECG/WTLS curve over a 160 bit prime field" },
+	{ NID_wap_wsg_idm_ecid_wtls8, &_EC_WTLS_8.h, 0, "WTLS curve over a 112 bit prime field" },
+	{ NID_wap_wsg_idm_ecid_wtls9, &_EC_WTLS_9.h, 0, "WTLS curve over a 160 bit prime field" },
+#ifndef OPENSSL_NO_EC2M
+	{ NID_wap_wsg_idm_ecid_wtls10, &_EC_NIST_CHAR2_233K.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field" },
+	{ NID_wap_wsg_idm_ecid_wtls11, &_EC_NIST_CHAR2_233B.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field" },
+#endif
+	{ NID_wap_wsg_idm_ecid_wtls12, &_EC_WTLS_12.h, 0, "WTLS curvs over a 224 bit prime field" },
+#ifndef OPENSSL_NO_EC2M
+	/* IPSec curves */
+	{ NID_ipsec3, &_EC_IPSEC_155_ID3.h, 0, "\n\tIPSec/IKE/Oakley curve #3 over a 155 bit binary field.\n"
+	  "\tNot suitable for ECDSA.\n\tQuestionable extension field!" },
+	{ NID_ipsec4, &_EC_IPSEC_185_ID4.h, 0, "\n\tIPSec/IKE/Oakley curve #4 over a 185 bit binary field.\n"
+	  "\tNot suitable for ECDSA.\n\tQuestionable extension field!" },
+#endif
+};
+
+#define curve_list_length (sizeof(curve_list)/sizeof(ec_list_element))
+
+static EC_GROUP *ec_group_new_from_data(const ec_list_element curve)
+	{
+	EC_GROUP *group=NULL;
+	EC_POINT *P=NULL;
+	BN_CTX	 *ctx=NULL;
+	BIGNUM	 *p=NULL, *a=NULL, *b=NULL, *x=NULL, *y=NULL, *order=NULL;
+	int	 ok=0;
+	int	 seed_len,param_len;
+	const EC_METHOD *meth;
+	const EC_CURVE_DATA *data;
+	const unsigned char *params;
+
+	if ((ctx = BN_CTX_new()) == NULL)
+		{
+		ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+
+	data = curve.data;
+	seed_len  = data->seed_len;
+	param_len = data->param_len;
+	params	  = (const unsigned char *)(data+1);	/* skip header */
+	params	 += seed_len;				/* skip seed   */
+
+	if (!(p = BN_bin2bn(params+0*param_len, param_len, NULL))
+		|| !(a = BN_bin2bn(params+1*param_len, param_len, NULL))
+		|| !(b = BN_bin2bn(params+2*param_len, param_len, NULL)))
+		{
+		ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB);
+		goto err;
+		}
+
+	if (curve.meth != 0)
+		{
+		meth = curve.meth();
+		if (((group = EC_GROUP_new(meth)) == NULL) ||
+			(!(group->meth->group_set_curve(group, p, a, b, ctx))))
+			{
+			ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
+			goto err;
+			}
+		}
+	else if (data->field_type == NID_X9_62_prime_field)
+		{
+		if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL)
+			{
+			ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
+			goto err;
+			}
+		}
+#ifndef OPENSSL_NO_EC2M
+	else	/* field_type == NID_X9_62_characteristic_two_field */
+		{
+		if ((group = EC_GROUP_new_curve_GF2m(p, a, b, ctx)) == NULL)
+			{
+			ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
+			goto err;
+			}
+		}
+#endif
+
+	if ((P = EC_POINT_new(group)) == NULL)
+		{
+		ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
+		goto err;
+		}
+
+	if (!(x = BN_bin2bn(params+3*param_len, param_len, NULL))
+		|| !(y = BN_bin2bn(params+4*param_len, param_len, NULL)))
+		{
+		ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB);
+		goto err;
+		}
+	if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx))
+		{
+		ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
+		goto err;
+		}
+	if (!(order = BN_bin2bn(params+5*param_len, param_len, NULL))
+		|| !BN_set_word(x, (BN_ULONG)data->cofactor))
+		{
+		ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB);
+		goto err;
+		}
+	if (!EC_GROUP_set_generator(group, P, order, x))
+		{
+		ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
+		goto err;
+		}
+	if (seed_len)
+		{
+		if (!EC_GROUP_set_seed(group, params-seed_len, seed_len))
+			{
+			ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
+			goto err;
+			}
+		}
+	ok=1;
+err:
+	if (!ok)
+		{
+		EC_GROUP_free(group);
+		group = NULL;
+		}
+	if (P)
+		EC_POINT_free(P);
+	if (ctx)
+		BN_CTX_free(ctx);
+	if (p)
+		BN_free(p);
+	if (a)
+		BN_free(a);
+	if (b)
+		BN_free(b);
+	if (order)
+		BN_free(order);
+	if (x)
+		BN_free(x);
+	if (y)
+		BN_free(y);
+	return group;
+	}
+
+EC_GROUP *EC_GROUP_new_by_curve_name(int nid)
+	{
+	size_t i;
+	EC_GROUP *ret = NULL;
+
+	if (nid <= 0)
+		return NULL;
+
+	for (i=0; i<curve_list_length; i++)
+		if (curve_list[i].nid == nid)
+			{
+			ret = ec_group_new_from_data(curve_list[i]);
+			break;
+			}
+
+	if (ret == NULL)
+		{
+		ECerr(EC_F_EC_GROUP_NEW_BY_CURVE_NAME, EC_R_UNKNOWN_GROUP);
+		return NULL;
+		}
+
+	EC_GROUP_set_curve_name(ret, nid);
+
+	return ret;
+	}
+
+size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems)
+	{
+	size_t	i, min;
+
+	if (r == NULL || nitems == 0)
+		return curve_list_length;
+
+	min = nitems < curve_list_length ? nitems : curve_list_length;
+
+	for (i = 0; i < min; i++)
+		{
+		r[i].nid = curve_list[i].nid;
+		r[i].comment = curve_list[i].comment;
+		}
+
+	return curve_list_length;
+	}
diff --git a/jni/openssl/crypto/ec/ec_cvt.c b/jni/openssl/crypto/ec/ec_cvt.c
new file mode 100644
index 0000000..bfcbab3
--- /dev/null
+++ b/jni/openssl/crypto/ec/ec_cvt.c
@@ -0,0 +1,170 @@
+/* crypto/ec/ec_cvt.c */
+/*
+ * Originally written by Bodo Moeller for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2002 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 of the attached software ("Contribution") are developed by 
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * The elliptic curve binary polynomial software is originally written by
+ * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
+ *
+ */
+
+#include <openssl/err.h>
+#include "ec_lcl.h"
+
+
+EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
+	{
+	const EC_METHOD *meth;
+	EC_GROUP *ret;
+
+#if defined(OPENSSL_BN_ASM_MONT)
+	/*
+	 * This might appear controversial, but the fact is that generic
+	 * prime method was observed to deliver better performance even
+	 * for NIST primes on a range of platforms, e.g.: 60%-15%
+	 * improvement on IA-64, ~25% on ARM, 30%-90% on P4, 20%-25%
+	 * in 32-bit build and 35%--12% in 64-bit build on Core2...
+	 * Coefficients are relative to optimized bn_nist.c for most
+	 * intensive ECDSA verify and ECDH operations for 192- and 521-
+	 * bit keys respectively. Choice of these boundary values is
+	 * arguable, because the dependency of improvement coefficient
+	 * from key length is not a "monotone" curve. For example while
+	 * 571-bit result is 23% on ARM, 384-bit one is -1%. But it's
+	 * generally faster, sometimes "respectfully" faster, sometimes
+	 * "tolerably" slower... What effectively happens is that loop
+	 * with bn_mul_add_words is put against bn_mul_mont, and the
+	 * latter "wins" on short vectors. Correct solution should be
+	 * implementing dedicated NxN multiplication subroutines for
+	 * small N. But till it materializes, let's stick to generic
+	 * prime method...
+	 *						<appro>
+	 */
+	meth = EC_GFp_mont_method();
+#else
+	meth = EC_GFp_nist_method();
+#endif
+	
+	ret = EC_GROUP_new(meth);
+	if (ret == NULL)
+		return NULL;
+
+	if (!EC_GROUP_set_curve_GFp(ret, p, a, b, ctx))
+		{
+		unsigned long err;
+		  
+		err = ERR_peek_last_error();
+
+		if (!(ERR_GET_LIB(err) == ERR_LIB_EC &&
+			((ERR_GET_REASON(err) == EC_R_NOT_A_NIST_PRIME) ||
+			 (ERR_GET_REASON(err) == EC_R_NOT_A_SUPPORTED_NIST_PRIME))))
+			{
+			/* real error */
+			
+			EC_GROUP_clear_free(ret);
+			return NULL;
+			}
+			
+		
+		/* not an actual error, we just cannot use EC_GFp_nist_method */
+
+		ERR_clear_error();
+
+		EC_GROUP_clear_free(ret);
+		meth = EC_GFp_mont_method();
+
+		ret = EC_GROUP_new(meth);
+		if (ret == NULL)
+			return NULL;
+
+		if (!EC_GROUP_set_curve_GFp(ret, p, a, b, ctx))
+			{
+			EC_GROUP_clear_free(ret);
+			return NULL;
+			}
+		}
+
+	return ret;
+	}
+
+#ifndef OPENSSL_NO_EC2M
+EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
+	{
+	const EC_METHOD *meth;
+	EC_GROUP *ret;
+	
+	meth = EC_GF2m_simple_method();
+	
+	ret = EC_GROUP_new(meth);
+	if (ret == NULL)
+		return NULL;
+
+	if (!EC_GROUP_set_curve_GF2m(ret, p, a, b, ctx))
+		{
+		EC_GROUP_clear_free(ret);
+		return NULL;
+		}
+
+	return ret;
+	}
+#endif
diff --git a/jni/openssl/crypto/ec/ec_err.c b/jni/openssl/crypto/ec/ec_err.c
new file mode 100644
index 0000000..0d19398
--- /dev/null
+++ b/jni/openssl/crypto/ec/ec_err.c
@@ -0,0 +1,276 @@
+/* crypto/ec/ec_err.c */
+/* ====================================================================
+ * Copyright (c) 1999-2011 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).
+ *
+ */
+
+/* NOTE: this file was auto generated by the mkerr.pl script: any changes
+ * made to it will be overwritten when the script next updates this file,
+ * only reason strings will be preserved.
+ */
+
+#include <stdio.h>
+#include <openssl/err.h>
+#include <openssl/ec.h>
+
+/* BEGIN ERROR CODES */
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_EC,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_EC,0,reason)
+
+static ERR_STRING_DATA EC_str_functs[]=
+	{
+{ERR_FUNC(EC_F_BN_TO_FELEM),	"BN_TO_FELEM"},
+{ERR_FUNC(EC_F_COMPUTE_WNAF),	"COMPUTE_WNAF"},
+{ERR_FUNC(EC_F_D2I_ECPARAMETERS),	"d2i_ECParameters"},
+{ERR_FUNC(EC_F_D2I_ECPKPARAMETERS),	"d2i_ECPKParameters"},
+{ERR_FUNC(EC_F_D2I_ECPRIVATEKEY),	"d2i_ECPrivateKey"},
+{ERR_FUNC(EC_F_DO_EC_KEY_PRINT),	"DO_EC_KEY_PRINT"},
+{ERR_FUNC(EC_F_ECKEY_PARAM2TYPE),	"ECKEY_PARAM2TYPE"},
+{ERR_FUNC(EC_F_ECKEY_PARAM_DECODE),	"ECKEY_PARAM_DECODE"},
+{ERR_FUNC(EC_F_ECKEY_PRIV_DECODE),	"ECKEY_PRIV_DECODE"},
+{ERR_FUNC(EC_F_ECKEY_PRIV_ENCODE),	"ECKEY_PRIV_ENCODE"},
+{ERR_FUNC(EC_F_ECKEY_PUB_DECODE),	"ECKEY_PUB_DECODE"},
+{ERR_FUNC(EC_F_ECKEY_PUB_ENCODE),	"ECKEY_PUB_ENCODE"},
+{ERR_FUNC(EC_F_ECKEY_TYPE2PARAM),	"ECKEY_TYPE2PARAM"},
+{ERR_FUNC(EC_F_ECPARAMETERS_PRINT),	"ECParameters_print"},
+{ERR_FUNC(EC_F_ECPARAMETERS_PRINT_FP),	"ECParameters_print_fp"},
+{ERR_FUNC(EC_F_ECPKPARAMETERS_PRINT),	"ECPKParameters_print"},
+{ERR_FUNC(EC_F_ECPKPARAMETERS_PRINT_FP),	"ECPKParameters_print_fp"},
+{ERR_FUNC(EC_F_ECP_NIST_MOD_192),	"ECP_NIST_MOD_192"},
+{ERR_FUNC(EC_F_ECP_NIST_MOD_224),	"ECP_NIST_MOD_224"},
+{ERR_FUNC(EC_F_ECP_NIST_MOD_256),	"ECP_NIST_MOD_256"},
+{ERR_FUNC(EC_F_ECP_NIST_MOD_521),	"ECP_NIST_MOD_521"},
+{ERR_FUNC(EC_F_EC_ASN1_GROUP2CURVE),	"EC_ASN1_GROUP2CURVE"},
+{ERR_FUNC(EC_F_EC_ASN1_GROUP2FIELDID),	"EC_ASN1_GROUP2FIELDID"},
+{ERR_FUNC(EC_F_EC_ASN1_GROUP2PARAMETERS),	"EC_ASN1_GROUP2PARAMETERS"},
+{ERR_FUNC(EC_F_EC_ASN1_GROUP2PKPARAMETERS),	"EC_ASN1_GROUP2PKPARAMETERS"},
+{ERR_FUNC(EC_F_EC_ASN1_PARAMETERS2GROUP),	"EC_ASN1_PARAMETERS2GROUP"},
+{ERR_FUNC(EC_F_EC_ASN1_PKPARAMETERS2GROUP),	"EC_ASN1_PKPARAMETERS2GROUP"},
+{ERR_FUNC(EC_F_EC_EX_DATA_SET_DATA),	"EC_EX_DATA_set_data"},
+{ERR_FUNC(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY),	"EC_GF2M_MONTGOMERY_POINT_MULTIPLY"},
+{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT),	"ec_GF2m_simple_group_check_discriminant"},
+{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE),	"ec_GF2m_simple_group_set_curve"},
+{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_OCT2POINT),	"ec_GF2m_simple_oct2point"},
+{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_POINT2OCT),	"ec_GF2m_simple_point2oct"},
+{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES),	"ec_GF2m_simple_point_get_affine_coordinates"},
+{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES),	"ec_GF2m_simple_point_set_affine_coordinates"},
+{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES),	"ec_GF2m_simple_set_compressed_coordinates"},
+{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_DECODE),	"ec_GFp_mont_field_decode"},
+{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_ENCODE),	"ec_GFp_mont_field_encode"},
+{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_MUL),	"ec_GFp_mont_field_mul"},
+{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE),	"ec_GFp_mont_field_set_to_one"},
+{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_SQR),	"ec_GFp_mont_field_sqr"},
+{ERR_FUNC(EC_F_EC_GFP_MONT_GROUP_SET_CURVE),	"ec_GFp_mont_group_set_curve"},
+{ERR_FUNC(EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP),	"EC_GFP_MONT_GROUP_SET_CURVE_GFP"},
+{ERR_FUNC(EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE),	"ec_GFp_nistp224_group_set_curve"},
+{ERR_FUNC(EC_F_EC_GFP_NISTP224_POINTS_MUL),	"ec_GFp_nistp224_points_mul"},
+{ERR_FUNC(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES),	"ec_GFp_nistp224_point_get_affine_coordinates"},
+{ERR_FUNC(EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE),	"ec_GFp_nistp256_group_set_curve"},
+{ERR_FUNC(EC_F_EC_GFP_NISTP256_POINTS_MUL),	"ec_GFp_nistp256_points_mul"},
+{ERR_FUNC(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES),	"ec_GFp_nistp256_point_get_affine_coordinates"},
+{ERR_FUNC(EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE),	"ec_GFp_nistp521_group_set_curve"},
+{ERR_FUNC(EC_F_EC_GFP_NISTP521_POINTS_MUL),	"ec_GFp_nistp521_points_mul"},
+{ERR_FUNC(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES),	"ec_GFp_nistp521_point_get_affine_coordinates"},
+{ERR_FUNC(EC_F_EC_GFP_NIST_FIELD_MUL),	"ec_GFp_nist_field_mul"},
+{ERR_FUNC(EC_F_EC_GFP_NIST_FIELD_SQR),	"ec_GFp_nist_field_sqr"},
+{ERR_FUNC(EC_F_EC_GFP_NIST_GROUP_SET_CURVE),	"ec_GFp_nist_group_set_curve"},
+{ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT),	"ec_GFp_simple_group_check_discriminant"},
+{ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE),	"ec_GFp_simple_group_set_curve"},
+{ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP),	"EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP"},
+{ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR),	"EC_GFP_SIMPLE_GROUP_SET_GENERATOR"},
+{ERR_FUNC(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE),	"ec_GFp_simple_make_affine"},
+{ERR_FUNC(EC_F_EC_GFP_SIMPLE_OCT2POINT),	"ec_GFp_simple_oct2point"},
+{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT2OCT),	"ec_GFp_simple_point2oct"},
+{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE),	"ec_GFp_simple_points_make_affine"},
+{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES),	"ec_GFp_simple_point_get_affine_coordinates"},
+{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP),	"EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP"},
+{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES),	"ec_GFp_simple_point_set_affine_coordinates"},
+{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP),	"EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP"},
+{ERR_FUNC(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES),	"ec_GFp_simple_set_compressed_coordinates"},
+{ERR_FUNC(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP),	"EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP"},
+{ERR_FUNC(EC_F_EC_GROUP_CHECK),	"EC_GROUP_check"},
+{ERR_FUNC(EC_F_EC_GROUP_CHECK_DISCRIMINANT),	"EC_GROUP_check_discriminant"},
+{ERR_FUNC(EC_F_EC_GROUP_COPY),	"EC_GROUP_copy"},
+{ERR_FUNC(EC_F_EC_GROUP_GET0_GENERATOR),	"EC_GROUP_get0_generator"},
+{ERR_FUNC(EC_F_EC_GROUP_GET_COFACTOR),	"EC_GROUP_get_cofactor"},
+{ERR_FUNC(EC_F_EC_GROUP_GET_CURVE_GF2M),	"EC_GROUP_get_curve_GF2m"},
+{ERR_FUNC(EC_F_EC_GROUP_GET_CURVE_GFP),	"EC_GROUP_get_curve_GFp"},
+{ERR_FUNC(EC_F_EC_GROUP_GET_DEGREE),	"EC_GROUP_get_degree"},
+{ERR_FUNC(EC_F_EC_GROUP_GET_ORDER),	"EC_GROUP_get_order"},
+{ERR_FUNC(EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS),	"EC_GROUP_get_pentanomial_basis"},
+{ERR_FUNC(EC_F_EC_GROUP_GET_TRINOMIAL_BASIS),	"EC_GROUP_get_trinomial_basis"},
+{ERR_FUNC(EC_F_EC_GROUP_NEW),	"EC_GROUP_new"},
+{ERR_FUNC(EC_F_EC_GROUP_NEW_BY_CURVE_NAME),	"EC_GROUP_new_by_curve_name"},
+{ERR_FUNC(EC_F_EC_GROUP_NEW_FROM_DATA),	"EC_GROUP_NEW_FROM_DATA"},
+{ERR_FUNC(EC_F_EC_GROUP_PRECOMPUTE_MULT),	"EC_GROUP_precompute_mult"},
+{ERR_FUNC(EC_F_EC_GROUP_SET_CURVE_GF2M),	"EC_GROUP_set_curve_GF2m"},
+{ERR_FUNC(EC_F_EC_GROUP_SET_CURVE_GFP),	"EC_GROUP_set_curve_GFp"},
+{ERR_FUNC(EC_F_EC_GROUP_SET_EXTRA_DATA),	"EC_GROUP_SET_EXTRA_DATA"},
+{ERR_FUNC(EC_F_EC_GROUP_SET_GENERATOR),	"EC_GROUP_set_generator"},
+{ERR_FUNC(EC_F_EC_KEY_CHECK_KEY),	"EC_KEY_check_key"},
+{ERR_FUNC(EC_F_EC_KEY_COPY),	"EC_KEY_copy"},
+{ERR_FUNC(EC_F_EC_KEY_GENERATE_KEY),	"EC_KEY_generate_key"},
+{ERR_FUNC(EC_F_EC_KEY_NEW),	"EC_KEY_new"},
+{ERR_FUNC(EC_F_EC_KEY_PRINT),	"EC_KEY_print"},
+{ERR_FUNC(EC_F_EC_KEY_PRINT_FP),	"EC_KEY_print_fp"},
+{ERR_FUNC(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES),	"EC_KEY_set_public_key_affine_coordinates"},
+{ERR_FUNC(EC_F_EC_POINTS_MAKE_AFFINE),	"EC_POINTs_make_affine"},
+{ERR_FUNC(EC_F_EC_POINT_ADD),	"EC_POINT_add"},
+{ERR_FUNC(EC_F_EC_POINT_CMP),	"EC_POINT_cmp"},
+{ERR_FUNC(EC_F_EC_POINT_COPY),	"EC_POINT_copy"},
+{ERR_FUNC(EC_F_EC_POINT_DBL),	"EC_POINT_dbl"},
+{ERR_FUNC(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M),	"EC_POINT_get_affine_coordinates_GF2m"},
+{ERR_FUNC(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP),	"EC_POINT_get_affine_coordinates_GFp"},
+{ERR_FUNC(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP),	"EC_POINT_get_Jprojective_coordinates_GFp"},
+{ERR_FUNC(EC_F_EC_POINT_INVERT),	"EC_POINT_invert"},
+{ERR_FUNC(EC_F_EC_POINT_IS_AT_INFINITY),	"EC_POINT_is_at_infinity"},
+{ERR_FUNC(EC_F_EC_POINT_IS_ON_CURVE),	"EC_POINT_is_on_curve"},
+{ERR_FUNC(EC_F_EC_POINT_MAKE_AFFINE),	"EC_POINT_make_affine"},
+{ERR_FUNC(EC_F_EC_POINT_MUL),	"EC_POINT_mul"},
+{ERR_FUNC(EC_F_EC_POINT_NEW),	"EC_POINT_new"},
+{ERR_FUNC(EC_F_EC_POINT_OCT2POINT),	"EC_POINT_oct2point"},
+{ERR_FUNC(EC_F_EC_POINT_POINT2OCT),	"EC_POINT_point2oct"},
+{ERR_FUNC(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M),	"EC_POINT_set_affine_coordinates_GF2m"},
+{ERR_FUNC(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP),	"EC_POINT_set_affine_coordinates_GFp"},
+{ERR_FUNC(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M),	"EC_POINT_set_compressed_coordinates_GF2m"},
+{ERR_FUNC(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP),	"EC_POINT_set_compressed_coordinates_GFp"},
+{ERR_FUNC(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP),	"EC_POINT_set_Jprojective_coordinates_GFp"},
+{ERR_FUNC(EC_F_EC_POINT_SET_TO_INFINITY),	"EC_POINT_set_to_infinity"},
+{ERR_FUNC(EC_F_EC_PRE_COMP_DUP),	"EC_PRE_COMP_DUP"},
+{ERR_FUNC(EC_F_EC_PRE_COMP_NEW),	"EC_PRE_COMP_NEW"},
+{ERR_FUNC(EC_F_EC_WNAF_MUL),	"ec_wNAF_mul"},
+{ERR_FUNC(EC_F_EC_WNAF_PRECOMPUTE_MULT),	"ec_wNAF_precompute_mult"},
+{ERR_FUNC(EC_F_I2D_ECPARAMETERS),	"i2d_ECParameters"},
+{ERR_FUNC(EC_F_I2D_ECPKPARAMETERS),	"i2d_ECPKParameters"},
+{ERR_FUNC(EC_F_I2D_ECPRIVATEKEY),	"i2d_ECPrivateKey"},
+{ERR_FUNC(EC_F_I2O_ECPUBLICKEY),	"i2o_ECPublicKey"},
+{ERR_FUNC(EC_F_NISTP224_PRE_COMP_NEW),	"NISTP224_PRE_COMP_NEW"},
+{ERR_FUNC(EC_F_NISTP256_PRE_COMP_NEW),	"NISTP256_PRE_COMP_NEW"},
+{ERR_FUNC(EC_F_NISTP521_PRE_COMP_NEW),	"NISTP521_PRE_COMP_NEW"},
+{ERR_FUNC(EC_F_O2I_ECPUBLICKEY),	"o2i_ECPublicKey"},
+{ERR_FUNC(EC_F_OLD_EC_PRIV_DECODE),	"OLD_EC_PRIV_DECODE"},
+{ERR_FUNC(EC_F_PKEY_EC_CTRL),	"PKEY_EC_CTRL"},
+{ERR_FUNC(EC_F_PKEY_EC_CTRL_STR),	"PKEY_EC_CTRL_STR"},
+{ERR_FUNC(EC_F_PKEY_EC_DERIVE),	"PKEY_EC_DERIVE"},
+{ERR_FUNC(EC_F_PKEY_EC_KEYGEN),	"PKEY_EC_KEYGEN"},
+{ERR_FUNC(EC_F_PKEY_EC_PARAMGEN),	"PKEY_EC_PARAMGEN"},
+{ERR_FUNC(EC_F_PKEY_EC_SIGN),	"PKEY_EC_SIGN"},
+{0,NULL}
+	};
+
+static ERR_STRING_DATA EC_str_reasons[]=
+	{
+{ERR_REASON(EC_R_ASN1_ERROR)             ,"asn1 error"},
+{ERR_REASON(EC_R_ASN1_UNKNOWN_FIELD)     ,"asn1 unknown field"},
+{ERR_REASON(EC_R_BIGNUM_OUT_OF_RANGE)    ,"bignum out of range"},
+{ERR_REASON(EC_R_BUFFER_TOO_SMALL)       ,"buffer too small"},
+{ERR_REASON(EC_R_COORDINATES_OUT_OF_RANGE),"coordinates out of range"},
+{ERR_REASON(EC_R_D2I_ECPKPARAMETERS_FAILURE),"d2i ecpkparameters failure"},
+{ERR_REASON(EC_R_DECODE_ERROR)           ,"decode error"},
+{ERR_REASON(EC_R_DISCRIMINANT_IS_ZERO)   ,"discriminant is zero"},
+{ERR_REASON(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE),"ec group new by name failure"},
+{ERR_REASON(EC_R_FIELD_TOO_LARGE)        ,"field too large"},
+{ERR_REASON(EC_R_GF2M_NOT_SUPPORTED)     ,"gf2m not supported"},
+{ERR_REASON(EC_R_GROUP2PKPARAMETERS_FAILURE),"group2pkparameters failure"},
+{ERR_REASON(EC_R_I2D_ECPKPARAMETERS_FAILURE),"i2d ecpkparameters failure"},
+{ERR_REASON(EC_R_INCOMPATIBLE_OBJECTS)   ,"incompatible objects"},
+{ERR_REASON(EC_R_INVALID_ARGUMENT)       ,"invalid argument"},
+{ERR_REASON(EC_R_INVALID_COMPRESSED_POINT),"invalid compressed point"},
+{ERR_REASON(EC_R_INVALID_COMPRESSION_BIT),"invalid compression bit"},
+{ERR_REASON(EC_R_INVALID_CURVE)          ,"invalid curve"},
+{ERR_REASON(EC_R_INVALID_DIGEST_TYPE)    ,"invalid digest type"},
+{ERR_REASON(EC_R_INVALID_ENCODING)       ,"invalid encoding"},
+{ERR_REASON(EC_R_INVALID_FIELD)          ,"invalid field"},
+{ERR_REASON(EC_R_INVALID_FORM)           ,"invalid form"},
+{ERR_REASON(EC_R_INVALID_GROUP_ORDER)    ,"invalid group order"},
+{ERR_REASON(EC_R_INVALID_PENTANOMIAL_BASIS),"invalid pentanomial basis"},
+{ERR_REASON(EC_R_INVALID_PRIVATE_KEY)    ,"invalid private key"},
+{ERR_REASON(EC_R_INVALID_TRINOMIAL_BASIS),"invalid trinomial basis"},
+{ERR_REASON(EC_R_KEYS_NOT_SET)           ,"keys not set"},
+{ERR_REASON(EC_R_MISSING_PARAMETERS)     ,"missing parameters"},
+{ERR_REASON(EC_R_MISSING_PRIVATE_KEY)    ,"missing private key"},
+{ERR_REASON(EC_R_NOT_A_NIST_PRIME)       ,"not a NIST prime"},
+{ERR_REASON(EC_R_NOT_A_SUPPORTED_NIST_PRIME),"not a supported NIST prime"},
+{ERR_REASON(EC_R_NOT_IMPLEMENTED)        ,"not implemented"},
+{ERR_REASON(EC_R_NOT_INITIALIZED)        ,"not initialized"},
+{ERR_REASON(EC_R_NO_FIELD_MOD)           ,"no field mod"},
+{ERR_REASON(EC_R_NO_PARAMETERS_SET)      ,"no parameters set"},
+{ERR_REASON(EC_R_PASSED_NULL_PARAMETER)  ,"passed null parameter"},
+{ERR_REASON(EC_R_PKPARAMETERS2GROUP_FAILURE),"pkparameters2group failure"},
+{ERR_REASON(EC_R_POINT_AT_INFINITY)      ,"point at infinity"},
+{ERR_REASON(EC_R_POINT_IS_NOT_ON_CURVE)  ,"point is not on curve"},
+{ERR_REASON(EC_R_SLOT_FULL)              ,"slot full"},
+{ERR_REASON(EC_R_UNDEFINED_GENERATOR)    ,"undefined generator"},
+{ERR_REASON(EC_R_UNDEFINED_ORDER)        ,"undefined order"},
+{ERR_REASON(EC_R_UNKNOWN_GROUP)          ,"unknown group"},
+{ERR_REASON(EC_R_UNKNOWN_ORDER)          ,"unknown order"},
+{ERR_REASON(EC_R_UNSUPPORTED_FIELD)      ,"unsupported field"},
+{ERR_REASON(EC_R_WRONG_CURVE_PARAMETERS) ,"wrong curve parameters"},
+{ERR_REASON(EC_R_WRONG_ORDER)            ,"wrong order"},
+{0,NULL}
+	};
+
+#endif
+
+void ERR_load_EC_strings(void)
+	{
+#ifndef OPENSSL_NO_ERR
+
+	if (ERR_func_error_string(EC_str_functs[0].error) == NULL)
+		{
+		ERR_load_strings(0,EC_str_functs);
+		ERR_load_strings(0,EC_str_reasons);
+		}
+#endif
+	}
diff --git a/jni/openssl/crypto/ec/ec_key.c b/jni/openssl/crypto/ec/ec_key.c
new file mode 100644
index 0000000..bf9fd2d
--- /dev/null
+++ b/jni/openssl/crypto/ec/ec_key.c
@@ -0,0 +1,563 @@
+/* crypto/ec/ec_key.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 <string.h>
+#include "ec_lcl.h"
+#include <openssl/err.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
+EC_KEY *EC_KEY_new(void)
+	{
+	EC_KEY *ret;
+
+	ret=(EC_KEY *)OPENSSL_malloc(sizeof(EC_KEY));
+	if (ret == NULL)
+		{
+		ECerr(EC_F_EC_KEY_NEW, 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);
+	}
+
+EC_KEY *EC_KEY_new_by_curve_name(int nid)
+	{
+	EC_KEY *ret = EC_KEY_new();
+	if (ret == NULL)
+		return NULL;
+	ret->group = EC_GROUP_new_by_curve_name(nid);
+	if (ret->group == NULL)
+		{
+		EC_KEY_free(ret);
+		return NULL;
+		}
+	return ret;
+	}
+
+void EC_KEY_free(EC_KEY *r)
+	{
+	int i;
+
+	if (r == NULL) return;
+
+	i=CRYPTO_add(&r->references,-1,CRYPTO_LOCK_EC);
+#ifdef REF_PRINT
+	REF_PRINT("EC_KEY",r);
+#endif
+	if (i > 0) return;
+#ifdef REF_CHECK
+	if (i < 0)
+		{
+		fprintf(stderr,"EC_KEY_free, bad reference count\n");
+		abort();
+		}
+#endif
+
+	if (r->group    != NULL) 
+		EC_GROUP_free(r->group);
+	if (r->pub_key  != NULL)
+		EC_POINT_free(r->pub_key);
+	if (r->priv_key != NULL)
+		BN_clear_free(r->priv_key);
+
+	EC_EX_DATA_free_all_data(&r->method_data);
+
+	OPENSSL_cleanse((void *)r, sizeof(EC_KEY));
+
+	OPENSSL_free(r);
+	}
+
+EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
+	{
+	EC_EXTRA_DATA *d;
+
+	if (dest == NULL || src == NULL)
+		{
+		ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER);
+		return NULL;
+		}
+	/* copy the parameters */
+	if (src->group)
+		{
+		const EC_METHOD *meth = EC_GROUP_method_of(src->group);
+		/* clear the old group */
+		if (dest->group)
+			EC_GROUP_free(dest->group);
+		dest->group = EC_GROUP_new(meth);
+		if (dest->group == NULL)
+			return NULL;
+		if (!EC_GROUP_copy(dest->group, src->group))
+			return NULL;
+		}
+	/*  copy the public key */
+	if (src->pub_key && src->group)
+		{
+		if (dest->pub_key)
+			EC_POINT_free(dest->pub_key);
+		dest->pub_key = EC_POINT_new(src->group);
+		if (dest->pub_key == NULL)
+			return NULL;
+		if (!EC_POINT_copy(dest->pub_key, src->pub_key))
+			return NULL;
+		}
+	/* copy the private key */
+	if (src->priv_key)
+		{
+		if (dest->priv_key == NULL)
+			{
+			dest->priv_key = BN_new();
+			if (dest->priv_key == NULL)
+				return NULL;
+			}
+		if (!BN_copy(dest->priv_key, src->priv_key))
+			return NULL;
+		}
+	/* copy method/extra data */
+	EC_EX_DATA_free_all_data(&dest->method_data);
+
+	for (d = src->method_data; d != NULL; d = d->next)
+		{
+		void *t = d->dup_func(d->data);
+		
+		if (t == NULL)
+			return 0;
+		if (!EC_EX_DATA_set_data(&dest->method_data, t, d->dup_func, d->free_func, d->clear_free_func))
+			return 0;
+		}
+
+	/* copy the rest */
+	dest->enc_flag  = src->enc_flag;
+	dest->conv_form = src->conv_form;
+	dest->version   = src->version;
+	dest->flags = src->flags;
+
+	return dest;
+	}
+
+EC_KEY *EC_KEY_dup(const EC_KEY *ec_key)
+	{
+	EC_KEY *ret = EC_KEY_new();
+	if (ret == NULL)
+		return NULL;
+	if (EC_KEY_copy(ret, ec_key) == NULL)
+		{
+		EC_KEY_free(ret);
+		return NULL;
+		}
+	return ret;
+	}
+
+int EC_KEY_up_ref(EC_KEY *r)
+	{
+	int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_EC);
+#ifdef REF_PRINT
+	REF_PRINT("EC_KEY",r);
+#endif
+#ifdef REF_CHECK
+	if (i < 2)
+		{
+		fprintf(stderr, "EC_KEY_up, bad reference count\n");
+		abort();
+		}
+#endif
+	return ((i > 1) ? 1 : 0);
+	}
+
+int EC_KEY_generate_key(EC_KEY *eckey)
+	{	
+	int	ok = 0;
+	BN_CTX	*ctx = NULL;
+	BIGNUM	*priv_key = NULL, *order = NULL;
+	EC_POINT *pub_key = NULL;
+
+#ifdef OPENSSL_FIPS
+	if (FIPS_mode())
+		return FIPS_ec_key_generate_key(eckey);
+#endif
+
+	if (!eckey || !eckey->group)
+		{
+		ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER);
+		return 0;
+		}
+
+	if ((order = BN_new()) == NULL) goto err;
+	if ((ctx = BN_CTX_new()) == NULL) goto err;
+
+	if (eckey->priv_key == NULL)
+		{
+		priv_key = BN_new();
+		if (priv_key == NULL)
+			goto err;
+		}
+	else
+		priv_key = eckey->priv_key;
+
+	if (!EC_GROUP_get_order(eckey->group, order, ctx))
+		goto err;
+
+	do
+		if (!BN_rand_range(priv_key, order))
+			goto err;
+	while (BN_is_zero(priv_key));
+
+	if (eckey->pub_key == NULL)
+		{
+		pub_key = EC_POINT_new(eckey->group);
+		if (pub_key == NULL)
+			goto err;
+		}
+	else
+		pub_key = eckey->pub_key;
+
+	if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, ctx))
+		goto err;
+
+	eckey->priv_key = priv_key;
+	eckey->pub_key  = pub_key;
+
+	ok=1;
+
+err:	
+	if (order)
+		BN_free(order);
+	if (pub_key  != NULL && eckey->pub_key  == NULL)
+		EC_POINT_free(pub_key);
+	if (priv_key != NULL && eckey->priv_key == NULL)
+		BN_free(priv_key);
+	if (ctx != NULL)
+		BN_CTX_free(ctx);
+	return(ok);
+	}
+
+int EC_KEY_check_key(const EC_KEY *eckey)
+	{
+	int	ok   = 0;
+	BN_CTX	*ctx = NULL;
+	const BIGNUM	*order  = NULL;
+	EC_POINT *point = NULL;
+
+	if (!eckey || !eckey->group || !eckey->pub_key)
+		{
+		ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER);
+		return 0;
+		}
+
+	if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key))
+		{
+		ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_AT_INFINITY);
+		goto err;
+		}
+
+	if ((ctx = BN_CTX_new()) == NULL)
+		goto err;
+	if ((point = EC_POINT_new(eckey->group)) == NULL)
+		goto err;
+
+	/* testing whether the pub_key is on the elliptic curve */
+	if (!EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx))
+		{
+		ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE);
+		goto err;
+		}
+	/* testing whether pub_key * order is the point at infinity */
+	order = &eckey->group->order;
+	if (BN_is_zero(order))
+		{
+		ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_GROUP_ORDER);
+		goto err;
+		}
+	if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx))
+		{
+		ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB);
+		goto err;
+		}
+	if (!EC_POINT_is_at_infinity(eckey->group, point))
+		{
+		ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER);
+		goto err;
+		}
+	/* in case the priv_key is present : 
+	 * check if generator * priv_key == pub_key 
+	 */
+	if (eckey->priv_key)
+		{
+		if (BN_cmp(eckey->priv_key, order) >= 0)
+			{
+			ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER);
+			goto err;
+			}
+		if (!EC_POINT_mul(eckey->group, point, eckey->priv_key,
+			NULL, NULL, ctx))
+			{
+			ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB);
+			goto err;
+			}
+		if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, 
+			ctx) != 0)
+			{
+			ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY);
+			goto err;
+			}
+		}
+	ok = 1;
+err:
+	if (ctx   != NULL)
+		BN_CTX_free(ctx);
+	if (point != NULL)
+		EC_POINT_free(point);
+	return(ok);
+	}
+
+int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y)
+	{
+	BN_CTX *ctx = NULL;
+	BIGNUM *tx, *ty;
+	EC_POINT *point = NULL;
+	int ok = 0, tmp_nid, is_char_two = 0;
+
+	if (!key || !key->group || !x || !y)
+		{
+		ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES,
+						ERR_R_PASSED_NULL_PARAMETER);
+		return 0;
+		}
+	ctx = BN_CTX_new();
+	if (!ctx)
+		goto err;
+
+	point = EC_POINT_new(key->group);
+
+	if (!point)
+		goto err;
+
+	tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(key->group));
+
+        if (tmp_nid == NID_X9_62_characteristic_two_field)
+		is_char_two = 1;
+
+	tx = BN_CTX_get(ctx);
+	ty = BN_CTX_get(ctx);
+#ifndef OPENSSL_NO_EC2M
+	if (is_char_two)
+		{
+		if (!EC_POINT_set_affine_coordinates_GF2m(key->group, point,
+								x, y, ctx))
+			goto err;
+		if (!EC_POINT_get_affine_coordinates_GF2m(key->group, point,
+								tx, ty, ctx))
+			goto err;
+		}
+	else
+#endif
+		{
+		if (!EC_POINT_set_affine_coordinates_GFp(key->group, point,
+								x, y, ctx))
+			goto err;
+		if (!EC_POINT_get_affine_coordinates_GFp(key->group, point,
+								tx, ty, ctx))
+			goto err;
+		}
+	/* Check if retrieved coordinates match originals: if not values
+	 * are out of range.
+	 */
+	if (BN_cmp(x, tx) || BN_cmp(y, ty))
+		{
+		ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES,
+			EC_R_COORDINATES_OUT_OF_RANGE);
+		goto err;
+		}
+
+	if (!EC_KEY_set_public_key(key, point))
+		goto err;
+
+	if (EC_KEY_check_key(key) == 0)
+		goto err;
+
+	ok = 1;
+
+	err:
+	if (ctx)
+		BN_CTX_free(ctx);
+	if (point)
+		EC_POINT_free(point);
+	return ok;
+
+	}
+
+const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key)
+	{
+	return key->group;
+	}
+
+int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group)
+	{
+	if (key->group != NULL)
+		EC_GROUP_free(key->group);
+	key->group = EC_GROUP_dup(group);
+	return (key->group == NULL) ? 0 : 1;
+	}
+
+const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key)
+	{
+	return key->priv_key;
+	}
+
+int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key)
+	{
+	if (key->priv_key)
+		BN_clear_free(key->priv_key);
+	key->priv_key = BN_dup(priv_key);
+	return (key->priv_key == NULL) ? 0 : 1;
+	}
+
+const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key)
+	{
+	return key->pub_key;
+	}
+
+int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key)
+	{
+	if (key->pub_key != NULL)
+		EC_POINT_free(key->pub_key);
+	key->pub_key = EC_POINT_dup(pub_key, key->group);
+	return (key->pub_key == NULL) ? 0 : 1;
+	}
+
+unsigned int EC_KEY_get_enc_flags(const EC_KEY *key)
+	{
+	return key->enc_flag;
+	}
+
+void EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags)
+	{
+	key->enc_flag = flags;
+	}
+
+point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key)
+	{
+	return key->conv_form;
+	}
+
+void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform)
+	{
+	key->conv_form = cform;
+	if (key->group != NULL)
+		EC_GROUP_set_point_conversion_form(key->group, cform);
+	}
+
+void *EC_KEY_get_key_method_data(EC_KEY *key,
+	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
+	{
+	return EC_EX_DATA_get_data(key->method_data, dup_func, free_func, clear_free_func);
+	}
+
+void EC_KEY_insert_key_method_data(EC_KEY *key, void *data,
+	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
+	{
+	EC_EXTRA_DATA *ex_data;
+	CRYPTO_w_lock(CRYPTO_LOCK_EC);
+	ex_data = EC_EX_DATA_get_data(key->method_data, dup_func, free_func, clear_free_func);
+	if (ex_data == NULL)
+		EC_EX_DATA_set_data(&key->method_data, data, dup_func, free_func, clear_free_func);
+	CRYPTO_w_unlock(CRYPTO_LOCK_EC);
+	}
+
+void EC_KEY_set_asn1_flag(EC_KEY *key, int flag)
+	{
+	if (key->group != NULL)
+		EC_GROUP_set_asn1_flag(key->group, flag);
+	}
+
+int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx)
+	{
+	if (key->group == NULL)
+		return 0;
+	return EC_GROUP_precompute_mult(key->group, ctx);
+	}
+
+int EC_KEY_get_flags(const EC_KEY *key)
+	{
+	return key->flags;
+	}
+
+void EC_KEY_set_flags(EC_KEY *key, int flags)
+	{
+	key->flags |= flags;
+	}
+
+void EC_KEY_clear_flags(EC_KEY *key, int flags)
+	{
+	key->flags &= ~flags;
+	}
diff --git a/jni/openssl/crypto/ec/ec_lcl.h b/jni/openssl/crypto/ec/ec_lcl.h
new file mode 100644
index 0000000..da7967d
--- /dev/null
+++ b/jni/openssl/crypto/ec/ec_lcl.h
@@ -0,0 +1,446 @@
+/* crypto/ec/ec_lcl.h */
+/*
+ * Originally written by Bodo Moeller for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2010 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 of the attached software ("Contribution") are developed by 
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * The elliptic curve binary polynomial software is originally written by 
+ * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
+ *
+ */
+
+
+#include <stdlib.h>
+
+#include <openssl/obj_mac.h>
+#include <openssl/ec.h>
+#include <openssl/bn.h>
+
+#if defined(__SUNPRO_C)
+# if __SUNPRO_C >= 0x520
+# pragma error_messages (off,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE)
+# endif
+#endif
+
+/* Use default functions for poin2oct, oct2point and compressed coordinates */
+#define EC_FLAGS_DEFAULT_OCT	0x1
+
+/* Structure details are not part of the exported interface,
+ * so all this may change in future versions. */
+
+struct ec_method_st {
+	/* Various method flags */
+	int flags;
+	/* used by EC_METHOD_get_field_type: */
+	int field_type; /* a NID */
+
+	/* used by EC_GROUP_new, EC_GROUP_free, EC_GROUP_clear_free, EC_GROUP_copy: */
+	int (*group_init)(EC_GROUP *);
+	void (*group_finish)(EC_GROUP *);
+	void (*group_clear_finish)(EC_GROUP *);
+	int (*group_copy)(EC_GROUP *, const EC_GROUP *);
+
+	/* used by EC_GROUP_set_curve_GFp, EC_GROUP_get_curve_GFp, */
+	/* EC_GROUP_set_curve_GF2m, and EC_GROUP_get_curve_GF2m: */
+	int (*group_set_curve)(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+	int (*group_get_curve)(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *);
+
+	/* used by EC_GROUP_get_degree: */
+	int (*group_get_degree)(const EC_GROUP *);
+
+	/* used by EC_GROUP_check: */
+	int (*group_check_discriminant)(const EC_GROUP *, BN_CTX *);
+
+	/* used by EC_POINT_new, EC_POINT_free, EC_POINT_clear_free, EC_POINT_copy: */
+	int (*point_init)(EC_POINT *);
+	void (*point_finish)(EC_POINT *);
+	void (*point_clear_finish)(EC_POINT *);
+	int (*point_copy)(EC_POINT *, const EC_POINT *);
+
+	/* used by EC_POINT_set_to_infinity,
+	 * EC_POINT_set_Jprojective_coordinates_GFp,
+	 * EC_POINT_get_Jprojective_coordinates_GFp,
+	 * EC_POINT_set_affine_coordinates_GFp,     ..._GF2m,
+	 * EC_POINT_get_affine_coordinates_GFp,     ..._GF2m,
+	 * EC_POINT_set_compressed_coordinates_GFp, ..._GF2m:
+	 */
+	int (*point_set_to_infinity)(const EC_GROUP *, EC_POINT *);
+	int (*point_set_Jprojective_coordinates_GFp)(const EC_GROUP *, EC_POINT *,
+		const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *);
+	int (*point_get_Jprojective_coordinates_GFp)(const EC_GROUP *, const EC_POINT *,
+		BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *);
+	int (*point_set_affine_coordinates)(const EC_GROUP *, EC_POINT *,
+		const BIGNUM *x, const BIGNUM *y, BN_CTX *);
+	int (*point_get_affine_coordinates)(const EC_GROUP *, const EC_POINT *,
+		BIGNUM *x, BIGNUM *y, BN_CTX *);
+	int (*point_set_compressed_coordinates)(const EC_GROUP *, EC_POINT *,
+		const BIGNUM *x, int y_bit, BN_CTX *);
+
+	/* used by EC_POINT_point2oct, EC_POINT_oct2point: */
+	size_t (*point2oct)(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form,
+	        unsigned char *buf, size_t len, BN_CTX *);
+	int (*oct2point)(const EC_GROUP *, EC_POINT *,
+	        const unsigned char *buf, size_t len, BN_CTX *);
+
+	/* used by EC_POINT_add, EC_POINT_dbl, ECP_POINT_invert: */
+	int (*add)(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *);
+	int (*dbl)(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *);
+	int (*invert)(const EC_GROUP *, EC_POINT *, BN_CTX *);
+
+	/* used by EC_POINT_is_at_infinity, EC_POINT_is_on_curve, EC_POINT_cmp: */
+	int (*is_at_infinity)(const EC_GROUP *, const EC_POINT *);
+	int (*is_on_curve)(const EC_GROUP *, const EC_POINT *, BN_CTX *);
+	int (*point_cmp)(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, BN_CTX *);
+
+	/* used by EC_POINT_make_affine, EC_POINTs_make_affine: */
+	int (*make_affine)(const EC_GROUP *, EC_POINT *, BN_CTX *);
+	int (*points_make_affine)(const EC_GROUP *, size_t num, EC_POINT *[], BN_CTX *);
+
+	/* used by EC_POINTs_mul, EC_POINT_mul, EC_POINT_precompute_mult, EC_POINT_have_precompute_mult
+	 * (default implementations are used if the 'mul' pointer is 0): */
+	int (*mul)(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
+		size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *);
+	int (*precompute_mult)(EC_GROUP *group, BN_CTX *);
+	int (*have_precompute_mult)(const EC_GROUP *group);
+
+
+	/* internal functions */
+
+	/* 'field_mul', 'field_sqr', and 'field_div' can be used by 'add' and 'dbl' so that
+	 * the same implementations of point operations can be used with different
+	 * optimized implementations of expensive field operations: */
+	int (*field_mul)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+	int (*field_sqr)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *);
+	int (*field_div)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+
+	int (*field_encode)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); /* e.g. to Montgomery */
+	int (*field_decode)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); /* e.g. from Montgomery */
+	int (*field_set_to_one)(const EC_GROUP *, BIGNUM *r, BN_CTX *);
+} /* EC_METHOD */;
+
+typedef struct ec_extra_data_st {
+	struct ec_extra_data_st *next;
+	void *data;
+	void *(*dup_func)(void *);
+	void (*free_func)(void *);
+	void (*clear_free_func)(void *);
+} EC_EXTRA_DATA; /* used in EC_GROUP */
+
+struct ec_group_st {
+	const EC_METHOD *meth;
+
+	EC_POINT *generator; /* optional */
+	BIGNUM order, cofactor;
+
+	int curve_name;/* optional NID for named curve */
+	int asn1_flag; /* flag to control the asn1 encoding */
+	point_conversion_form_t asn1_form;
+
+	unsigned char *seed; /* optional seed for parameters (appears in ASN1) */
+	size_t seed_len;
+
+	EC_EXTRA_DATA *extra_data; /* linked list */
+
+	/* The following members are handled by the method functions,
+	 * even if they appear generic */
+	
+	BIGNUM field; /* Field specification.
+	               * For curves over GF(p), this is the modulus;
+	               * for curves over GF(2^m), this is the 
+	               * irreducible polynomial defining the field.
+	               */
+
+	int poly[6]; /* Field specification for curves over GF(2^m).
+	              * The irreducible f(t) is then of the form:
+	              *     t^poly[0] + t^poly[1] + ... + t^poly[k]
+	              * where m = poly[0] > poly[1] > ... > poly[k] = 0.
+	              * The array is terminated with poly[k+1]=-1.
+	              * All elliptic curve irreducibles have at most 5
+	              * non-zero terms.
+	              */
+
+	BIGNUM a, b; /* Curve coefficients.
+	              * (Here the assumption is that BIGNUMs can be used
+	              * or abused for all kinds of fields, not just GF(p).)
+	              * For characteristic  > 3,  the curve is defined
+	              * by a Weierstrass equation of the form
+	              *     y^2 = x^3 + a*x + b.
+	              * For characteristic  2,  the curve is defined by
+	              * an equation of the form
+	              *     y^2 + x*y = x^3 + a*x^2 + b.
+	              */
+
+	int a_is_minus3; /* enable optimized point arithmetics for special case */
+
+	void *field_data1; /* method-specific (e.g., Montgomery structure) */
+	void *field_data2; /* method-specific */
+	int (*field_mod_func)(BIGNUM *, const BIGNUM *, const BIGNUM *,	BN_CTX *); /* method-specific */
+} /* EC_GROUP */;
+
+struct ec_key_st {
+	int version;
+
+	EC_GROUP *group;
+
+	EC_POINT *pub_key;
+	BIGNUM	 *priv_key;
+
+	unsigned int enc_flag;
+	point_conversion_form_t conv_form;
+
+	int 	references;
+	int	flags;
+
+	EC_EXTRA_DATA *method_data;
+} /* EC_KEY */;
+
+/* Basically a 'mixin' for extra data, but available for EC_GROUPs/EC_KEYs only
+ * (with visibility limited to 'package' level for now).
+ * We use the function pointers as index for retrieval; this obviates
+ * global ex_data-style index tables.
+ */
+int EC_EX_DATA_set_data(EC_EXTRA_DATA **, void *data,
+	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
+void *EC_EX_DATA_get_data(const EC_EXTRA_DATA *,
+	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
+void EC_EX_DATA_free_data(EC_EXTRA_DATA **,
+	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
+void EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **,
+	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
+void EC_EX_DATA_free_all_data(EC_EXTRA_DATA **);
+void EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **);
+
+
+
+struct ec_point_st {
+	const EC_METHOD *meth;
+
+	/* All members except 'meth' are handled by the method functions,
+	 * even if they appear generic */
+
+	BIGNUM X;
+	BIGNUM Y;
+	BIGNUM Z; /* Jacobian projective coordinates:
+	           * (X, Y, Z)  represents  (X/Z^2, Y/Z^3)  if  Z != 0 */
+	int Z_is_one; /* enable optimized point arithmetics for special case */
+} /* EC_POINT */;
+
+
+
+/* method functions in ec_mult.c
+ * (ec_lib.c uses these as defaults if group->method->mul is 0) */
+int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
+	size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *);
+int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *);
+int ec_wNAF_have_precompute_mult(const EC_GROUP *group);
+
+
+/* method functions in ecp_smpl.c */
+int ec_GFp_simple_group_init(EC_GROUP *);
+void ec_GFp_simple_group_finish(EC_GROUP *);
+void ec_GFp_simple_group_clear_finish(EC_GROUP *);
+int ec_GFp_simple_group_copy(EC_GROUP *, const EC_GROUP *);
+int ec_GFp_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+int ec_GFp_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *);
+int ec_GFp_simple_group_get_degree(const EC_GROUP *);
+int ec_GFp_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *);
+int ec_GFp_simple_point_init(EC_POINT *);
+void ec_GFp_simple_point_finish(EC_POINT *);
+void ec_GFp_simple_point_clear_finish(EC_POINT *);
+int ec_GFp_simple_point_copy(EC_POINT *, const EC_POINT *);
+int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *);
+int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *, EC_POINT *,
+	const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *);
+int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *, const EC_POINT *,
+	BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *);
+int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *,
+	const BIGNUM *x, const BIGNUM *y, BN_CTX *);
+int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *, const EC_POINT *,
+	BIGNUM *x, BIGNUM *y, BN_CTX *);
+int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *,
+	const BIGNUM *x, int y_bit, BN_CTX *);
+size_t ec_GFp_simple_point2oct(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form,
+	unsigned char *buf, size_t len, BN_CTX *);
+int ec_GFp_simple_oct2point(const EC_GROUP *, EC_POINT *,
+	const unsigned char *buf, size_t len, BN_CTX *);
+int ec_GFp_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *);
+int ec_GFp_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *);
+int ec_GFp_simple_invert(const EC_GROUP *, EC_POINT *, BN_CTX *);
+int ec_GFp_simple_is_at_infinity(const EC_GROUP *, const EC_POINT *);
+int ec_GFp_simple_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *);
+int ec_GFp_simple_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, BN_CTX *);
+int ec_GFp_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *);
+int ec_GFp_simple_points_make_affine(const EC_GROUP *, size_t num, EC_POINT *[], BN_CTX *);
+int ec_GFp_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+int ec_GFp_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *);
+
+
+/* method functions in ecp_mont.c */
+int ec_GFp_mont_group_init(EC_GROUP *);
+int ec_GFp_mont_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+void ec_GFp_mont_group_finish(EC_GROUP *);
+void ec_GFp_mont_group_clear_finish(EC_GROUP *);
+int ec_GFp_mont_group_copy(EC_GROUP *, const EC_GROUP *);
+int ec_GFp_mont_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+int ec_GFp_mont_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *);
+int ec_GFp_mont_field_encode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *);
+int ec_GFp_mont_field_decode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *);
+int ec_GFp_mont_field_set_to_one(const EC_GROUP *, BIGNUM *r, BN_CTX *);
+
+
+/* method functions in ecp_nist.c */
+int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src);
+int ec_GFp_nist_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+int ec_GFp_nist_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+int ec_GFp_nist_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *);
+
+
+/* method functions in ec2_smpl.c */
+int ec_GF2m_simple_group_init(EC_GROUP *);
+void ec_GF2m_simple_group_finish(EC_GROUP *);
+void ec_GF2m_simple_group_clear_finish(EC_GROUP *);
+int ec_GF2m_simple_group_copy(EC_GROUP *, const EC_GROUP *);
+int ec_GF2m_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+int ec_GF2m_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *);
+int ec_GF2m_simple_group_get_degree(const EC_GROUP *);
+int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *);
+int ec_GF2m_simple_point_init(EC_POINT *);
+void ec_GF2m_simple_point_finish(EC_POINT *);
+void ec_GF2m_simple_point_clear_finish(EC_POINT *);
+int ec_GF2m_simple_point_copy(EC_POINT *, const EC_POINT *);
+int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *);
+int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *,
+	const BIGNUM *x, const BIGNUM *y, BN_CTX *);
+int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *, const EC_POINT *,
+	BIGNUM *x, BIGNUM *y, BN_CTX *);
+int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *,
+	const BIGNUM *x, int y_bit, BN_CTX *);
+size_t ec_GF2m_simple_point2oct(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form,
+	unsigned char *buf, size_t len, BN_CTX *);
+int ec_GF2m_simple_oct2point(const EC_GROUP *, EC_POINT *,
+	const unsigned char *buf, size_t len, BN_CTX *);
+int ec_GF2m_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *);
+int ec_GF2m_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *);
+int ec_GF2m_simple_invert(const EC_GROUP *, EC_POINT *, BN_CTX *);
+int ec_GF2m_simple_is_at_infinity(const EC_GROUP *, const EC_POINT *);
+int ec_GF2m_simple_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *);
+int ec_GF2m_simple_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, BN_CTX *);
+int ec_GF2m_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *);
+int ec_GF2m_simple_points_make_affine(const EC_GROUP *, size_t num, EC_POINT *[], BN_CTX *);
+int ec_GF2m_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+int ec_GF2m_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *);
+int ec_GF2m_simple_field_div(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+
+
+/* method functions in ec2_mult.c */
+int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
+	size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *);
+int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
+int ec_GF2m_have_precompute_mult(const EC_GROUP *group);
+
+/* method functions in ec2_mult.c */
+int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
+	size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *);
+int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
+int ec_GF2m_have_precompute_mult(const EC_GROUP *group);
+
+#ifndef OPENSSL_EC_NISTP_64_GCC_128
+/* method functions in ecp_nistp224.c */
+int ec_GFp_nistp224_group_init(EC_GROUP *group);
+int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *n, BN_CTX *);
+int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx);
+int ec_GFp_nistp224_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *);
+int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx);
+int ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
+int ec_GFp_nistp224_have_precompute_mult(const EC_GROUP *group);
+
+/* method functions in ecp_nistp256.c */
+int ec_GFp_nistp256_group_init(EC_GROUP *group);
+int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *n, BN_CTX *);
+int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx);
+int ec_GFp_nistp256_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *);
+int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx);
+int ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
+int ec_GFp_nistp256_have_precompute_mult(const EC_GROUP *group);
+
+/* 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 *);
+int ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx);
+int ec_GFp_nistp521_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *);
+int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx);
+int ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
+int ec_GFp_nistp521_have_precompute_mult(const EC_GROUP *group);
+
+/* utility functions in ecp_nistputil.c */
+void ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array,
+	size_t felem_size, void *tmp_felems,
+	void (*felem_one)(void *out),
+	int (*felem_is_zero)(const void *in),
+	void (*felem_assign)(void *out, const void *in),
+	void (*felem_square)(void *out, const void *in),
+	void (*felem_mul)(void *out, const void *in1, const void *in2),
+	void (*felem_inv)(void *out, const void *in),
+	void (*felem_contract)(void *out, const void *in));
+void ec_GFp_nistp_recode_scalar_bits(unsigned char *sign, unsigned char *digit, unsigned char in);
+#endif
diff --git a/jni/openssl/crypto/ec/ec_lib.c b/jni/openssl/crypto/ec/ec_lib.c
new file mode 100644
index 0000000..25247b5
--- /dev/null
+++ b/jni/openssl/crypto/ec/ec_lib.c
@@ -0,0 +1,1096 @@
+/* crypto/ec/ec_lib.c */
+/*
+ * Originally written by Bodo Moeller for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2003 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.
+ * Binary polynomial ECC support in OpenSSL originally developed by 
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#include <string.h>
+
+#include <openssl/err.h>
+#include <openssl/opensslv.h>
+
+#include "ec_lcl.h"
+
+static const char EC_version[] = "EC" OPENSSL_VERSION_PTEXT;
+
+
+/* functions for EC_GROUP objects */
+
+EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
+	{
+	EC_GROUP *ret;
+
+	if (meth == NULL)
+		{
+		ECerr(EC_F_EC_GROUP_NEW, EC_R_SLOT_FULL);
+		return NULL;
+		}
+	if (meth->group_init == 0)
+		{
+		ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return NULL;
+		}
+
+	ret = OPENSSL_malloc(sizeof *ret);
+	if (ret == NULL)
+		{
+		ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE);
+		return NULL;
+		}
+
+	ret->meth = meth;
+
+	ret->extra_data = NULL;
+
+	ret->generator = NULL;
+	BN_init(&ret->order);
+	BN_init(&ret->cofactor);
+
+	ret->curve_name = 0;	
+	ret->asn1_flag  = 0;
+	ret->asn1_form  = POINT_CONVERSION_UNCOMPRESSED;
+
+	ret->seed = NULL;
+	ret->seed_len = 0;
+
+	if (!meth->group_init(ret))
+		{
+		OPENSSL_free(ret);
+		return NULL;
+		}
+	
+	return ret;
+	}
+
+
+void EC_GROUP_free(EC_GROUP *group)
+	{
+	if (!group) return;
+
+	if (group->meth->group_finish != 0)
+		group->meth->group_finish(group);
+
+	EC_EX_DATA_free_all_data(&group->extra_data);
+
+	if (group->generator != NULL)
+		EC_POINT_free(group->generator);
+	BN_free(&group->order);
+	BN_free(&group->cofactor);
+
+	if (group->seed)
+		OPENSSL_free(group->seed);
+
+	OPENSSL_free(group);
+	}
+ 
+
+void EC_GROUP_clear_free(EC_GROUP *group)
+	{
+	if (!group) return;
+
+	if (group->meth->group_clear_finish != 0)
+		group->meth->group_clear_finish(group);
+	else if (group->meth->group_finish != 0)
+		group->meth->group_finish(group);
+
+	EC_EX_DATA_clear_free_all_data(&group->extra_data);
+
+	if (group->generator != NULL)
+		EC_POINT_clear_free(group->generator);
+	BN_clear_free(&group->order);
+	BN_clear_free(&group->cofactor);
+
+	if (group->seed)
+		{
+		OPENSSL_cleanse(group->seed, group->seed_len);
+		OPENSSL_free(group->seed);
+		}
+
+	OPENSSL_cleanse(group, sizeof *group);
+	OPENSSL_free(group);
+	}
+
+
+int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
+	{
+	EC_EXTRA_DATA *d;
+
+	if (dest->meth->group_copy == 0)
+		{
+		ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	if (dest->meth != src->meth)
+		{
+		ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+		}
+	if (dest == src)
+		return 1;
+	
+	EC_EX_DATA_free_all_data(&dest->extra_data);
+
+	for (d = src->extra_data; d != NULL; d = d->next)
+		{
+		void *t = d->dup_func(d->data);
+		
+		if (t == NULL)
+			return 0;
+		if (!EC_EX_DATA_set_data(&dest->extra_data, t, d->dup_func, d->free_func, d->clear_free_func))
+			return 0;
+		}
+
+	if (src->generator != NULL)
+		{
+		if (dest->generator == NULL)
+			{
+			dest->generator = EC_POINT_new(dest);
+			if (dest->generator == NULL) return 0;
+			}
+		if (!EC_POINT_copy(dest->generator, src->generator)) return 0;
+		}
+	else
+		{
+		/* src->generator == NULL */
+		if (dest->generator != NULL)
+			{
+			EC_POINT_clear_free(dest->generator);
+			dest->generator = NULL;
+			}
+		}
+
+	if (!BN_copy(&dest->order, &src->order)) return 0;
+	if (!BN_copy(&dest->cofactor, &src->cofactor)) return 0;
+
+	dest->curve_name = src->curve_name;
+	dest->asn1_flag  = src->asn1_flag;
+	dest->asn1_form  = src->asn1_form;
+
+	if (src->seed)
+		{
+		if (dest->seed)
+			OPENSSL_free(dest->seed);
+		dest->seed = OPENSSL_malloc(src->seed_len);
+		if (dest->seed == NULL)
+			return 0;
+		if (!memcpy(dest->seed, src->seed, src->seed_len))
+			return 0;
+		dest->seed_len = src->seed_len;
+		}
+	else
+		{
+		if (dest->seed)
+			OPENSSL_free(dest->seed);
+		dest->seed = NULL;
+		dest->seed_len = 0;
+		}
+	
+
+	return dest->meth->group_copy(dest, src);
+	}
+
+
+EC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
+	{
+	EC_GROUP *t = NULL;
+	int ok = 0;
+
+	if (a == NULL) return NULL;
+
+	if ((t = EC_GROUP_new(a->meth)) == NULL) return(NULL);
+	if (!EC_GROUP_copy(t, a)) goto err;
+
+	ok = 1;
+
+  err:	
+	if (!ok)
+		{
+		if (t) EC_GROUP_free(t);
+		return NULL;
+		}
+	else return t;
+	}
+
+
+const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
+	{
+	return group->meth;
+	}
+
+
+int EC_METHOD_get_field_type(const EC_METHOD *meth)
+        {
+        return meth->field_type;
+        }
+
+
+int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor)
+	{
+	if (generator == NULL)
+		{
+		ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER);
+		return 0   ;
+		}
+
+	if (group->generator == NULL)
+		{
+		group->generator = EC_POINT_new(group);
+		if (group->generator == NULL) return 0;
+		}
+	if (!EC_POINT_copy(group->generator, generator)) return 0;
+
+	if (order != NULL)
+		{ if (!BN_copy(&group->order, order)) return 0; }	
+	else
+		BN_zero(&group->order);
+
+	if (cofactor != NULL)
+		{ if (!BN_copy(&group->cofactor, cofactor)) return 0; }	
+	else
+		BN_zero(&group->cofactor);
+
+	return 1;
+	}
+
+
+const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
+	{
+	return group->generator;
+	}
+
+
+int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
+	{
+	if (!BN_copy(order, &group->order))
+		return 0;
+
+	return !BN_is_zero(order);
+	}
+
+
+int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx)
+	{
+	if (!BN_copy(cofactor, &group->cofactor))
+		return 0;
+
+	return !BN_is_zero(&group->cofactor);
+	}
+
+
+void EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
+	{
+	group->curve_name = nid;
+	}
+
+
+int EC_GROUP_get_curve_name(const EC_GROUP *group)
+	{
+	return group->curve_name;
+	}
+
+
+void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
+	{
+	group->asn1_flag = flag;
+	}
+
+
+int EC_GROUP_get_asn1_flag(const EC_GROUP *group)
+	{
+	return group->asn1_flag;
+	}
+
+
+void EC_GROUP_set_point_conversion_form(EC_GROUP *group, 
+                                        point_conversion_form_t form)
+	{
+	group->asn1_form = form;
+	}
+
+
+point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *group)
+	{
+	return group->asn1_form;
+	}
+
+
+size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
+	{
+	if (group->seed)
+		{
+		OPENSSL_free(group->seed);
+		group->seed = NULL;
+		group->seed_len = 0;
+		}
+
+	if (!len || !p)
+		return 1;
+
+	if ((group->seed = OPENSSL_malloc(len)) == NULL)
+		return 0;
+	memcpy(group->seed, p, len);
+	group->seed_len = len;
+
+	return len;
+	}
+
+
+unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)
+	{
+	return group->seed;
+	}
+
+
+size_t EC_GROUP_get_seed_len(const EC_GROUP *group)
+	{
+	return group->seed_len;
+	}
+
+
+int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
+	{
+	if (group->meth->group_set_curve == 0)
+		{
+		ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	return group->meth->group_set_curve(group, p, a, b, ctx);
+	}
+
+
+int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
+	{
+	if (group->meth->group_get_curve == 0)
+		{
+		ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	return group->meth->group_get_curve(group, p, a, b, ctx);
+	}
+
+#ifndef OPENSSL_NO_EC2M
+int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
+	{
+	if (group->meth->group_set_curve == 0)
+		{
+		ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	return group->meth->group_set_curve(group, p, a, b, ctx);
+	}
+
+
+int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
+	{
+	if (group->meth->group_get_curve == 0)
+		{
+		ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	return group->meth->group_get_curve(group, p, a, b, ctx);
+	}
+#endif
+
+int EC_GROUP_get_degree(const EC_GROUP *group)
+	{
+	if (group->meth->group_get_degree == 0)
+		{
+		ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	return group->meth->group_get_degree(group);
+	}
+
+
+int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
+	{
+	if (group->meth->group_check_discriminant == 0)
+		{
+		ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	return group->meth->group_check_discriminant(group, ctx);
+	}
+
+
+int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
+	{
+	int    r = 0;
+	BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
+	BN_CTX *ctx_new = NULL;
+
+	/* compare the field types*/
+	if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) !=
+	    EC_METHOD_get_field_type(EC_GROUP_method_of(b)))
+		return 1;
+	/* compare the curve name (if present) */
+	if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
+	    EC_GROUP_get_curve_name(a) == EC_GROUP_get_curve_name(b))
+		return 0;
+
+	if (!ctx)
+		ctx_new = ctx = BN_CTX_new();
+	if (!ctx)
+		return -1;
+	
+	BN_CTX_start(ctx);
+	a1 = BN_CTX_get(ctx);
+	a2 = BN_CTX_get(ctx);
+	a3 = BN_CTX_get(ctx);
+	b1 = BN_CTX_get(ctx);
+	b2 = BN_CTX_get(ctx);
+	b3 = BN_CTX_get(ctx);
+	if (!b3)
+		{
+		BN_CTX_end(ctx);
+		if (ctx_new)
+			BN_CTX_free(ctx);
+		return -1;
+		}
+
+	/* XXX This approach assumes that the external representation
+	 * of curves over the same field type is the same.
+	 */
+	if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
+	    !b->meth->group_get_curve(b, b1, b2, b3, ctx))
+		r = 1;
+
+	if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3))
+		r = 1;
+
+	/* XXX EC_POINT_cmp() assumes that the methods are equal */
+	if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
+	    EC_GROUP_get0_generator(b), ctx))
+		r = 1;
+
+	if (!r)
+		{
+		/* compare the order and cofactor */
+		if (!EC_GROUP_get_order(a, a1, ctx) ||
+		    !EC_GROUP_get_order(b, b1, ctx) ||
+		    !EC_GROUP_get_cofactor(a, a2, ctx) ||
+		    !EC_GROUP_get_cofactor(b, b2, ctx))
+			{
+			BN_CTX_end(ctx);
+			if (ctx_new)
+				BN_CTX_free(ctx);
+			return -1;
+			}
+		if (BN_cmp(a1, b1) || BN_cmp(a2, b2))
+			r = 1;
+		}
+
+	BN_CTX_end(ctx);
+	if (ctx_new)
+		BN_CTX_free(ctx);
+
+	return r;
+	}
+
+
+/* this has 'package' visibility */
+int EC_EX_DATA_set_data(EC_EXTRA_DATA **ex_data, void *data,
+	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
+	{
+	EC_EXTRA_DATA *d;
+
+	if (ex_data == NULL)
+		return 0;
+
+	for (d = *ex_data; d != NULL; d = d->next)
+		{
+		if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func)
+			{
+			ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL);
+			return 0;
+			}
+		}
+
+	if (data == NULL)
+		/* no explicit entry needed */
+		return 1;
+
+	d = OPENSSL_malloc(sizeof *d);
+	if (d == NULL)
+		return 0;
+
+	d->data = data;
+	d->dup_func = dup_func;
+	d->free_func = free_func;
+	d->clear_free_func = clear_free_func;
+
+	d->next = *ex_data;
+	*ex_data = d;
+
+	return 1;
+	}
+
+/* this has 'package' visibility */
+void *EC_EX_DATA_get_data(const EC_EXTRA_DATA *ex_data,
+	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
+	{
+	const EC_EXTRA_DATA *d;
+
+	for (d = ex_data; d != NULL; d = d->next)
+		{
+		if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func)
+			return d->data;
+		}
+	
+	return NULL;
+	}
+
+/* this has 'package' visibility */
+void EC_EX_DATA_free_data(EC_EXTRA_DATA **ex_data,
+	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
+	{
+	EC_EXTRA_DATA **p;
+
+	if (ex_data == NULL)
+		return;
+
+	for (p = ex_data; *p != NULL; p = &((*p)->next))
+		{
+		if ((*p)->dup_func == dup_func && (*p)->free_func == free_func && (*p)->clear_free_func == clear_free_func)
+			{
+			EC_EXTRA_DATA *next = (*p)->next;
+
+			(*p)->free_func((*p)->data);
+			OPENSSL_free(*p);
+			
+			*p = next;
+			return;
+			}
+		}
+	}
+
+/* this has 'package' visibility */
+void EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **ex_data,
+	void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
+	{
+	EC_EXTRA_DATA **p;
+
+	if (ex_data == NULL)
+		return;
+
+	for (p = ex_data; *p != NULL; p = &((*p)->next))
+		{
+		if ((*p)->dup_func == dup_func && (*p)->free_func == free_func && (*p)->clear_free_func == clear_free_func)
+			{
+			EC_EXTRA_DATA *next = (*p)->next;
+
+			(*p)->clear_free_func((*p)->data);
+			OPENSSL_free(*p);
+			
+			*p = next;
+			return;
+			}
+		}
+	}
+
+/* this has 'package' visibility */
+void EC_EX_DATA_free_all_data(EC_EXTRA_DATA **ex_data)
+	{
+	EC_EXTRA_DATA *d;
+
+	if (ex_data == NULL)
+		return;
+
+	d = *ex_data;
+	while (d)
+		{
+		EC_EXTRA_DATA *next = d->next;
+		
+		d->free_func(d->data);
+		OPENSSL_free(d);
+		
+		d = next;
+		}
+	*ex_data = NULL;
+	}
+
+/* this has 'package' visibility */
+void EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **ex_data)
+	{
+	EC_EXTRA_DATA *d;
+
+	if (ex_data == NULL)
+		return;
+
+	d = *ex_data;
+	while (d)
+		{
+		EC_EXTRA_DATA *next = d->next;
+		
+		d->clear_free_func(d->data);
+		OPENSSL_free(d);
+		
+		d = next;
+		}
+	*ex_data = NULL;
+	}
+
+
+/* functions for EC_POINT objects */
+
+EC_POINT *EC_POINT_new(const EC_GROUP *group)
+	{
+	EC_POINT *ret;
+
+	if (group == NULL)
+		{
+		ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER);
+		return NULL;
+		}
+	if (group->meth->point_init == 0)
+		{
+		ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return NULL;
+		}
+
+	ret = OPENSSL_malloc(sizeof *ret);
+	if (ret == NULL)
+		{
+		ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE);
+		return NULL;
+		}
+
+	ret->meth = group->meth;
+	
+	if (!ret->meth->point_init(ret))
+		{
+		OPENSSL_free(ret);
+		return NULL;
+		}
+	
+	return ret;
+	}
+
+
+void EC_POINT_free(EC_POINT *point)
+	{
+	if (!point) return;
+
+	if (point->meth->point_finish != 0)
+		point->meth->point_finish(point);
+	OPENSSL_free(point);
+	}
+ 
+
+void EC_POINT_clear_free(EC_POINT *point)
+	{
+	if (!point) return;
+
+	if (point->meth->point_clear_finish != 0)
+		point->meth->point_clear_finish(point);
+	else if (point->meth->point_finish != 0)
+		point->meth->point_finish(point);
+	OPENSSL_cleanse(point, sizeof *point);
+	OPENSSL_free(point);
+	}
+
+
+int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
+	{
+	if (dest->meth->point_copy == 0)
+		{
+		ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	if (dest->meth != src->meth)
+		{
+		ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+		}
+	if (dest == src)
+		return 1;
+	return dest->meth->point_copy(dest, src);
+	}
+
+
+EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)
+	{
+	EC_POINT *t;
+	int r;
+
+	if (a == NULL) return NULL;
+
+	t = EC_POINT_new(group);
+	if (t == NULL) return(NULL);
+	r = EC_POINT_copy(t, a);
+	if (!r)
+		{
+		EC_POINT_free(t);
+		return NULL;
+		}
+	else return t;
+	}
+
+
+const EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
+	{
+	return point->meth;
+	}
+
+
+int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
+	{
+	if (group->meth->point_set_to_infinity == 0)
+		{
+		ECerr(EC_F_EC_POINT_SET_TO_INFINITY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	if (group->meth != point->meth)
+		{
+		ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+		}
+	return group->meth->point_set_to_infinity(group, point);
+	}
+
+
+int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
+	const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx)
+	{
+	if (group->meth->point_set_Jprojective_coordinates_GFp == 0)
+		{
+		ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	if (group->meth != point->meth)
+		{
+		ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+		}
+	return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, y, z, ctx);
+	}
+
+
+int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
+	BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx)
+	{
+	if (group->meth->point_get_Jprojective_coordinates_GFp == 0)
+		{
+		ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	if (group->meth != point->meth)
+		{
+		ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+		}
+	return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x, y, z, ctx);
+	}
+
+
+int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
+	const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
+	{
+	if (group->meth->point_set_affine_coordinates == 0)
+		{
+		ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	if (group->meth != point->meth)
+		{
+		ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+		}
+	return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
+	}
+
+#ifndef OPENSSL_NO_EC2M
+int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point,
+	const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
+	{
+	if (group->meth->point_set_affine_coordinates == 0)
+		{
+		ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	if (group->meth != point->meth)
+		{
+		ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+		}
+	return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
+	}
+#endif
+
+int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
+	BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
+	{
+	if (group->meth->point_get_affine_coordinates == 0)
+		{
+		ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	if (group->meth != point->meth)
+		{
+		ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+		}
+	return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
+	}
+
+#ifndef OPENSSL_NO_EC2M
+int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, const EC_POINT *point,
+	BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
+	{
+	if (group->meth->point_get_affine_coordinates == 0)
+		{
+		ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	if (group->meth != point->meth)
+		{
+		ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+		}
+	return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
+	}
+#endif
+
+int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
+	{
+	if (group->meth->add == 0)
+		{
+		ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	if ((group->meth != r->meth) || (r->meth != a->meth) || (a->meth != b->meth))
+		{
+		ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+		}
+	return group->meth->add(group, r, a, b, ctx);
+	}
+
+
+int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
+	{
+	if (group->meth->dbl == 0)
+		{
+		ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	if ((group->meth != r->meth) || (r->meth != a->meth))
+		{
+		ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+		}
+	return group->meth->dbl(group, r, a, ctx);
+	}
+
+
+int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
+	{
+	if (group->meth->dbl == 0)
+		{
+		ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	if (group->meth != a->meth)
+		{
+		ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+		}
+	return group->meth->invert(group, a, ctx);
+	}
+
+
+int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
+	{
+	if (group->meth->is_at_infinity == 0)
+		{
+		ECerr(EC_F_EC_POINT_IS_AT_INFINITY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	if (group->meth != point->meth)
+		{
+		ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+		}
+	return group->meth->is_at_infinity(group, point);
+	}
+
+
+int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
+	{
+	if (group->meth->is_on_curve == 0)
+		{
+		ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	if (group->meth != point->meth)
+		{
+		ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+		}
+	return group->meth->is_on_curve(group, point, ctx);
+	}
+
+
+int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
+	{
+	if (group->meth->point_cmp == 0)
+		{
+		ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	if ((group->meth != a->meth) || (a->meth != b->meth))
+		{
+		ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+		}
+	return group->meth->point_cmp(group, a, b, ctx);
+	}
+
+
+int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
+	{
+	if (group->meth->make_affine == 0)
+		{
+		ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	if (group->meth != point->meth)
+		{
+		ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+		}
+	return group->meth->make_affine(group, point, ctx);
+	}
+
+
+int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
+	{
+	size_t i;
+
+	if (group->meth->points_make_affine == 0)
+		{
+		ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	for (i = 0; i < num; i++)
+		{
+		if (group->meth != points[i]->meth)
+			{
+			ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
+			return 0;
+			}
+		}
+	return group->meth->points_make_affine(group, num, points, ctx);
+	}
+
+
+/* Functions for point multiplication.
+ *
+ * If group->meth->mul is 0, we use the wNAF-based implementations in ec_mult.c;
+ * otherwise we dispatch through methods.
+ */
+
+int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
+	size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx)
+	{
+	if (group->meth->mul == 0)
+		/* use default */
+		return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
+
+	return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
+	}
+
+int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
+	const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
+	{
+	/* just a convenient interface to EC_POINTs_mul() */
+
+	const EC_POINT *points[1];
+	const BIGNUM *scalars[1];
+
+	points[0] = point;
+	scalars[0] = p_scalar;
+
+	return EC_POINTs_mul(group, r, g_scalar, (point != NULL && p_scalar != NULL), points, scalars, ctx);
+	}
+
+int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
+	{
+	if (group->meth->mul == 0)
+		/* use default */
+		return ec_wNAF_precompute_mult(group, ctx);
+
+	if (group->meth->precompute_mult != 0)
+		return group->meth->precompute_mult(group, ctx);
+	else
+		return 1; /* nothing to do, so report success */
+	}
+
+int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
+	{
+	if (group->meth->mul == 0)
+		/* use default */
+		return ec_wNAF_have_precompute_mult(group);
+
+	if (group->meth->have_precompute_mult != 0)
+		return group->meth->have_precompute_mult(group);
+	else
+		return 0; /* cannot tell whether precomputation has been performed */
+	}
diff --git a/jni/openssl/crypto/ec/ec_mult.c b/jni/openssl/crypto/ec/ec_mult.c
new file mode 100644
index 0000000..19f2167
--- /dev/null
+++ b/jni/openssl/crypto/ec/ec_mult.c
@@ -0,0 +1,940 @@
+/* crypto/ec/ec_mult.c */
+/*
+ * Originally written by Bodo Moeller and Nils Larsch for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2007 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 of this software developed by SUN MICROSYSTEMS, INC.,
+ * and contributed to the OpenSSL project.
+ */
+
+#include <string.h>
+
+#include <openssl/err.h>
+
+#include "ec_lcl.h"
+
+
+/*
+ * This file implements the wNAF-based interleaving multi-exponentation method
+ * (<URL:http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#multiexp>);
+ * for multiplication with precomputation, we use wNAF splitting
+ * (<URL:http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#fastexp>).
+ */
+
+
+
+
+/* structure for precomputed multiples of the generator */
+typedef struct ec_pre_comp_st {
+	const EC_GROUP *group; /* parent EC_GROUP object */
+	size_t blocksize;      /* block size for wNAF splitting */
+	size_t numblocks;      /* max. number of blocks for which we have precomputation */
+	size_t w;              /* window size */
+	EC_POINT **points;     /* array with pre-calculated multiples of generator:
+	                        * 'num' pointers to EC_POINT objects followed by a NULL */
+	size_t num;            /* numblocks * 2^(w-1) */
+	int references;
+} EC_PRE_COMP;
+ 
+/* functions to manage EC_PRE_COMP within the EC_GROUP extra_data framework */
+static void *ec_pre_comp_dup(void *);
+static void ec_pre_comp_free(void *);
+static void ec_pre_comp_clear_free(void *);
+
+static EC_PRE_COMP *ec_pre_comp_new(const EC_GROUP *group)
+	{
+	EC_PRE_COMP *ret = NULL;
+
+	if (!group)
+		return NULL;
+
+	ret = (EC_PRE_COMP *)OPENSSL_malloc(sizeof(EC_PRE_COMP));
+	if (!ret)
+		{
+		ECerr(EC_F_EC_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
+		return ret;
+		}
+	ret->group = group;
+	ret->blocksize = 8; /* default */
+	ret->numblocks = 0;
+	ret->w = 4; /* default */
+	ret->points = NULL;
+	ret->num = 0;
+	ret->references = 1;
+	return ret;
+	}
+
+static void *ec_pre_comp_dup(void *src_)
+	{
+	EC_PRE_COMP *src = src_;
+
+	/* no need to actually copy, these objects never change! */
+
+	CRYPTO_add(&src->references, 1, CRYPTO_LOCK_EC_PRE_COMP);
+
+	return src_;
+	}
+
+static void ec_pre_comp_free(void *pre_)
+	{
+	int i;
+	EC_PRE_COMP *pre = pre_;
+
+	if (!pre)
+		return;
+
+	i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP);
+	if (i > 0)
+		return;
+
+	if (pre->points)
+		{
+		EC_POINT **p;
+
+		for (p = pre->points; *p != NULL; p++)
+			EC_POINT_free(*p);
+		OPENSSL_free(pre->points);
+		}
+	OPENSSL_free(pre);
+	}
+
+static void ec_pre_comp_clear_free(void *pre_)
+	{
+	int i;
+	EC_PRE_COMP *pre = pre_;
+
+	if (!pre)
+		return;
+
+	i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP);
+	if (i > 0)
+		return;
+
+	if (pre->points)
+		{
+		EC_POINT **p;
+
+		for (p = pre->points; *p != NULL; p++)
+			{
+			EC_POINT_clear_free(*p);
+			OPENSSL_cleanse(p, sizeof *p);
+			}
+		OPENSSL_free(pre->points);
+		}
+	OPENSSL_cleanse(pre, sizeof *pre);
+	OPENSSL_free(pre);
+	}
+
+
+
+
+/* Determine the modified width-(w+1) Non-Adjacent Form (wNAF) of 'scalar'.
+ * This is an array  r[]  of values that are either zero or odd with an
+ * absolute value less than  2^w  satisfying
+ *     scalar = \sum_j r[j]*2^j
+ * where at most one of any  w+1  consecutive digits is non-zero
+ * with the exception that the most significant digit may be only
+ * w-1 zeros away from that next non-zero digit.
+ */
+static signed char *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len)
+	{
+	int window_val;
+	int ok = 0;
+	signed char *r = NULL;
+	int sign = 1;
+	int bit, next_bit, mask;
+	size_t len = 0, j;
+	
+	if (BN_is_zero(scalar))
+		{
+		r = OPENSSL_malloc(1);
+		if (!r)
+			{
+			ECerr(EC_F_COMPUTE_WNAF, ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+		r[0] = 0;
+		*ret_len = 1;
+		return r;
+		}
+		
+	if (w <= 0 || w > 7) /* 'signed char' can represent integers with absolute values less than 2^7 */
+		{
+		ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
+		goto err;
+		}
+	bit = 1 << w; /* at most 128 */
+	next_bit = bit << 1; /* at most 256 */
+	mask = next_bit - 1; /* at most 255 */
+
+	if (BN_is_negative(scalar))
+		{
+		sign = -1;
+		}
+
+	if (scalar->d == NULL || scalar->top == 0)
+		{
+		ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
+		goto err;
+		}
+
+	len = BN_num_bits(scalar);
+	r = OPENSSL_malloc(len + 1); /* modified wNAF may be one digit longer than binary representation
+	                              * (*ret_len will be set to the actual length, i.e. at most
+	                              * BN_num_bits(scalar) + 1) */
+	if (r == NULL)
+		{
+		ECerr(EC_F_COMPUTE_WNAF, ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+	window_val = scalar->d[0] & mask;
+	j = 0;
+	while ((window_val != 0) || (j + w + 1 < len)) /* if j+w+1 >= len, window_val will not increase */
+		{
+		int digit = 0;
+
+		/* 0 <= window_val <= 2^(w+1) */
+
+		if (window_val & 1)
+			{
+			/* 0 < window_val < 2^(w+1) */
+
+			if (window_val & bit)
+				{
+				digit = window_val - next_bit; /* -2^w < digit < 0 */
+
+#if 1 /* modified wNAF */
+				if (j + w + 1 >= len)
+					{
+					/* special case for generating modified wNAFs:
+					 * no new bits will be added into window_val,
+					 * so using a positive digit here will decrease
+					 * the total length of the representation */
+					
+					digit = window_val & (mask >> 1); /* 0 < digit < 2^w */
+					}
+#endif
+				}
+			else
+				{
+				digit = window_val; /* 0 < digit < 2^w */
+				}
+			
+			if (digit <= -bit || digit >= bit || !(digit & 1))
+				{
+				ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
+				goto err;
+				}
+
+			window_val -= digit;
+
+			/* now window_val is 0 or 2^(w+1) in standard wNAF generation;
+			 * for modified window NAFs, it may also be 2^w
+			 */
+			if (window_val != 0 && window_val != next_bit && window_val != bit)
+				{
+				ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
+				goto err;
+				}
+			}
+
+		r[j++] = sign * digit;
+
+		window_val >>= 1;
+		window_val += bit * BN_is_bit_set(scalar, j + w);
+
+		if (window_val > next_bit)
+			{
+			ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
+			goto err;
+			}
+		}
+
+	if (j > len + 1)
+		{
+		ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
+		goto err;
+		}
+	len = j;
+	ok = 1;
+
+ err:
+	if (!ok)
+		{
+		OPENSSL_free(r);
+		r = NULL;
+		}
+	if (ok)
+		*ret_len = len;
+	return r;
+	}
+
+
+/* TODO: table should be optimised for the wNAF-based implementation,
+ *       sometimes smaller windows will give better performance
+ *       (thus the boundaries should be increased)
+ */
+#define EC_window_bits_for_scalar_size(b) \
+		((size_t) \
+		 ((b) >= 2000 ? 6 : \
+		  (b) >=  800 ? 5 : \
+		  (b) >=  300 ? 4 : \
+		  (b) >=   70 ? 3 : \
+		  (b) >=   20 ? 2 : \
+		  1))
+
+/* Compute
+ *      \sum scalars[i]*points[i],
+ * also including
+ *      scalar*generator
+ * in the addition if scalar != NULL
+ */
+int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
+	size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx)
+	{
+	BN_CTX *new_ctx = NULL;
+	const EC_POINT *generator = NULL;
+	EC_POINT *tmp = NULL;
+	size_t totalnum;
+	size_t blocksize = 0, numblocks = 0; /* for wNAF splitting */
+	size_t pre_points_per_block = 0;
+	size_t i, j;
+	int k;
+	int r_is_inverted = 0;
+	int r_is_at_infinity = 1;
+	size_t *wsize = NULL; /* individual window sizes */
+	signed char **wNAF = NULL; /* individual wNAFs */
+	size_t *wNAF_len = NULL;
+	size_t max_len = 0;
+	size_t num_val;
+	EC_POINT **val = NULL; /* precomputation */
+	EC_POINT **v;
+	EC_POINT ***val_sub = NULL; /* pointers to sub-arrays of 'val' or 'pre_comp->points' */
+	const EC_PRE_COMP *pre_comp = NULL;
+	int num_scalar = 0; /* flag: will be set to 1 if 'scalar' must be treated like other scalars,
+	                     * i.e. precomputation is not available */
+	int ret = 0;
+	
+	if (group->meth != r->meth)
+		{
+		ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+		}
+
+	if ((scalar == NULL) && (num == 0))
+		{
+		return EC_POINT_set_to_infinity(group, r);
+		}
+
+	for (i = 0; i < num; i++)
+		{
+		if (group->meth != points[i]->meth)
+			{
+			ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS);
+			return 0;
+			}
+		}
+
+	if (ctx == NULL)
+		{
+		ctx = new_ctx = BN_CTX_new();
+		if (ctx == NULL)
+			goto err;
+		}
+
+	if (scalar != NULL)
+		{
+		generator = EC_GROUP_get0_generator(group);
+		if (generator == NULL)
+			{
+			ECerr(EC_F_EC_WNAF_MUL, EC_R_UNDEFINED_GENERATOR);
+			goto err;
+			}
+		
+		/* look if we can use precomputed multiples of generator */
+
+		pre_comp = EC_EX_DATA_get_data(group->extra_data, ec_pre_comp_dup, ec_pre_comp_free, ec_pre_comp_clear_free);
+
+		if (pre_comp && pre_comp->numblocks && (EC_POINT_cmp(group, generator, pre_comp->points[0], ctx) == 0))
+			{
+			blocksize = pre_comp->blocksize;
+
+			/* determine maximum number of blocks that wNAF splitting may yield
+			 * (NB: maximum wNAF length is bit length plus one) */
+			numblocks = (BN_num_bits(scalar) / blocksize) + 1;
+
+			/* we cannot use more blocks than we have precomputation for */
+			if (numblocks > pre_comp->numblocks)
+				numblocks = pre_comp->numblocks;
+
+			pre_points_per_block = (size_t)1 << (pre_comp->w - 1);
+
+			/* check that pre_comp looks sane */
+			if (pre_comp->num != (pre_comp->numblocks * pre_points_per_block))
+				{
+				ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
+				goto err;
+				}
+			}
+		else
+			{
+			/* can't use precomputation */
+			pre_comp = NULL;
+			numblocks = 1;
+			num_scalar = 1; /* treat 'scalar' like 'num'-th element of 'scalars' */
+			}
+		}
+	
+	totalnum = num + numblocks;
+
+	wsize    = OPENSSL_malloc(totalnum * sizeof wsize[0]);
+	wNAF_len = OPENSSL_malloc(totalnum * sizeof wNAF_len[0]);
+	wNAF     = OPENSSL_malloc((totalnum + 1) * sizeof wNAF[0]); /* includes space for pivot */
+	val_sub  = OPENSSL_malloc(totalnum * sizeof val_sub[0]);
+		 
+	if (!wsize || !wNAF_len || !wNAF || !val_sub)
+		{
+		ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+
+	wNAF[0] = NULL;	/* preliminary pivot */
+
+	/* num_val will be the total number of temporarily precomputed points */
+	num_val = 0;
+
+	for (i = 0; i < num + num_scalar; i++)
+		{
+		size_t bits;
+
+		bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(scalar);
+		wsize[i] = EC_window_bits_for_scalar_size(bits);
+		num_val += (size_t)1 << (wsize[i] - 1);
+		wNAF[i + 1] = NULL; /* make sure we always have a pivot */
+		wNAF[i] = compute_wNAF((i < num ? scalars[i] : scalar), wsize[i], &wNAF_len[i]);
+		if (wNAF[i] == NULL)
+			goto err;
+		if (wNAF_len[i] > max_len)
+			max_len = wNAF_len[i];
+		}
+
+	if (numblocks)
+		{
+		/* we go here iff scalar != NULL */
+		
+		if (pre_comp == NULL)
+			{
+			if (num_scalar != 1)
+				{
+				ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
+				goto err;
+				}
+			/* we have already generated a wNAF for 'scalar' */
+			}
+		else
+			{
+			signed char *tmp_wNAF = NULL;
+			size_t tmp_len = 0;
+			
+			if (num_scalar != 0)
+				{
+				ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
+				goto err;
+				}
+
+			/* use the window size for which we have precomputation */
+			wsize[num] = pre_comp->w;
+			tmp_wNAF = compute_wNAF(scalar, wsize[num], &tmp_len);
+			if (!tmp_wNAF)
+				goto err;
+
+			if (tmp_len <= max_len)
+				{
+				/* One of the other wNAFs is at least as long
+				 * as the wNAF belonging to the generator,
+				 * so wNAF splitting will not buy us anything. */
+
+				numblocks = 1;
+				totalnum = num + 1; /* don't use wNAF splitting */
+				wNAF[num] = tmp_wNAF;
+				wNAF[num + 1] = NULL;
+				wNAF_len[num] = tmp_len;
+				if (tmp_len > max_len)
+					max_len = tmp_len;
+				/* pre_comp->points starts with the points that we need here: */
+				val_sub[num] = pre_comp->points;
+				}
+			else
+				{
+				/* don't include tmp_wNAF directly into wNAF array
+				 * - use wNAF splitting and include the blocks */
+
+				signed char *pp;
+				EC_POINT **tmp_points;
+				
+				if (tmp_len < numblocks * blocksize)
+					{
+					/* possibly we can do with fewer blocks than estimated */
+					numblocks = (tmp_len + blocksize - 1) / blocksize;
+					if (numblocks > pre_comp->numblocks)
+						{
+						ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
+						goto err;
+						}
+					totalnum = num + numblocks;
+					}
+				
+				/* split wNAF in 'numblocks' parts */
+				pp = tmp_wNAF;
+				tmp_points = pre_comp->points;
+
+				for (i = num; i < totalnum; i++)
+					{
+					if (i < totalnum - 1)
+						{
+						wNAF_len[i] = blocksize;
+						if (tmp_len < blocksize)
+							{
+							ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
+							goto err;
+							}
+						tmp_len -= blocksize;
+						}
+					else
+						/* last block gets whatever is left
+						 * (this could be more or less than 'blocksize'!) */
+						wNAF_len[i] = tmp_len;
+					
+					wNAF[i + 1] = NULL;
+					wNAF[i] = OPENSSL_malloc(wNAF_len[i]);
+					if (wNAF[i] == NULL)
+						{
+						ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);
+						OPENSSL_free(tmp_wNAF);
+						goto err;
+						}
+					memcpy(wNAF[i], pp, wNAF_len[i]);
+					if (wNAF_len[i] > max_len)
+						max_len = wNAF_len[i];
+
+					if (*tmp_points == NULL)
+						{
+						ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
+						OPENSSL_free(tmp_wNAF);
+						goto err;
+						}
+					val_sub[i] = tmp_points;
+					tmp_points += pre_points_per_block;
+					pp += blocksize;
+					}
+				OPENSSL_free(tmp_wNAF);
+				}
+			}
+		}
+
+	/* All points we precompute now go into a single array 'val'.
+	 * 'val_sub[i]' is a pointer to the subarray for the i-th point,
+	 * or to a subarray of 'pre_comp->points' if we already have precomputation. */
+	val = OPENSSL_malloc((num_val + 1) * sizeof val[0]);
+	if (val == NULL)
+		{
+		ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+	val[num_val] = NULL; /* pivot element */
+
+	/* allocate points for precomputation */
+	v = val;
+	for (i = 0; i < num + num_scalar; i++)
+		{
+		val_sub[i] = v;
+		for (j = 0; j < ((size_t)1 << (wsize[i] - 1)); j++)
+			{
+			*v = EC_POINT_new(group);
+			if (*v == NULL) goto err;
+			v++;
+			}
+		}
+	if (!(v == val + num_val))
+		{
+		ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
+		goto err;
+		}
+
+	if (!(tmp = EC_POINT_new(group)))
+		goto err;
+
+	/* prepare precomputed values:
+	 *    val_sub[i][0] :=     points[i]
+	 *    val_sub[i][1] := 3 * points[i]
+	 *    val_sub[i][2] := 5 * points[i]
+	 *    ...
+	 */
+	for (i = 0; i < num + num_scalar; i++)
+		{
+		if (i < num)
+			{
+			if (!EC_POINT_copy(val_sub[i][0], points[i])) goto err;
+			}
+		else
+			{
+			if (!EC_POINT_copy(val_sub[i][0], generator)) goto err;
+			}
+
+		if (wsize[i] > 1)
+			{
+			if (!EC_POINT_dbl(group, tmp, val_sub[i][0], ctx)) goto err;
+			for (j = 1; j < ((size_t)1 << (wsize[i] - 1)); j++)
+				{
+				if (!EC_POINT_add(group, val_sub[i][j], val_sub[i][j - 1], tmp, ctx)) goto err;
+				}
+			}
+		}
+
+#if 1 /* optional; EC_window_bits_for_scalar_size assumes we do this step */
+	if (!EC_POINTs_make_affine(group, num_val, val, ctx))
+		goto err;
+#endif
+
+	r_is_at_infinity = 1;
+
+	for (k = max_len - 1; k >= 0; k--)
+		{
+		if (!r_is_at_infinity)
+			{
+			if (!EC_POINT_dbl(group, r, r, ctx)) goto err;
+			}
+		
+		for (i = 0; i < totalnum; i++)
+			{
+			if (wNAF_len[i] > (size_t)k)
+				{
+				int digit = wNAF[i][k];
+				int is_neg;
+
+				if (digit) 
+					{
+					is_neg = digit < 0;
+
+					if (is_neg)
+						digit = -digit;
+
+					if (is_neg != r_is_inverted)
+						{
+						if (!r_is_at_infinity)
+							{
+							if (!EC_POINT_invert(group, r, ctx)) goto err;
+							}
+						r_is_inverted = !r_is_inverted;
+						}
+
+					/* digit > 0 */
+
+					if (r_is_at_infinity)
+						{
+						if (!EC_POINT_copy(r, val_sub[i][digit >> 1])) goto err;
+						r_is_at_infinity = 0;
+						}
+					else
+						{
+						if (!EC_POINT_add(group, r, r, val_sub[i][digit >> 1], ctx)) goto err;
+						}
+					}
+				}
+			}
+		}
+
+	if (r_is_at_infinity)
+		{
+		if (!EC_POINT_set_to_infinity(group, r)) goto err;
+		}
+	else
+		{
+		if (r_is_inverted)
+			if (!EC_POINT_invert(group, r, ctx)) goto err;
+		}
+	
+	ret = 1;
+
+ err:
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	if (tmp != NULL)
+		EC_POINT_free(tmp);
+	if (wsize != NULL)
+		OPENSSL_free(wsize);
+	if (wNAF_len != NULL)
+		OPENSSL_free(wNAF_len);
+	if (wNAF != NULL)
+		{
+		signed char **w;
+		
+		for (w = wNAF; *w != NULL; w++)
+			OPENSSL_free(*w);
+		
+		OPENSSL_free(wNAF);
+		}
+	if (val != NULL)
+		{
+		for (v = val; *v != NULL; v++)
+			EC_POINT_clear_free(*v);
+
+		OPENSSL_free(val);
+		}
+	if (val_sub != NULL)
+		{
+		OPENSSL_free(val_sub);
+		}
+	return ret;
+	}
+
+
+/* ec_wNAF_precompute_mult()
+ * creates an EC_PRE_COMP object with preprecomputed multiples of the generator
+ * for use with wNAF splitting as implemented in ec_wNAF_mul().
+ * 
+ * 'pre_comp->points' is an array of multiples of the generator
+ * of the following form:
+ * points[0] =     generator;
+ * points[1] = 3 * generator;
+ * ...
+ * points[2^(w-1)-1] =     (2^(w-1)-1) * generator;
+ * points[2^(w-1)]   =     2^blocksize * generator;
+ * points[2^(w-1)+1] = 3 * 2^blocksize * generator;
+ * ...
+ * points[2^(w-1)*(numblocks-1)-1] = (2^(w-1)) *  2^(blocksize*(numblocks-2)) * generator
+ * points[2^(w-1)*(numblocks-1)]   =              2^(blocksize*(numblocks-1)) * generator
+ * ...
+ * points[2^(w-1)*numblocks-1]     = (2^(w-1)) *  2^(blocksize*(numblocks-1)) * generator
+ * points[2^(w-1)*numblocks]       = NULL
+ */
+int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
+	{
+	const EC_POINT *generator;
+	EC_POINT *tmp_point = NULL, *base = NULL, **var;
+	BN_CTX *new_ctx = NULL;
+	BIGNUM *order;
+	size_t i, bits, w, pre_points_per_block, blocksize, numblocks, num;
+	EC_POINT **points = NULL;
+	EC_PRE_COMP *pre_comp;
+	int ret = 0;
+
+	/* if there is an old EC_PRE_COMP object, throw it away */
+	EC_EX_DATA_free_data(&group->extra_data, ec_pre_comp_dup, ec_pre_comp_free, ec_pre_comp_clear_free);
+
+	if ((pre_comp = ec_pre_comp_new(group)) == NULL)
+		return 0;
+
+	generator = EC_GROUP_get0_generator(group);
+	if (generator == NULL)
+		{
+		ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNDEFINED_GENERATOR);
+		goto err;
+		}
+
+	if (ctx == NULL)
+		{
+		ctx = new_ctx = BN_CTX_new();
+		if (ctx == NULL)
+			goto err;
+		}
+	
+	BN_CTX_start(ctx);
+	order = BN_CTX_get(ctx);
+	if (order == NULL) goto err;
+	
+	if (!EC_GROUP_get_order(group, order, ctx)) goto err;		
+	if (BN_is_zero(order))
+		{
+		ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNKNOWN_ORDER);
+		goto err;
+		}
+
+	bits = BN_num_bits(order);
+	/* The following parameters mean we precompute (approximately)
+	 * one point per bit.
+	 *
+	 * TBD: The combination  8, 4  is perfect for 160 bits; for other
+	 * bit lengths, other parameter combinations might provide better
+	 * efficiency.
+	 */
+	blocksize = 8;
+	w = 4;
+	if (EC_window_bits_for_scalar_size(bits) > w)
+		{
+		/* let's not make the window too small ... */
+		w = EC_window_bits_for_scalar_size(bits);
+		}
+
+	numblocks = (bits + blocksize - 1) / blocksize; /* max. number of blocks to use for wNAF splitting */
+	
+	pre_points_per_block = (size_t)1 << (w - 1);
+	num = pre_points_per_block * numblocks; /* number of points to compute and store */
+
+	points = OPENSSL_malloc(sizeof (EC_POINT*)*(num + 1));
+	if (!points)
+		{
+		ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);
+		goto err;
+		}
+
+	var = points;
+	var[num] = NULL; /* pivot */
+	for (i = 0; i < num; i++)
+		{
+		if ((var[i] = EC_POINT_new(group)) == NULL)
+			{
+			ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+		}
+
+	if (!(tmp_point = EC_POINT_new(group)) || !(base = EC_POINT_new(group)))
+		{
+		ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);
+		goto err;
+		}	
+	
+	if (!EC_POINT_copy(base, generator))
+		goto err;
+	
+	/* do the precomputation */
+	for (i = 0; i < numblocks; i++)
+		{
+		size_t j;
+
+		if (!EC_POINT_dbl(group, tmp_point, base, ctx))
+			goto err;
+
+		if (!EC_POINT_copy(*var++, base))
+			goto err;
+
+		for (j = 1; j < pre_points_per_block; j++, var++)
+			{
+			/* calculate odd multiples of the current base point */
+			if (!EC_POINT_add(group, *var, tmp_point, *(var - 1), ctx))
+				goto err;
+			}
+
+		if (i < numblocks - 1)
+			{
+			/* get the next base (multiply current one by 2^blocksize) */
+			size_t k;
+
+			if (blocksize <= 2)
+				{
+				ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_INTERNAL_ERROR);
+				goto err;
+				}				
+
+			if (!EC_POINT_dbl(group, base, tmp_point, ctx))
+				goto err;
+			for (k = 2; k < blocksize; k++)
+				{
+				if (!EC_POINT_dbl(group,base,base,ctx))
+					goto err;
+				}
+			}
+ 		}
+
+	if (!EC_POINTs_make_affine(group, num, points, ctx))
+		goto err;
+	
+	pre_comp->group = group;
+	pre_comp->blocksize = blocksize;
+	pre_comp->numblocks = numblocks;
+	pre_comp->w = w;
+	pre_comp->points = points;
+	points = NULL;
+	pre_comp->num = num;
+
+	if (!EC_EX_DATA_set_data(&group->extra_data, pre_comp,
+		ec_pre_comp_dup, ec_pre_comp_free, ec_pre_comp_clear_free))
+		goto err;
+	pre_comp = NULL;
+
+	ret = 1;
+ err:
+	if (ctx != NULL)
+		BN_CTX_end(ctx);
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	if (pre_comp)
+		ec_pre_comp_free(pre_comp);
+	if (points)
+		{
+		EC_POINT **p;
+
+		for (p = points; *p != NULL; p++)
+			EC_POINT_free(*p);
+		OPENSSL_free(points);
+		}
+	if (tmp_point)
+		EC_POINT_free(tmp_point);
+	if (base)
+		EC_POINT_free(base);
+	return ret;
+	}
+
+
+int ec_wNAF_have_precompute_mult(const EC_GROUP *group)
+	{
+	if (EC_EX_DATA_get_data(group->extra_data, ec_pre_comp_dup, ec_pre_comp_free, ec_pre_comp_clear_free) != NULL)
+		return 1;
+	else
+		return 0;
+	}
diff --git a/jni/openssl/crypto/ec/ec_oct.c b/jni/openssl/crypto/ec/ec_oct.c
new file mode 100644
index 0000000..fd9db07
--- /dev/null
+++ b/jni/openssl/crypto/ec/ec_oct.c
@@ -0,0 +1,199 @@
+/* crypto/ec/ec_lib.c */
+/*
+ * Originally written by Bodo Moeller for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2003 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.
+ * Binary polynomial ECC support in OpenSSL originally developed by 
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#include <string.h>
+
+#include <openssl/err.h>
+#include <openssl/opensslv.h>
+
+#include "ec_lcl.h"
+
+int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
+	const BIGNUM *x, int y_bit, BN_CTX *ctx)
+	{
+	if (group->meth->point_set_compressed_coordinates == 0
+		&& !(group->meth->flags & EC_FLAGS_DEFAULT_OCT))
+		{
+		ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	if (group->meth != point->meth)
+		{
+		ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+		}
+	if(group->meth->flags & EC_FLAGS_DEFAULT_OCT)
+		{
+		if (group->meth->field_type == NID_X9_62_prime_field)
+			return ec_GFp_simple_set_compressed_coordinates(
+					group, point, x, y_bit, ctx);
+		else
+#ifdef OPENSSL_NO_EC2M
+			{
+			ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, EC_R_GF2M_NOT_SUPPORTED);
+			return 0;
+			}
+#else
+			return ec_GF2m_simple_set_compressed_coordinates(
+					group, point, x, y_bit, ctx);
+#endif
+		}
+	return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx);
+	}
+
+#ifndef OPENSSL_NO_EC2M
+int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point,
+	const BIGNUM *x, int y_bit, BN_CTX *ctx)
+	{
+	if (group->meth->point_set_compressed_coordinates == 0
+		&& !(group->meth->flags & EC_FLAGS_DEFAULT_OCT))
+		{
+		ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	if (group->meth != point->meth)
+		{
+		ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+		}
+	if(group->meth->flags & EC_FLAGS_DEFAULT_OCT)
+		{
+		if (group->meth->field_type == NID_X9_62_prime_field)
+			return ec_GFp_simple_set_compressed_coordinates(
+					group, point, x, y_bit, ctx);
+		else
+			return ec_GF2m_simple_set_compressed_coordinates(
+					group, point, x, y_bit, ctx);
+		}
+	return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx);
+	}
+#endif
+
+size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
+        unsigned char *buf, size_t len, BN_CTX *ctx)
+	{
+	if (group->meth->point2oct == 0
+		&& !(group->meth->flags & EC_FLAGS_DEFAULT_OCT))
+		{
+		ECerr(EC_F_EC_POINT_POINT2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	if (group->meth != point->meth)
+		{
+		ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+		}
+	if(group->meth->flags & EC_FLAGS_DEFAULT_OCT)
+		{
+		if (group->meth->field_type == NID_X9_62_prime_field)
+			return ec_GFp_simple_point2oct(group, point,
+							form, buf, len, ctx);
+		else
+#ifdef OPENSSL_NO_EC2M
+			{
+			ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_GF2M_NOT_SUPPORTED);
+			return 0;
+			}
+#else
+			return ec_GF2m_simple_point2oct(group, point,
+							form, buf, len, ctx);
+#endif
+		}
+			
+	return group->meth->point2oct(group, point, form, buf, len, ctx);
+	}
+
+
+int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
+        const unsigned char *buf, size_t len, BN_CTX *ctx)
+	{
+	if (group->meth->oct2point == 0
+		&& !(group->meth->flags & EC_FLAGS_DEFAULT_OCT))
+		{
+		ECerr(EC_F_EC_POINT_OCT2POINT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+		}
+	if (group->meth != point->meth)
+		{
+		ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+		}
+	if(group->meth->flags & EC_FLAGS_DEFAULT_OCT)
+		{
+		if (group->meth->field_type == NID_X9_62_prime_field)
+			return ec_GFp_simple_oct2point(group, point,
+							buf, len, ctx);
+		else
+#ifdef OPENSSL_NO_EC2M
+			{
+			ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_GF2M_NOT_SUPPORTED);
+			return 0;
+			}
+#else
+			return ec_GF2m_simple_oct2point(group, point,
+							buf, len, ctx);
+#endif
+		}
+	return group->meth->oct2point(group, point, buf, len, ctx);
+	}
+
diff --git a/jni/openssl/crypto/ec/ec_pmeth.c b/jni/openssl/crypto/ec/ec_pmeth.c
new file mode 100644
index 0000000..d1ed66c
--- /dev/null
+++ b/jni/openssl/crypto/ec/ec_pmeth.c
@@ -0,0 +1,341 @@
+/* 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_ecdsa_with_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/jni/openssl/crypto/ec/ec_print.c b/jni/openssl/crypto/ec/ec_print.c
new file mode 100644
index 0000000..f7c8a30
--- /dev/null
+++ b/jni/openssl/crypto/ec/ec_print.c
@@ -0,0 +1,195 @@
+/* crypto/ec/ec_print.c */
+/* ====================================================================
+ * Copyright (c) 1998-2002 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).
+ *
+ */
+
+#include <openssl/crypto.h>
+#include "ec_lcl.h"
+
+BIGNUM *EC_POINT_point2bn(const EC_GROUP *group, 
+                          const EC_POINT *point, 
+                          point_conversion_form_t form,
+                          BIGNUM *ret,
+                          BN_CTX *ctx)
+	{
+	size_t        buf_len=0;
+	unsigned char *buf;
+
+	buf_len = EC_POINT_point2oct(group, point, form,
+                                     NULL, 0, ctx);
+	if (buf_len == 0)
+		return NULL;
+
+	if ((buf = OPENSSL_malloc(buf_len)) == NULL)
+		return NULL;
+
+	if (!EC_POINT_point2oct(group, point, form, buf, buf_len, ctx))
+		{
+		OPENSSL_free(buf);
+		return NULL;
+		}
+
+	ret = BN_bin2bn(buf, buf_len, ret);
+
+	OPENSSL_free(buf);
+
+	return ret;
+}
+
+EC_POINT *EC_POINT_bn2point(const EC_GROUP *group,
+                            const BIGNUM *bn,
+                            EC_POINT *point, 
+                            BN_CTX *ctx)
+	{
+	size_t        buf_len=0;
+	unsigned char *buf;
+	EC_POINT      *ret;
+
+	if ((buf_len = BN_num_bytes(bn)) == 0) return NULL;
+	buf = OPENSSL_malloc(buf_len);
+	if (buf == NULL)
+		return NULL;
+
+	if (!BN_bn2bin(bn, buf)) 
+		{
+		OPENSSL_free(buf);
+		return NULL;
+		}
+
+	if (point == NULL)
+		{
+		if ((ret = EC_POINT_new(group)) == NULL)
+			{
+			OPENSSL_free(buf);
+			return NULL;
+			}
+		}
+	else
+		ret = point;
+
+	if (!EC_POINT_oct2point(group, ret, buf, buf_len, ctx))
+		{
+		if (point == NULL)
+			EC_POINT_clear_free(ret);
+		OPENSSL_free(buf);
+		return NULL;
+		}
+
+	OPENSSL_free(buf);
+	return ret;
+	}
+
+static const char *HEX_DIGITS = "0123456789ABCDEF";
+
+/* the return value must be freed (using OPENSSL_free()) */
+char *EC_POINT_point2hex(const EC_GROUP *group,
+                         const EC_POINT *point,
+                         point_conversion_form_t form,
+                         BN_CTX *ctx)
+	{
+	char          *ret, *p;
+	size_t        buf_len=0,i;
+	unsigned char *buf, *pbuf;
+
+	buf_len = EC_POINT_point2oct(group, point, form,
+                                     NULL, 0, ctx);
+	if (buf_len == 0)
+		return NULL;
+
+	if ((buf = OPENSSL_malloc(buf_len)) == NULL)
+		return NULL;
+
+	if (!EC_POINT_point2oct(group, point, form, buf, buf_len, ctx))
+		{
+		OPENSSL_free(buf);
+		return NULL;
+		}
+
+	ret = (char *)OPENSSL_malloc(buf_len*2+2);
+	if (ret == NULL)
+		{
+		OPENSSL_free(buf);
+		return NULL;
+		}
+	p = ret;
+	pbuf = buf;
+	for (i=buf_len; i > 0; i--)
+		{
+			int v = (int) *(pbuf++);
+			*(p++)=HEX_DIGITS[v>>4];
+			*(p++)=HEX_DIGITS[v&0x0F];
+		}
+	*p='\0';
+
+	OPENSSL_free(buf);
+
+	return ret;
+	}
+
+EC_POINT *EC_POINT_hex2point(const EC_GROUP *group,
+                             const char *buf,
+                             EC_POINT *point,
+                             BN_CTX *ctx)
+	{
+	EC_POINT *ret=NULL;
+	BIGNUM   *tmp_bn=NULL;
+
+	if (!BN_hex2bn(&tmp_bn, buf))
+		return NULL;
+
+	ret = EC_POINT_bn2point(group, tmp_bn, point, ctx);
+
+	BN_clear_free(tmp_bn);
+
+	return ret;
+	}
diff --git a/jni/openssl/crypto/ec/eck_prn.c b/jni/openssl/crypto/ec/eck_prn.c
new file mode 100644
index 0000000..06de8f3
--- /dev/null
+++ b/jni/openssl/crypto/ec/eck_prn.c
@@ -0,0 +1,392 @@
+/* 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;
+			}
+#ifndef OPENSSL_NO_EC2M
+		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 */
+#endif
+			{
+			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/jni/openssl/crypto/ec/ecp_mont.c b/jni/openssl/crypto/ec/ecp_mont.c
new file mode 100644
index 0000000..079e474
--- /dev/null
+++ b/jni/openssl/crypto/ec/ecp_mont.c
@@ -0,0 +1,323 @@
+/* crypto/ec/ecp_mont.c */
+/*
+ * Originally written by Bodo Moeller for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2001 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 of this software developed by SUN MICROSYSTEMS, INC.,
+ * and contributed to the OpenSSL project.
+ */
+
+#include <openssl/err.h>
+
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
+#include "ec_lcl.h"
+
+
+const EC_METHOD *EC_GFp_mont_method(void)
+	{
+#ifdef OPENSSL_FIPS
+	return fips_ec_gfp_mont_method();
+#else
+	static const EC_METHOD ret = {
+		EC_FLAGS_DEFAULT_OCT,
+		NID_X9_62_prime_field,
+		ec_GFp_mont_group_init,
+		ec_GFp_mont_group_finish,
+		ec_GFp_mont_group_clear_finish,
+		ec_GFp_mont_group_copy,
+		ec_GFp_mont_group_set_curve,
+		ec_GFp_simple_group_get_curve,
+		ec_GFp_simple_group_get_degree,
+		ec_GFp_simple_group_check_discriminant,
+		ec_GFp_simple_point_init,
+		ec_GFp_simple_point_finish,
+		ec_GFp_simple_point_clear_finish,
+		ec_GFp_simple_point_copy,
+		ec_GFp_simple_point_set_to_infinity,
+		ec_GFp_simple_set_Jprojective_coordinates_GFp,
+		ec_GFp_simple_get_Jprojective_coordinates_GFp,
+		ec_GFp_simple_point_set_affine_coordinates,
+		ec_GFp_simple_point_get_affine_coordinates,
+		0,0,0,
+		ec_GFp_simple_add,
+		ec_GFp_simple_dbl,
+		ec_GFp_simple_invert,
+		ec_GFp_simple_is_at_infinity,
+		ec_GFp_simple_is_on_curve,
+		ec_GFp_simple_cmp,
+		ec_GFp_simple_make_affine,
+		ec_GFp_simple_points_make_affine,
+		0 /* mul */,
+		0 /* precompute_mult */,
+		0 /* have_precompute_mult */,	
+		ec_GFp_mont_field_mul,
+		ec_GFp_mont_field_sqr,
+		0 /* field_div */,
+		ec_GFp_mont_field_encode,
+		ec_GFp_mont_field_decode,
+		ec_GFp_mont_field_set_to_one };
+
+
+	return &ret;
+#endif
+	}
+
+
+int ec_GFp_mont_group_init(EC_GROUP *group)
+	{
+	int ok;
+
+	ok = ec_GFp_simple_group_init(group);
+	group->field_data1 = NULL;
+	group->field_data2 = NULL;
+	return ok;
+	}
+
+
+void ec_GFp_mont_group_finish(EC_GROUP *group)
+	{
+	if (group->field_data1 != NULL)
+		{
+		BN_MONT_CTX_free(group->field_data1);
+		group->field_data1 = NULL;
+		}
+	if (group->field_data2 != NULL)
+		{
+		BN_free(group->field_data2);
+		group->field_data2 = NULL;
+		}
+	ec_GFp_simple_group_finish(group);
+	}
+
+
+void ec_GFp_mont_group_clear_finish(EC_GROUP *group)
+	{
+	if (group->field_data1 != NULL)
+		{
+		BN_MONT_CTX_free(group->field_data1);
+		group->field_data1 = NULL;
+		}
+	if (group->field_data2 != NULL)
+		{
+		BN_clear_free(group->field_data2);
+		group->field_data2 = NULL;
+		}
+	ec_GFp_simple_group_clear_finish(group);
+	}
+
+
+int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src)
+	{
+	if (dest->field_data1 != NULL)
+		{
+		BN_MONT_CTX_free(dest->field_data1);
+		dest->field_data1 = NULL;
+		}
+	if (dest->field_data2 != NULL)
+		{
+		BN_clear_free(dest->field_data2);
+		dest->field_data2 = NULL;
+		}
+
+	if (!ec_GFp_simple_group_copy(dest, src)) return 0;
+
+	if (src->field_data1 != NULL)
+		{
+		dest->field_data1 = BN_MONT_CTX_new();
+		if (dest->field_data1 == NULL) return 0;
+		if (!BN_MONT_CTX_copy(dest->field_data1, src->field_data1)) goto err;
+		}
+	if (src->field_data2 != NULL)
+		{
+		dest->field_data2 = BN_dup(src->field_data2);
+		if (dest->field_data2 == NULL) goto err;
+		}
+
+	return 1;
+
+ err:
+	if (dest->field_data1 != NULL)
+		{
+		BN_MONT_CTX_free(dest->field_data1);
+		dest->field_data1 = NULL;
+		}
+	return 0;	
+	}
+
+
+int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
+	{
+	BN_CTX *new_ctx = NULL;
+	BN_MONT_CTX *mont = NULL;
+	BIGNUM *one = NULL;
+	int ret = 0;
+
+	if (group->field_data1 != NULL)
+		{
+		BN_MONT_CTX_free(group->field_data1);
+		group->field_data1 = NULL;
+		}
+	if (group->field_data2 != NULL)
+		{
+		BN_free(group->field_data2);
+		group->field_data2 = NULL;
+		}
+	
+	if (ctx == NULL)
+		{
+		ctx = new_ctx = BN_CTX_new();
+		if (ctx == NULL)
+			return 0;
+		}
+
+	mont = BN_MONT_CTX_new();
+	if (mont == NULL) goto err;
+	if (!BN_MONT_CTX_set(mont, p, ctx))
+		{
+		ECerr(EC_F_EC_GFP_MONT_GROUP_SET_CURVE, ERR_R_BN_LIB);
+		goto err;
+		}
+	one = BN_new();
+	if (one == NULL) goto err;
+	if (!BN_to_montgomery(one, BN_value_one(), mont, ctx)) goto err;
+
+	group->field_data1 = mont;
+	mont = NULL;
+	group->field_data2 = one;
+	one = NULL;
+
+	ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
+
+	if (!ret)
+		{
+		BN_MONT_CTX_free(group->field_data1);
+		group->field_data1 = NULL;
+		BN_free(group->field_data2);
+		group->field_data2 = NULL;
+		}
+
+ err:
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	if (mont != NULL)
+		BN_MONT_CTX_free(mont);
+	return ret;
+	}
+
+
+int ec_GFp_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
+	{
+	if (group->field_data1 == NULL)
+		{
+		ECerr(EC_F_EC_GFP_MONT_FIELD_MUL, EC_R_NOT_INITIALIZED);
+		return 0;
+		}
+
+	return BN_mod_mul_montgomery(r, a, b, group->field_data1, ctx);
+	}
+
+
+int ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
+	{
+	if (group->field_data1 == NULL)
+		{
+		ECerr(EC_F_EC_GFP_MONT_FIELD_SQR, EC_R_NOT_INITIALIZED);
+		return 0;
+		}
+
+	return BN_mod_mul_montgomery(r, a, a, group->field_data1, ctx);
+	}
+
+
+int ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
+	{
+	if (group->field_data1 == NULL)
+		{
+		ECerr(EC_F_EC_GFP_MONT_FIELD_ENCODE, EC_R_NOT_INITIALIZED);
+		return 0;
+		}
+
+	return BN_to_montgomery(r, a, (BN_MONT_CTX *)group->field_data1, ctx);
+	}
+
+
+int ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
+	{
+	if (group->field_data1 == NULL)
+		{
+		ECerr(EC_F_EC_GFP_MONT_FIELD_DECODE, EC_R_NOT_INITIALIZED);
+		return 0;
+		}
+
+	return BN_from_montgomery(r, a, group->field_data1, ctx);
+	}
+
+
+int ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r, BN_CTX *ctx)
+	{
+	if (group->field_data2 == NULL)
+		{
+		ECerr(EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE, EC_R_NOT_INITIALIZED);
+		return 0;
+		}
+
+	if (!BN_copy(r, group->field_data2)) return 0;
+	return 1;
+	}
diff --git a/jni/openssl/crypto/ec/ecp_nist.c b/jni/openssl/crypto/ec/ecp_nist.c
new file mode 100644
index 0000000..aad2d5f
--- /dev/null
+++ b/jni/openssl/crypto/ec/ecp_nist.c
@@ -0,0 +1,217 @@
+/* crypto/ec/ecp_nist.c */
+/*
+ * Written by Nils Larsch for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2003 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 of this software developed by SUN MICROSYSTEMS, INC.,
+ * and contributed to the OpenSSL project.
+ */
+
+#include <limits.h>
+
+#include <openssl/err.h>
+#include <openssl/obj_mac.h>
+#include "ec_lcl.h"
+
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
+const EC_METHOD *EC_GFp_nist_method(void)
+	{
+#ifdef OPENSSL_FIPS
+	return fips_ec_gfp_nist_method();
+#else
+	static const EC_METHOD ret = {
+		EC_FLAGS_DEFAULT_OCT,
+		NID_X9_62_prime_field,
+		ec_GFp_simple_group_init,
+		ec_GFp_simple_group_finish,
+		ec_GFp_simple_group_clear_finish,
+		ec_GFp_nist_group_copy,
+		ec_GFp_nist_group_set_curve,
+		ec_GFp_simple_group_get_curve,
+		ec_GFp_simple_group_get_degree,
+		ec_GFp_simple_group_check_discriminant,
+		ec_GFp_simple_point_init,
+		ec_GFp_simple_point_finish,
+		ec_GFp_simple_point_clear_finish,
+		ec_GFp_simple_point_copy,
+		ec_GFp_simple_point_set_to_infinity,
+		ec_GFp_simple_set_Jprojective_coordinates_GFp,
+		ec_GFp_simple_get_Jprojective_coordinates_GFp,
+		ec_GFp_simple_point_set_affine_coordinates,
+		ec_GFp_simple_point_get_affine_coordinates,
+		0,0,0,
+		ec_GFp_simple_add,
+		ec_GFp_simple_dbl,
+		ec_GFp_simple_invert,
+		ec_GFp_simple_is_at_infinity,
+		ec_GFp_simple_is_on_curve,
+		ec_GFp_simple_cmp,
+		ec_GFp_simple_make_affine,
+		ec_GFp_simple_points_make_affine,
+		0 /* mul */,
+		0 /* precompute_mult */,
+		0 /* have_precompute_mult */,	
+		ec_GFp_nist_field_mul,
+		ec_GFp_nist_field_sqr,
+		0 /* field_div */,
+		0 /* field_encode */,
+		0 /* field_decode */,
+		0 /* field_set_to_one */ };
+
+	return &ret;
+#endif
+	}
+
+int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src)
+	{
+	dest->field_mod_func = src->field_mod_func;
+
+	return ec_GFp_simple_group_copy(dest, src);
+	}
+
+int ec_GFp_nist_group_set_curve(EC_GROUP *group, const BIGNUM *p,
+	const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
+	{
+	int ret = 0;
+	BN_CTX *new_ctx = NULL;
+	BIGNUM *tmp_bn;
+	
+	if (ctx == NULL)
+		if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0;
+
+	BN_CTX_start(ctx);
+	if ((tmp_bn = BN_CTX_get(ctx)) == NULL) goto err;
+
+	if (BN_ucmp(BN_get0_nist_prime_192(), p) == 0)
+		group->field_mod_func = BN_nist_mod_192;
+	else if (BN_ucmp(BN_get0_nist_prime_224(), p) == 0)
+		group->field_mod_func = BN_nist_mod_224;
+	else if (BN_ucmp(BN_get0_nist_prime_256(), p) == 0)
+		group->field_mod_func = BN_nist_mod_256;
+	else if (BN_ucmp(BN_get0_nist_prime_384(), p) == 0)
+		group->field_mod_func = BN_nist_mod_384;
+	else if (BN_ucmp(BN_get0_nist_prime_521(), p) == 0)
+		group->field_mod_func = BN_nist_mod_521;
+	else
+		{
+		ECerr(EC_F_EC_GFP_NIST_GROUP_SET_CURVE, EC_R_NOT_A_NIST_PRIME);
+		goto err;
+		}
+
+	ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
+
+ err:
+	BN_CTX_end(ctx);
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	return ret;
+	}
+
+
+int ec_GFp_nist_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
+	const BIGNUM *b, BN_CTX *ctx)
+	{
+	int	ret=0;
+	BN_CTX	*ctx_new=NULL;
+
+	if (!group || !r || !a || !b)
+		{
+		ECerr(EC_F_EC_GFP_NIST_FIELD_MUL, ERR_R_PASSED_NULL_PARAMETER);
+		goto err;
+		}
+	if (!ctx)
+		if ((ctx_new = ctx = BN_CTX_new()) == NULL) goto err;
+
+	if (!BN_mul(r, a, b, ctx)) goto err;
+	if (!group->field_mod_func(r, r, &group->field, ctx))
+		goto err;
+
+	ret=1;
+err:
+	if (ctx_new)
+		BN_CTX_free(ctx_new);
+	return ret;
+	}
+
+
+int ec_GFp_nist_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
+	BN_CTX *ctx)
+	{
+	int	ret=0;
+	BN_CTX	*ctx_new=NULL;
+
+	if (!group || !r || !a)
+		{
+		ECerr(EC_F_EC_GFP_NIST_FIELD_SQR, EC_R_PASSED_NULL_PARAMETER);
+		goto err;
+		}
+	if (!ctx)
+		if ((ctx_new = ctx = BN_CTX_new()) == NULL) goto err;
+
+	if (!BN_sqr(r, a, ctx)) goto err;
+	if (!group->field_mod_func(r, r, &group->field, ctx))
+		goto err;
+
+	ret=1;
+err:
+	if (ctx_new)
+		BN_CTX_free(ctx_new);
+	return ret;
+	}
diff --git a/jni/openssl/crypto/ec/ecp_oct.c b/jni/openssl/crypto/ec/ecp_oct.c
new file mode 100644
index 0000000..374a0ee
--- /dev/null
+++ b/jni/openssl/crypto/ec/ecp_oct.c
@@ -0,0 +1,433 @@
+/* crypto/ec/ecp_oct.c */
+/* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de>
+ * for the OpenSSL project. 
+ * Includes code written by Bodo Moeller for the OpenSSL project.
+*/
+/* ====================================================================
+ * Copyright (c) 1998-2002 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 of this software developed by SUN MICROSYSTEMS, INC.,
+ * and contributed to the OpenSSL project.
+ */
+
+#include <openssl/err.h>
+#include <openssl/symhacks.h>
+
+#include "ec_lcl.h"
+
+int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
+	const BIGNUM *x_, int y_bit, BN_CTX *ctx)
+	{
+	BN_CTX *new_ctx = NULL;
+	BIGNUM *tmp1, *tmp2, *x, *y;
+	int ret = 0;
+
+	/* clear error queue*/
+	ERR_clear_error();
+
+	if (ctx == NULL)
+		{
+		ctx = new_ctx = BN_CTX_new();
+		if (ctx == NULL)
+			return 0;
+		}
+
+	y_bit = (y_bit != 0);
+
+	BN_CTX_start(ctx);
+	tmp1 = BN_CTX_get(ctx);
+	tmp2 = BN_CTX_get(ctx);
+	x = BN_CTX_get(ctx);
+	y = BN_CTX_get(ctx);
+	if (y == NULL) goto err;
+
+	/* Recover y.  We have a Weierstrass equation
+	 *     y^2 = x^3 + a*x + b,
+	 * so  y  is one of the square roots of  x^3 + a*x + b.
+	 */
+
+	/* tmp1 := x^3 */
+	if (!BN_nnmod(x, x_, &group->field,ctx)) goto err;
+	if (group->meth->field_decode == 0)
+		{
+		/* field_{sqr,mul} work on standard representation */
+		if (!group->meth->field_sqr(group, tmp2, x_, ctx)) goto err;
+		if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx)) goto err;
+		}
+	else
+		{
+		if (!BN_mod_sqr(tmp2, x_, &group->field, ctx)) goto err;
+		if (!BN_mod_mul(tmp1, tmp2, x_, &group->field, ctx)) goto err;
+		}
+	
+	/* tmp1 := tmp1 + a*x */
+	if (group->a_is_minus3)
+		{
+		if (!BN_mod_lshift1_quick(tmp2, x, &group->field)) goto err;
+		if (!BN_mod_add_quick(tmp2, tmp2, x, &group->field)) goto err;
+		if (!BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
+		}
+	else
+		{
+		if (group->meth->field_decode)
+			{
+			if (!group->meth->field_decode(group, tmp2, &group->a, ctx)) goto err;
+			if (!BN_mod_mul(tmp2, tmp2, x, &group->field, ctx)) goto err;
+			}
+		else
+			{
+			/* field_mul works on standard representation */
+			if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx)) goto err;
+			}
+		
+		if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
+		}
+	
+	/* tmp1 := tmp1 + b */
+	if (group->meth->field_decode)
+		{
+		if (!group->meth->field_decode(group, tmp2, &group->b, ctx)) goto err;
+		if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
+		}
+	else
+		{
+		if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field)) goto err;
+		}
+	
+	if (!BN_mod_sqrt(y, tmp1, &group->field, ctx))
+		{
+		unsigned long err = ERR_peek_last_error();
+		
+		if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE)
+			{
+			ERR_clear_error();
+			ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
+			}
+		else
+			ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
+		goto err;
+		}
+
+	if (y_bit != BN_is_odd(y))
+		{
+		if (BN_is_zero(y))
+			{
+			int kron;
+
+			kron = BN_kronecker(x, &group->field, ctx);
+			if (kron == -2) goto err;
+
+			if (kron == 1)
+				ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSION_BIT);
+			else
+				/* BN_mod_sqrt() should have cought this error (not a square) */
+				ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
+			goto err;
+			}
+		if (!BN_usub(y, &group->field, y)) goto err;
+		}
+	if (y_bit != BN_is_odd(y))
+		{
+		ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_INTERNAL_ERROR);
+		goto err;
+		}
+
+	if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	return ret;
+	}
+
+
+size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
+	unsigned char *buf, size_t len, BN_CTX *ctx)
+	{
+	size_t ret;
+	BN_CTX *new_ctx = NULL;
+	int used_ctx = 0;
+	BIGNUM *x, *y;
+	size_t field_len, i, skip;
+
+	if ((form != POINT_CONVERSION_COMPRESSED)
+		&& (form != POINT_CONVERSION_UNCOMPRESSED)
+		&& (form != POINT_CONVERSION_HYBRID))
+		{
+		ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
+		goto err;
+		}
+
+	if (EC_POINT_is_at_infinity(group, point))
+		{
+		/* encodes to a single 0 octet */
+		if (buf != NULL)
+			{
+			if (len < 1)
+				{
+				ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
+				return 0;
+				}
+			buf[0] = 0;
+			}
+		return 1;
+		}
+
+
+	/* ret := required output buffer length */
+	field_len = BN_num_bytes(&group->field);
+	ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
+
+	/* if 'buf' is NULL, just return required length */
+	if (buf != NULL)
+		{
+		if (len < ret)
+			{
+			ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
+			goto err;
+			}
+
+		if (ctx == NULL)
+			{
+			ctx = new_ctx = BN_CTX_new();
+			if (ctx == NULL)
+				return 0;
+			}
+
+		BN_CTX_start(ctx);
+		used_ctx = 1;
+		x = BN_CTX_get(ctx);
+		y = BN_CTX_get(ctx);
+		if (y == NULL) goto err;
+
+		if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
+
+		if ((form == POINT_CONVERSION_COMPRESSED || form == POINT_CONVERSION_HYBRID) && BN_is_odd(y))
+			buf[0] = form + 1;
+		else
+			buf[0] = form;
+	
+		i = 1;
+		
+		skip = field_len - BN_num_bytes(x);
+		if (skip > field_len)
+			{
+			ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
+			goto err;
+			}
+		while (skip > 0)
+			{
+			buf[i++] = 0;
+			skip--;
+			}
+		skip = BN_bn2bin(x, buf + i);
+		i += skip;
+		if (i != 1 + field_len)
+			{
+			ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
+			goto err;
+			}
+
+		if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
+			{
+			skip = field_len - BN_num_bytes(y);
+			if (skip > field_len)
+				{
+				ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
+				goto err;
+				}
+			while (skip > 0)
+				{
+				buf[i++] = 0;
+				skip--;
+				}
+			skip = BN_bn2bin(y, buf + i);
+			i += skip;
+			}
+
+		if (i != ret)
+			{
+			ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
+			goto err;
+			}
+		}
+	
+	if (used_ctx)
+		BN_CTX_end(ctx);
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	return ret;
+
+ err:
+	if (used_ctx)
+		BN_CTX_end(ctx);
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	return 0;
+	}
+
+
+int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
+	const unsigned char *buf, size_t len, BN_CTX *ctx)
+	{
+	point_conversion_form_t form;
+	int y_bit;
+	BN_CTX *new_ctx = NULL;
+	BIGNUM *x, *y;
+	size_t field_len, enc_len;
+	int ret = 0;
+
+	if (len == 0)
+		{
+		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
+		return 0;
+		}
+	form = buf[0];
+	y_bit = form & 1;
+	form = form & ~1U;
+	if ((form != 0)	&& (form != POINT_CONVERSION_COMPRESSED)
+		&& (form != POINT_CONVERSION_UNCOMPRESSED)
+		&& (form != POINT_CONVERSION_HYBRID))
+		{
+		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+		return 0;
+		}
+	if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
+		{
+		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+		return 0;
+		}
+
+	if (form == 0)
+		{
+		if (len != 1)
+			{
+			ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+			return 0;
+			}
+
+		return EC_POINT_set_to_infinity(group, point);
+		}
+	
+	field_len = BN_num_bytes(&group->field);
+	enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
+
+	if (len != enc_len)
+		{
+		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+		return 0;
+		}
+
+	if (ctx == NULL)
+		{
+		ctx = new_ctx = BN_CTX_new();
+		if (ctx == NULL)
+			return 0;
+		}
+
+	BN_CTX_start(ctx);
+	x = BN_CTX_get(ctx);
+	y = BN_CTX_get(ctx);
+	if (y == NULL) goto err;
+
+	if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
+	if (BN_ucmp(x, &group->field) >= 0)
+		{
+		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+		goto err;
+		}
+
+	if (form == POINT_CONVERSION_COMPRESSED)
+		{
+		if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx)) goto err;
+		}
+	else
+		{
+		if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
+		if (BN_ucmp(y, &group->field) >= 0)
+			{
+			ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+			goto err;
+			}
+		if (form == POINT_CONVERSION_HYBRID)
+			{
+			if (y_bit != BN_is_odd(y))
+				{
+				ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+				goto err;
+				}
+			}
+
+		if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
+		}
+	
+	if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
+		{
+		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
+		goto err;
+		}
+
+	ret = 1;
+	
+ err:
+	BN_CTX_end(ctx);
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	return ret;
+	}
+
diff --git a/jni/openssl/crypto/ec/ecp_smpl.c b/jni/openssl/crypto/ec/ecp_smpl.c
new file mode 100644
index 0000000..7cbb321
--- /dev/null
+++ b/jni/openssl/crypto/ec/ecp_smpl.c
@@ -0,0 +1,1360 @@
+/* crypto/ec/ecp_smpl.c */
+/* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de>
+ * for the OpenSSL project. 
+ * Includes code written by Bodo Moeller for the OpenSSL project.
+*/
+/* ====================================================================
+ * Copyright (c) 1998-2002 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 of this software developed by SUN MICROSYSTEMS, INC.,
+ * and contributed to the OpenSSL project.
+ */
+
+#include <openssl/err.h>
+#include <openssl/symhacks.h>
+
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
+#include "ec_lcl.h"
+
+const EC_METHOD *EC_GFp_simple_method(void)
+	{
+#ifdef OPENSSL_FIPS
+	return fips_ec_gfp_simple_method();
+#else
+	static const EC_METHOD ret = {
+		EC_FLAGS_DEFAULT_OCT,
+		NID_X9_62_prime_field,
+		ec_GFp_simple_group_init,
+		ec_GFp_simple_group_finish,
+		ec_GFp_simple_group_clear_finish,
+		ec_GFp_simple_group_copy,
+		ec_GFp_simple_group_set_curve,
+		ec_GFp_simple_group_get_curve,
+		ec_GFp_simple_group_get_degree,
+		ec_GFp_simple_group_check_discriminant,
+		ec_GFp_simple_point_init,
+		ec_GFp_simple_point_finish,
+		ec_GFp_simple_point_clear_finish,
+		ec_GFp_simple_point_copy,
+		ec_GFp_simple_point_set_to_infinity,
+		ec_GFp_simple_set_Jprojective_coordinates_GFp,
+		ec_GFp_simple_get_Jprojective_coordinates_GFp,
+		ec_GFp_simple_point_set_affine_coordinates,
+		ec_GFp_simple_point_get_affine_coordinates,
+		0,0,0,
+		ec_GFp_simple_add,
+		ec_GFp_simple_dbl,
+		ec_GFp_simple_invert,
+		ec_GFp_simple_is_at_infinity,
+		ec_GFp_simple_is_on_curve,
+		ec_GFp_simple_cmp,
+		ec_GFp_simple_make_affine,
+		ec_GFp_simple_points_make_affine,
+		0 /* mul */,
+		0 /* precompute_mult */,
+		0 /* have_precompute_mult */,	
+		ec_GFp_simple_field_mul,
+		ec_GFp_simple_field_sqr,
+		0 /* field_div */,
+		0 /* field_encode */,
+		0 /* field_decode */,
+		0 /* field_set_to_one */ };
+
+	return &ret;
+#endif
+	}
+
+
+/* Most method functions in this file are designed to work with
+ * non-trivial representations of field elements if necessary
+ * (see ecp_mont.c): while standard modular addition and subtraction
+ * are used, the field_mul and field_sqr methods will be used for
+ * multiplication, and field_encode and field_decode (if defined)
+ * will be used for converting between representations.
+
+ * Functions ec_GFp_simple_points_make_affine() and
+ * ec_GFp_simple_point_get_affine_coordinates() specifically assume
+ * that if a non-trivial representation is used, it is a Montgomery
+ * representation (i.e. 'encoding' means multiplying by some factor R).
+ */
+
+
+int ec_GFp_simple_group_init(EC_GROUP *group)
+	{
+	BN_init(&group->field);
+	BN_init(&group->a);
+	BN_init(&group->b);
+	group->a_is_minus3 = 0;
+	return 1;
+	}
+
+
+void ec_GFp_simple_group_finish(EC_GROUP *group)
+	{
+	BN_free(&group->field);
+	BN_free(&group->a);
+	BN_free(&group->b);
+	}
+
+
+void ec_GFp_simple_group_clear_finish(EC_GROUP *group)
+	{
+	BN_clear_free(&group->field);
+	BN_clear_free(&group->a);
+	BN_clear_free(&group->b);
+	}
+
+
+int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
+	{
+	if (!BN_copy(&dest->field, &src->field)) return 0;
+	if (!BN_copy(&dest->a, &src->a)) return 0;
+	if (!BN_copy(&dest->b, &src->b)) return 0;
+
+	dest->a_is_minus3 = src->a_is_minus3;
+
+	return 1;
+	}
+
+
+int ec_GFp_simple_group_set_curve(EC_GROUP *group,
+	const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
+	{
+	int ret = 0;
+	BN_CTX *new_ctx = NULL;
+	BIGNUM *tmp_a;
+	
+	/* p must be a prime > 3 */
+	if (BN_num_bits(p) <= 2 || !BN_is_odd(p))
+		{
+		ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, EC_R_INVALID_FIELD);
+		return 0;
+		}
+
+	if (ctx == NULL)
+		{
+		ctx = new_ctx = BN_CTX_new();
+		if (ctx == NULL)
+			return 0;
+		}
+
+	BN_CTX_start(ctx);
+	tmp_a = BN_CTX_get(ctx);
+	if (tmp_a == NULL) goto err;
+
+	/* group->field */
+	if (!BN_copy(&group->field, p)) goto err;
+	BN_set_negative(&group->field, 0);
+
+	/* group->a */
+	if (!BN_nnmod(tmp_a, a, p, ctx)) goto err;
+	if (group->meth->field_encode)
+		{ if (!group->meth->field_encode(group, &group->a, tmp_a, ctx)) goto err; }	
+	else
+		if (!BN_copy(&group->a, tmp_a)) goto err;
+	
+	/* group->b */
+	if (!BN_nnmod(&group->b, b, p, ctx)) goto err;
+	if (group->meth->field_encode)
+		if (!group->meth->field_encode(group, &group->b, &group->b, ctx)) goto err;
+	
+	/* group->a_is_minus3 */
+	if (!BN_add_word(tmp_a, 3)) goto err;
+	group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field));
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	return ret;
+	}
+
+
+int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
+	{
+	int ret = 0;
+	BN_CTX *new_ctx = NULL;
+	
+	if (p != NULL)
+		{
+		if (!BN_copy(p, &group->field)) return 0;
+		}
+
+	if (a != NULL || b != NULL)
+		{
+		if (group->meth->field_decode)
+			{
+			if (ctx == NULL)
+				{
+				ctx = new_ctx = BN_CTX_new();
+				if (ctx == NULL)
+					return 0;
+				}
+			if (a != NULL)
+				{
+				if (!group->meth->field_decode(group, a, &group->a, ctx)) goto err;
+				}
+			if (b != NULL)
+				{
+				if (!group->meth->field_decode(group, b, &group->b, ctx)) goto err;
+				}
+			}
+		else
+			{
+			if (a != NULL)
+				{
+				if (!BN_copy(a, &group->a)) goto err;
+				}
+			if (b != NULL)
+				{
+				if (!BN_copy(b, &group->b)) goto err;
+				}
+			}
+		}
+	
+	ret = 1;
+	
+ err:
+	if (new_ctx)
+		BN_CTX_free(new_ctx);
+	return ret;
+	}
+
+
+int ec_GFp_simple_group_get_degree(const EC_GROUP *group)
+	{
+	return BN_num_bits(&group->field);
+	}
+
+
+int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
+	{
+	int ret = 0;
+	BIGNUM *a,*b,*order,*tmp_1,*tmp_2;
+	const BIGNUM *p = &group->field;
+	BN_CTX *new_ctx = NULL;
+
+	if (ctx == NULL)
+		{
+		ctx = new_ctx = BN_CTX_new();
+		if (ctx == NULL)
+			{
+			ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT, ERR_R_MALLOC_FAILURE);
+			goto err;
+			}
+		}
+	BN_CTX_start(ctx);
+	a = BN_CTX_get(ctx);
+	b = BN_CTX_get(ctx);
+	tmp_1 = BN_CTX_get(ctx);
+	tmp_2 = BN_CTX_get(ctx);
+	order = BN_CTX_get(ctx);
+	if (order == NULL) goto err;
+
+	if (group->meth->field_decode)
+		{
+		if (!group->meth->field_decode(group, a, &group->a, ctx)) goto err;
+		if (!group->meth->field_decode(group, b, &group->b, ctx)) goto err;
+		}
+	else
+		{
+		if (!BN_copy(a, &group->a)) goto err;
+		if (!BN_copy(b, &group->b)) goto err;
+		}
+	
+	/* check the discriminant:
+	 * y^2 = x^3 + a*x + b is an elliptic curve <=> 4*a^3 + 27*b^2 != 0 (mod p) 
+         * 0 =< a, b < p */
+	if (BN_is_zero(a))
+		{
+		if (BN_is_zero(b)) goto err;
+		}
+	else if (!BN_is_zero(b))
+		{
+		if (!BN_mod_sqr(tmp_1, a, p, ctx)) goto err;
+		if (!BN_mod_mul(tmp_2, tmp_1, a, p, ctx)) goto err;
+		if (!BN_lshift(tmp_1, tmp_2, 2)) goto err;
+		/* tmp_1 = 4*a^3 */
+
+		if (!BN_mod_sqr(tmp_2, b, p, ctx)) goto err;
+		if (!BN_mul_word(tmp_2, 27)) goto err;
+		/* tmp_2 = 27*b^2 */
+
+		if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx)) goto err;
+		if (BN_is_zero(a)) goto err;
+		}
+	ret = 1;
+
+err:
+	if (ctx != NULL)
+		BN_CTX_end(ctx);
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	return ret;
+	}
+
+
+int ec_GFp_simple_point_init(EC_POINT *point)
+	{
+	BN_init(&point->X);
+	BN_init(&point->Y);
+	BN_init(&point->Z);
+	point->Z_is_one = 0;
+
+	return 1;
+	}
+
+
+void ec_GFp_simple_point_finish(EC_POINT *point)
+	{
+	BN_free(&point->X);
+	BN_free(&point->Y);
+	BN_free(&point->Z);
+	}
+
+
+void ec_GFp_simple_point_clear_finish(EC_POINT *point)
+	{
+	BN_clear_free(&point->X);
+	BN_clear_free(&point->Y);
+	BN_clear_free(&point->Z);
+	point->Z_is_one = 0;
+	}
+
+
+int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
+	{
+	if (!BN_copy(&dest->X, &src->X)) return 0;
+	if (!BN_copy(&dest->Y, &src->Y)) return 0;
+	if (!BN_copy(&dest->Z, &src->Z)) return 0;
+	dest->Z_is_one = src->Z_is_one;
+
+	return 1;
+	}
+
+
+int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
+	{
+	point->Z_is_one = 0;
+	BN_zero(&point->Z);
+	return 1;
+	}
+
+
+int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
+	const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx)
+	{
+	BN_CTX *new_ctx = NULL;
+	int ret = 0;
+	
+	if (ctx == NULL)
+		{
+		ctx = new_ctx = BN_CTX_new();
+		if (ctx == NULL)
+			return 0;
+		}
+
+	if (x != NULL)
+		{
+		if (!BN_nnmod(&point->X, x, &group->field, ctx)) goto err;
+		if (group->meth->field_encode)
+			{
+			if (!group->meth->field_encode(group, &point->X, &point->X, ctx)) goto err;
+			}
+		}
+	
+	if (y != NULL)
+		{
+		if (!BN_nnmod(&point->Y, y, &group->field, ctx)) goto err;
+		if (group->meth->field_encode)
+			{
+			if (!group->meth->field_encode(group, &point->Y, &point->Y, ctx)) goto err;
+			}
+		}
+	
+	if (z != NULL)
+		{
+		int Z_is_one;
+
+		if (!BN_nnmod(&point->Z, z, &group->field, ctx)) goto err;
+		Z_is_one = BN_is_one(&point->Z);
+		if (group->meth->field_encode)
+			{
+			if (Z_is_one && (group->meth->field_set_to_one != 0))
+				{
+				if (!group->meth->field_set_to_one(group, &point->Z, ctx)) goto err;
+				}
+			else
+				{
+				if (!group->meth->field_encode(group, &point->Z, &point->Z, ctx)) goto err;
+				}
+			}
+		point->Z_is_one = Z_is_one;
+		}
+	
+	ret = 1;
+	
+ err:
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	return ret;
+	}
+
+
+int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
+	BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx)
+	{
+	BN_CTX *new_ctx = NULL;
+	int ret = 0;
+	
+	if (group->meth->field_decode != 0)
+		{
+		if (ctx == NULL)
+			{
+			ctx = new_ctx = BN_CTX_new();
+			if (ctx == NULL)
+				return 0;
+			}
+
+		if (x != NULL)
+			{
+			if (!group->meth->field_decode(group, x, &point->X, ctx)) goto err;
+			}
+		if (y != NULL)
+			{
+			if (!group->meth->field_decode(group, y, &point->Y, ctx)) goto err;
+			}
+		if (z != NULL)
+			{
+			if (!group->meth->field_decode(group, z, &point->Z, ctx)) goto err;
+			}
+		}
+	else	
+		{
+		if (x != NULL)
+			{
+			if (!BN_copy(x, &point->X)) goto err;
+			}
+		if (y != NULL)
+			{
+			if (!BN_copy(y, &point->Y)) goto err;
+			}
+		if (z != NULL)
+			{
+			if (!BN_copy(z, &point->Z)) goto err;
+			}
+		}
+	
+	ret = 1;
+
+ err:
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	return ret;
+	}
+
+
+int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
+	const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
+	{
+	if (x == NULL || y == NULL)
+		{
+		/* unlike for projective coordinates, we do not tolerate this */
+		ECerr(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER);
+		return 0;
+		}
+
+	return EC_POINT_set_Jprojective_coordinates_GFp(group, point, x, y, BN_value_one(), ctx);
+	}
+
+
+int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point,
+	BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
+	{
+	BN_CTX *new_ctx = NULL;
+	BIGNUM *Z, *Z_1, *Z_2, *Z_3;
+	const BIGNUM *Z_;
+	int ret = 0;
+
+	if (EC_POINT_is_at_infinity(group, point))
+		{
+		ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY);
+		return 0;
+		}
+
+	if (ctx == NULL)
+		{
+		ctx = new_ctx = BN_CTX_new();
+		if (ctx == NULL)
+			return 0;
+		}
+
+	BN_CTX_start(ctx);
+	Z = BN_CTX_get(ctx);
+	Z_1 = BN_CTX_get(ctx);
+	Z_2 = BN_CTX_get(ctx);
+	Z_3 = BN_CTX_get(ctx);
+	if (Z_3 == NULL) goto err;
+
+	/* transform  (X, Y, Z)  into  (x, y) := (X/Z^2, Y/Z^3) */
+	
+	if (group->meth->field_decode)
+		{
+		if (!group->meth->field_decode(group, Z, &point->Z, ctx)) goto err;
+		Z_ = Z;
+		}
+	else
+		{
+		Z_ = &point->Z;
+		}
+	
+	if (BN_is_one(Z_))
+		{
+		if (group->meth->field_decode)
+			{
+			if (x != NULL)
+				{
+				if (!group->meth->field_decode(group, x, &point->X, ctx)) goto err;
+				}
+			if (y != NULL)
+				{
+				if (!group->meth->field_decode(group, y, &point->Y, ctx)) goto err;
+				}
+			}
+		else
+			{
+			if (x != NULL)
+				{
+				if (!BN_copy(x, &point->X)) goto err;
+				}
+			if (y != NULL)
+				{
+				if (!BN_copy(y, &point->Y)) goto err;
+				}
+			}
+		}
+	else
+		{
+		if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx))
+			{
+			ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_BN_LIB);
+			goto err;
+			}
+		
+		if (group->meth->field_encode == 0)
+			{
+			/* field_sqr works on standard representation */
+			if (!group->meth->field_sqr(group, Z_2, Z_1, ctx)) goto err;
+			}
+		else
+			{
+			if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) goto err;
+			}
+	
+		if (x != NULL)
+			{
+			/* in the Montgomery case, field_mul will cancel out Montgomery factor in X: */
+			if (!group->meth->field_mul(group, x, &point->X, Z_2, ctx)) goto err;
+			}
+
+		if (y != NULL)
+			{
+			if (group->meth->field_encode == 0)
+				{
+				/* field_mul works on standard representation */
+				if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) goto err;
+				}
+			else
+				{
+				if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) goto err;
+				}
+
+			/* in the Montgomery case, field_mul will cancel out Montgomery factor in Y: */
+			if (!group->meth->field_mul(group, y, &point->Y, Z_3, ctx)) goto err;
+			}
+		}
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	return ret;
+	}
+
+int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
+	{
+	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
+	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
+	const BIGNUM *p;
+	BN_CTX *new_ctx = NULL;
+	BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6;
+	int ret = 0;
+	
+	if (a == b)
+		return EC_POINT_dbl(group, r, a, ctx);
+	if (EC_POINT_is_at_infinity(group, a))
+		return EC_POINT_copy(r, b);
+	if (EC_POINT_is_at_infinity(group, b))
+		return EC_POINT_copy(r, a);
+	
+	field_mul = group->meth->field_mul;
+	field_sqr = group->meth->field_sqr;
+	p = &group->field;
+
+	if (ctx == NULL)
+		{
+		ctx = new_ctx = BN_CTX_new();
+		if (ctx == NULL)
+			return 0;
+		}
+
+	BN_CTX_start(ctx);
+	n0 = BN_CTX_get(ctx);
+	n1 = BN_CTX_get(ctx);
+	n2 = BN_CTX_get(ctx);
+	n3 = BN_CTX_get(ctx);
+	n4 = BN_CTX_get(ctx);
+	n5 = BN_CTX_get(ctx);
+	n6 = BN_CTX_get(ctx);
+	if (n6 == NULL) goto end;
+
+	/* Note that in this function we must not read components of 'a' or 'b'
+	 * once we have written the corresponding components of 'r'.
+	 * ('r' might be one of 'a' or 'b'.)
+	 */
+
+	/* n1, n2 */
+	if (b->Z_is_one)
+		{
+		if (!BN_copy(n1, &a->X)) goto end;
+		if (!BN_copy(n2, &a->Y)) goto end;
+		/* n1 = X_a */
+		/* n2 = Y_a */
+		}
+	else
+		{
+		if (!field_sqr(group, n0, &b->Z, ctx)) goto end;
+		if (!field_mul(group, n1, &a->X, n0, ctx)) goto end;
+		/* n1 = X_a * Z_b^2 */
+
+		if (!field_mul(group, n0, n0, &b->Z, ctx)) goto end;
+		if (!field_mul(group, n2, &a->Y, n0, ctx)) goto end;
+		/* n2 = Y_a * Z_b^3 */
+		}
+
+	/* n3, n4 */
+	if (a->Z_is_one)
+		{
+		if (!BN_copy(n3, &b->X)) goto end;
+		if (!BN_copy(n4, &b->Y)) goto end;
+		/* n3 = X_b */
+		/* n4 = Y_b */
+		}
+	else
+		{
+		if (!field_sqr(group, n0, &a->Z, ctx)) goto end;
+		if (!field_mul(group, n3, &b->X, n0, ctx)) goto end;
+		/* n3 = X_b * Z_a^2 */
+
+		if (!field_mul(group, n0, n0, &a->Z, ctx)) goto end;
+		if (!field_mul(group, n4, &b->Y, n0, ctx)) goto end;
+		/* n4 = Y_b * Z_a^3 */
+		}
+
+	/* n5, n6 */
+	if (!BN_mod_sub_quick(n5, n1, n3, p)) goto end;
+	if (!BN_mod_sub_quick(n6, n2, n4, p)) goto end;
+	/* n5 = n1 - n3 */
+	/* n6 = n2 - n4 */
+
+	if (BN_is_zero(n5))
+		{
+		if (BN_is_zero(n6))
+			{
+			/* a is the same point as b */
+			BN_CTX_end(ctx);
+			ret = EC_POINT_dbl(group, r, a, ctx);
+			ctx = NULL;
+			goto end;
+			}
+		else
+			{
+			/* a is the inverse of b */
+			BN_zero(&r->Z);
+			r->Z_is_one = 0;
+			ret = 1;
+			goto end;
+			}
+		}
+
+	/* 'n7', 'n8' */
+	if (!BN_mod_add_quick(n1, n1, n3, p)) goto end;
+	if (!BN_mod_add_quick(n2, n2, n4, p)) goto end;
+	/* 'n7' = n1 + n3 */
+	/* 'n8' = n2 + n4 */
+
+	/* Z_r */
+	if (a->Z_is_one && b->Z_is_one)
+		{
+		if (!BN_copy(&r->Z, n5)) goto end;
+		}
+	else
+		{
+		if (a->Z_is_one)
+			{ if (!BN_copy(n0, &b->Z)) goto end; }
+		else if (b->Z_is_one)
+			{ if (!BN_copy(n0, &a->Z)) goto end; }
+		else
+			{ if (!field_mul(group, n0, &a->Z, &b->Z, ctx)) goto end; }
+		if (!field_mul(group, &r->Z, n0, n5, ctx)) goto end;
+		}
+	r->Z_is_one = 0;
+	/* Z_r = Z_a * Z_b * n5 */
+
+	/* X_r */
+	if (!field_sqr(group, n0, n6, ctx)) goto end;
+	if (!field_sqr(group, n4, n5, ctx)) goto end;
+	if (!field_mul(group, n3, n1, n4, ctx)) goto end;
+	if (!BN_mod_sub_quick(&r->X, n0, n3, p)) goto end;
+	/* X_r = n6^2 - n5^2 * 'n7' */
+	
+	/* 'n9' */
+	if (!BN_mod_lshift1_quick(n0, &r->X, p)) goto end;
+	if (!BN_mod_sub_quick(n0, n3, n0, p)) goto end;
+	/* n9 = n5^2 * 'n7' - 2 * X_r */
+
+	/* Y_r */
+	if (!field_mul(group, n0, n0, n6, ctx)) goto end;
+	if (!field_mul(group, n5, n4, n5, ctx)) goto end; /* now n5 is n5^3 */
+	if (!field_mul(group, n1, n2, n5, ctx)) goto end;
+	if (!BN_mod_sub_quick(n0, n0, n1, p)) goto end;
+	if (BN_is_odd(n0))
+		if (!BN_add(n0, n0, p)) goto end;
+	/* now  0 <= n0 < 2*p,  and n0 is even */
+	if (!BN_rshift1(&r->Y, n0)) goto end;
+	/* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */
+
+	ret = 1;
+
+ end:
+	if (ctx) /* otherwise we already called BN_CTX_end */
+		BN_CTX_end(ctx);
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	return ret;
+	}
+
+
+int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
+	{
+	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
+	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
+	const BIGNUM *p;
+	BN_CTX *new_ctx = NULL;
+	BIGNUM *n0, *n1, *n2, *n3;
+	int ret = 0;
+	
+	if (EC_POINT_is_at_infinity(group, a))
+		{
+		BN_zero(&r->Z);
+		r->Z_is_one = 0;
+		return 1;
+		}
+
+	field_mul = group->meth->field_mul;
+	field_sqr = group->meth->field_sqr;
+	p = &group->field;
+
+	if (ctx == NULL)
+		{
+		ctx = new_ctx = BN_CTX_new();
+		if (ctx == NULL)
+			return 0;
+		}
+
+	BN_CTX_start(ctx);
+	n0 = BN_CTX_get(ctx);
+	n1 = BN_CTX_get(ctx);
+	n2 = BN_CTX_get(ctx);
+	n3 = BN_CTX_get(ctx);
+	if (n3 == NULL) goto err;
+
+	/* Note that in this function we must not read components of 'a'
+	 * once we have written the corresponding components of 'r'.
+	 * ('r' might the same as 'a'.)
+	 */
+
+	/* n1 */
+	if (a->Z_is_one)
+		{
+		if (!field_sqr(group, n0, &a->X, ctx)) goto err;
+		if (!BN_mod_lshift1_quick(n1, n0, p)) goto err;
+		if (!BN_mod_add_quick(n0, n0, n1, p)) goto err;
+		if (!BN_mod_add_quick(n1, n0, &group->a, p)) goto err;
+		/* n1 = 3 * X_a^2 + a_curve */
+		}
+	else if (group->a_is_minus3)
+		{
+		if (!field_sqr(group, n1, &a->Z, ctx)) goto err;
+		if (!BN_mod_add_quick(n0, &a->X, n1, p)) goto err;
+		if (!BN_mod_sub_quick(n2, &a->X, n1, p)) goto err;
+		if (!field_mul(group, n1, n0, n2, ctx)) goto err;
+		if (!BN_mod_lshift1_quick(n0, n1, p)) goto err;
+		if (!BN_mod_add_quick(n1, n0, n1, p)) goto err;
+		/* n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2)
+		 *    = 3 * X_a^2 - 3 * Z_a^4 */
+		}
+	else
+		{
+		if (!field_sqr(group, n0, &a->X, ctx)) goto err;
+		if (!BN_mod_lshift1_quick(n1, n0, p)) goto err;
+		if (!BN_mod_add_quick(n0, n0, n1, p)) goto err;
+		if (!field_sqr(group, n1, &a->Z, ctx)) goto err;
+		if (!field_sqr(group, n1, n1, ctx)) goto err;
+		if (!field_mul(group, n1, n1, &group->a, ctx)) goto err;
+		if (!BN_mod_add_quick(n1, n1, n0, p)) goto err;
+		/* n1 = 3 * X_a^2 + a_curve * Z_a^4 */
+		}
+
+	/* Z_r */
+	if (a->Z_is_one)
+		{
+		if (!BN_copy(n0, &a->Y)) goto err;
+		}
+	else
+		{
+		if (!field_mul(group, n0, &a->Y, &a->Z, ctx)) goto err;
+		}
+	if (!BN_mod_lshift1_quick(&r->Z, n0, p)) goto err;
+	r->Z_is_one = 0;
+	/* Z_r = 2 * Y_a * Z_a */
+
+	/* n2 */
+	if (!field_sqr(group, n3, &a->Y, ctx)) goto err;
+	if (!field_mul(group, n2, &a->X, n3, ctx)) goto err;
+	if (!BN_mod_lshift_quick(n2, n2, 2, p)) goto err;
+	/* n2 = 4 * X_a * Y_a^2 */
+
+	/* X_r */
+	if (!BN_mod_lshift1_quick(n0, n2, p)) goto err;
+	if (!field_sqr(group, &r->X, n1, ctx)) goto err;
+	if (!BN_mod_sub_quick(&r->X, &r->X, n0, p)) goto err;
+	/* X_r = n1^2 - 2 * n2 */
+	
+	/* n3 */
+	if (!field_sqr(group, n0, n3, ctx)) goto err;
+	if (!BN_mod_lshift_quick(n3, n0, 3, p)) goto err;
+	/* n3 = 8 * Y_a^4 */
+	
+	/* Y_r */
+	if (!BN_mod_sub_quick(n0, n2, &r->X, p)) goto err;
+	if (!field_mul(group, n0, n1, n0, ctx)) goto err;
+	if (!BN_mod_sub_quick(&r->Y, n0, n3, p)) goto err;
+	/* Y_r = n1 * (n2 - X_r) - n3 */
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	return ret;
+	}
+
+
+int ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
+	{
+	if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y))
+		/* point is its own inverse */
+		return 1;
+	
+	return BN_usub(&point->Y, &group->field, &point->Y);
+	}
+
+
+int ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
+	{
+	return BN_is_zero(&point->Z);
+	}
+
+
+int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
+	{
+	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
+	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
+	const BIGNUM *p;
+	BN_CTX *new_ctx = NULL;
+	BIGNUM *rh, *tmp, *Z4, *Z6;
+	int ret = -1;
+
+	if (EC_POINT_is_at_infinity(group, point))
+		return 1;
+	
+	field_mul = group->meth->field_mul;
+	field_sqr = group->meth->field_sqr;
+	p = &group->field;
+
+	if (ctx == NULL)
+		{
+		ctx = new_ctx = BN_CTX_new();
+		if (ctx == NULL)
+			return -1;
+		}
+
+	BN_CTX_start(ctx);
+	rh = BN_CTX_get(ctx);
+	tmp = BN_CTX_get(ctx);
+	Z4 = BN_CTX_get(ctx);
+	Z6 = BN_CTX_get(ctx);
+	if (Z6 == NULL) goto err;
+
+	/* We have a curve defined by a Weierstrass equation
+	 *      y^2 = x^3 + a*x + b.
+	 * The point to consider is given in Jacobian projective coordinates
+	 * where  (X, Y, Z)  represents  (x, y) = (X/Z^2, Y/Z^3).
+	 * Substituting this and multiplying by  Z^6  transforms the above equation into
+	 *      Y^2 = X^3 + a*X*Z^4 + b*Z^6.
+	 * To test this, we add up the right-hand side in 'rh'.
+	 */
+
+	/* rh := X^2 */
+	if (!field_sqr(group, rh, &point->X, ctx)) goto err;
+
+	if (!point->Z_is_one)
+		{
+		if (!field_sqr(group, tmp, &point->Z, ctx)) goto err;
+		if (!field_sqr(group, Z4, tmp, ctx)) goto err;
+		if (!field_mul(group, Z6, Z4, tmp, ctx)) goto err;
+
+		/* rh := (rh + a*Z^4)*X */
+		if (group->a_is_minus3)
+			{
+			if (!BN_mod_lshift1_quick(tmp, Z4, p)) goto err;
+			if (!BN_mod_add_quick(tmp, tmp, Z4, p)) goto err;
+			if (!BN_mod_sub_quick(rh, rh, tmp, p)) goto err;
+			if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
+			}
+		else
+			{
+			if (!field_mul(group, tmp, Z4, &group->a, ctx)) goto err;
+			if (!BN_mod_add_quick(rh, rh, tmp, p)) goto err;
+			if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
+			}
+
+		/* rh := rh + b*Z^6 */
+		if (!field_mul(group, tmp, &group->b, Z6, ctx)) goto err;
+		if (!BN_mod_add_quick(rh, rh, tmp, p)) goto err;
+		}
+	else
+		{
+		/* point->Z_is_one */
+
+		/* rh := (rh + a)*X */
+		if (!BN_mod_add_quick(rh, rh, &group->a, p)) goto err;
+		if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
+		/* rh := rh + b */
+		if (!BN_mod_add_quick(rh, rh, &group->b, p)) goto err;
+		}
+
+	/* 'lh' := Y^2 */
+	if (!field_sqr(group, tmp, &point->Y, ctx)) goto err;
+
+	ret = (0 == BN_ucmp(tmp, rh));
+
+ err:
+	BN_CTX_end(ctx);
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	return ret;
+	}
+
+
+int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
+	{
+	/* return values:
+	 *  -1   error
+	 *   0   equal (in affine coordinates)
+	 *   1   not equal
+	 */
+
+	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
+	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
+	BN_CTX *new_ctx = NULL;
+	BIGNUM *tmp1, *tmp2, *Za23, *Zb23;
+	const BIGNUM *tmp1_, *tmp2_;
+	int ret = -1;
+	
+	if (EC_POINT_is_at_infinity(group, a))
+		{
+		return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
+		}
+
+	if (EC_POINT_is_at_infinity(group, b))
+		return 1;
+	
+	if (a->Z_is_one && b->Z_is_one)
+		{
+		return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
+		}
+
+	field_mul = group->meth->field_mul;
+	field_sqr = group->meth->field_sqr;
+
+	if (ctx == NULL)
+		{
+		ctx = new_ctx = BN_CTX_new();
+		if (ctx == NULL)
+			return -1;
+		}
+
+	BN_CTX_start(ctx);
+	tmp1 = BN_CTX_get(ctx);
+	tmp2 = BN_CTX_get(ctx);
+	Za23 = BN_CTX_get(ctx);
+	Zb23 = BN_CTX_get(ctx);
+	if (Zb23 == NULL) goto end;
+
+	/* We have to decide whether
+	 *     (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2, Y_b/Z_b^3),
+	 * or equivalently, whether
+	 *     (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3).
+	 */
+
+	if (!b->Z_is_one)
+		{
+		if (!field_sqr(group, Zb23, &b->Z, ctx)) goto end;
+		if (!field_mul(group, tmp1, &a->X, Zb23, ctx)) goto end;
+		tmp1_ = tmp1;
+		}
+	else
+		tmp1_ = &a->X;
+	if (!a->Z_is_one)
+		{
+		if (!field_sqr(group, Za23, &a->Z, ctx)) goto end;
+		if (!field_mul(group, tmp2, &b->X, Za23, ctx)) goto end;
+		tmp2_ = tmp2;
+		}
+	else
+		tmp2_ = &b->X;
+	
+	/* compare  X_a*Z_b^2  with  X_b*Z_a^2 */
+	if (BN_cmp(tmp1_, tmp2_) != 0)
+		{
+		ret = 1; /* points differ */
+		goto end;
+		}
+
+
+	if (!b->Z_is_one)
+		{
+		if (!field_mul(group, Zb23, Zb23, &b->Z, ctx)) goto end;
+		if (!field_mul(group, tmp1, &a->Y, Zb23, ctx)) goto end;
+		/* tmp1_ = tmp1 */
+		}
+	else
+		tmp1_ = &a->Y;
+	if (!a->Z_is_one)
+		{
+		if (!field_mul(group, Za23, Za23, &a->Z, ctx)) goto end;
+		if (!field_mul(group, tmp2, &b->Y, Za23, ctx)) goto end;
+		/* tmp2_ = tmp2 */
+		}
+	else
+		tmp2_ = &b->Y;
+
+	/* compare  Y_a*Z_b^3  with  Y_b*Z_a^3 */
+	if (BN_cmp(tmp1_, tmp2_) != 0)
+		{
+		ret = 1; /* points differ */
+		goto end;
+		}
+
+	/* points are equal */
+	ret = 0;
+
+ end:
+	BN_CTX_end(ctx);
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	return ret;
+	}
+
+
+int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
+	{
+	BN_CTX *new_ctx = NULL;
+	BIGNUM *x, *y;
+	int ret = 0;
+
+	if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
+		return 1;
+
+	if (ctx == NULL)
+		{
+		ctx = new_ctx = BN_CTX_new();
+		if (ctx == NULL)
+			return 0;
+		}
+
+	BN_CTX_start(ctx);
+	x = BN_CTX_get(ctx);
+	y = BN_CTX_get(ctx);
+	if (y == NULL) goto err;
+
+	if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
+	if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
+	if (!point->Z_is_one)
+		{
+		ECerr(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE, ERR_R_INTERNAL_ERROR);
+		goto err;
+		}
+	
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	return ret;
+	}
+
+
+int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
+	{
+	BN_CTX *new_ctx = NULL;
+	BIGNUM *tmp0, *tmp1;
+	size_t pow2 = 0;
+	BIGNUM **heap = NULL;
+	size_t i;
+	int ret = 0;
+
+	if (num == 0)
+		return 1;
+
+	if (ctx == NULL)
+		{
+		ctx = new_ctx = BN_CTX_new();
+		if (ctx == NULL)
+			return 0;
+		}
+
+	BN_CTX_start(ctx);
+	tmp0 = BN_CTX_get(ctx);
+	tmp1 = BN_CTX_get(ctx);
+	if (tmp0  == NULL || tmp1 == NULL) goto err;
+
+	/* Before converting the individual points, compute inverses of all Z values.
+	 * Modular inversion is rather slow, but luckily we can do with a single
+	 * explicit inversion, plus about 3 multiplications per input value.
+	 */
+
+	pow2 = 1;
+	while (num > pow2)
+		pow2 <<= 1;
+	/* Now pow2 is the smallest power of 2 satifsying pow2 >= num.
+	 * We need twice that. */
+	pow2 <<= 1;
+
+	heap = OPENSSL_malloc(pow2 * sizeof heap[0]);
+	if (heap == NULL) goto err;
+	
+	/* The array is used as a binary tree, exactly as in heapsort:
+	 *
+	 *                               heap[1]
+	 *                 heap[2]                     heap[3]
+	 *          heap[4]       heap[5]       heap[6]       heap[7]
+	 *   heap[8]heap[9] heap[10]heap[11] heap[12]heap[13] heap[14] heap[15]
+	 *
+	 * We put the Z's in the last line;
+	 * then we set each other node to the product of its two child-nodes (where
+	 * empty or 0 entries are treated as ones);
+	 * then we invert heap[1];
+	 * then we invert each other node by replacing it by the product of its
+	 * parent (after inversion) and its sibling (before inversion).
+	 */
+	heap[0] = NULL;
+	for (i = pow2/2 - 1; i > 0; i--)
+		heap[i] = NULL;
+	for (i = 0; i < num; i++)
+		heap[pow2/2 + i] = &points[i]->Z;
+	for (i = pow2/2 + num; i < pow2; i++)
+		heap[i] = NULL;
+	
+	/* set each node to the product of its children */
+	for (i = pow2/2 - 1; i > 0; i--)
+		{
+		heap[i] = BN_new();
+		if (heap[i] == NULL) goto err;
+		
+		if (heap[2*i] != NULL)
+			{
+			if ((heap[2*i + 1] == NULL) || BN_is_zero(heap[2*i + 1]))
+				{
+				if (!BN_copy(heap[i], heap[2*i])) goto err;
+				}
+			else
+				{
+				if (BN_is_zero(heap[2*i]))
+					{
+					if (!BN_copy(heap[i], heap[2*i + 1])) goto err;
+					}
+				else
+					{
+					if (!group->meth->field_mul(group, heap[i],
+						heap[2*i], heap[2*i + 1], ctx)) goto err;
+					}
+				}
+			}
+		}
+
+	/* invert heap[1] */
+	if (!BN_is_zero(heap[1]))
+		{
+		if (!BN_mod_inverse(heap[1], heap[1], &group->field, ctx))
+			{
+			ECerr(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, ERR_R_BN_LIB);
+			goto err;
+			}
+		}
+	if (group->meth->field_encode != 0)
+		{
+		/* in the Montgomery case, we just turned  R*H  (representing H)
+		 * into  1/(R*H),  but we need  R*(1/H)  (representing 1/H);
+		 * i.e. we have need to multiply by the Montgomery factor twice */
+		if (!group->meth->field_encode(group, heap[1], heap[1], ctx)) goto err;
+		if (!group->meth->field_encode(group, heap[1], heap[1], ctx)) goto err;
+		}
+
+	/* set other heap[i]'s to their inverses */
+	for (i = 2; i < pow2/2 + num; i += 2)
+		{
+		/* i is even */
+		if ((heap[i + 1] != NULL) && !BN_is_zero(heap[i + 1]))
+			{
+			if (!group->meth->field_mul(group, tmp0, heap[i/2], heap[i + 1], ctx)) goto err;
+			if (!group->meth->field_mul(group, tmp1, heap[i/2], heap[i], ctx)) goto err;
+			if (!BN_copy(heap[i], tmp0)) goto err;
+			if (!BN_copy(heap[i + 1], tmp1)) goto err;
+			}
+		else
+			{
+			if (!BN_copy(heap[i], heap[i/2])) goto err;
+			}
+		}
+
+	/* we have replaced all non-zero Z's by their inverses, now fix up all the points */
+	for (i = 0; i < num; i++)
+		{
+		EC_POINT *p = points[i];
+		
+		if (!BN_is_zero(&p->Z))
+			{
+			/* turn  (X, Y, 1/Z)  into  (X/Z^2, Y/Z^3, 1) */
+
+			if (!group->meth->field_sqr(group, tmp1, &p->Z, ctx)) goto err;
+			if (!group->meth->field_mul(group, &p->X, &p->X, tmp1, ctx)) goto err;
+
+			if (!group->meth->field_mul(group, tmp1, tmp1, &p->Z, ctx)) goto err;
+			if (!group->meth->field_mul(group, &p->Y, &p->Y, tmp1, ctx)) goto err;
+		
+			if (group->meth->field_set_to_one != 0)
+				{
+				if (!group->meth->field_set_to_one(group, &p->Z, ctx)) goto err;
+				}
+			else
+				{
+				if (!BN_one(&p->Z)) goto err;
+				}
+			p->Z_is_one = 1;
+			}
+		}
+
+	ret = 1;
+		
+ err:
+	BN_CTX_end(ctx);
+	if (new_ctx != NULL)
+		BN_CTX_free(new_ctx);
+	if (heap != NULL)
+		{
+		/* heap[pow2/2] .. heap[pow2-1] have not been allocated locally! */
+		for (i = pow2/2 - 1; i > 0; i--)
+			{
+			if (heap[i] != NULL)
+				BN_clear_free(heap[i]);
+			}
+		OPENSSL_free(heap);
+		}
+	return ret;
+	}
+
+
+int ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
+	{
+	return BN_mod_mul(r, a, b, &group->field, ctx);
+	}
+
+
+int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
+	{
+	return BN_mod_sqr(r, a, &group->field, ctx);
+	}
diff --git a/jni/openssl/crypto/ec/ectest.c b/jni/openssl/crypto/ec/ectest.c
new file mode 100644
index 0000000..f107782
--- /dev/null
+++ b/jni/openssl/crypto/ec/ectest.c
@@ -0,0 +1,1489 @@
+/* crypto/ec/ectest.c */
+/*
+ * Originally written by Bodo Moeller for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2001 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 of the attached software ("Contribution") are developed by 
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * The elliptic curve binary polynomial software is originally written by 
+ * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef FLAT_INC
+#include "e_os.h"
+#else
+#include "../e_os.h"
+#endif
+#include <string.h>
+#include <time.h>
+
+
+#ifdef OPENSSL_NO_EC
+int main(int argc, char * argv[]) { puts("Elliptic curves are disabled."); return 0; }
+#else
+
+
+#include <openssl/ec.h>
+#ifndef OPENSSL_NO_ENGINE
+#include <openssl/engine.h>
+#endif
+#include <openssl/err.h>
+#include <openssl/obj_mac.h>
+#include <openssl/objects.h>
+#include <openssl/rand.h>
+#include <openssl/bn.h>
+#include <openssl/opensslconf.h>
+
+#if defined(_MSC_VER) && defined(_MIPS_) && (_MSC_VER/100==12)
+/* suppress "too big too optimize" warning */
+#pragma warning(disable:4959)
+#endif
+
+#define ABORT do { \
+	fflush(stdout); \
+	fprintf(stderr, "%s:%d: ABORT\n", __FILE__, __LINE__); \
+	ERR_print_errors_fp(stderr); \
+	EXIT(1); \
+} while (0)
+
+#define TIMING_BASE_PT 0
+#define TIMING_RAND_PT 1
+#define TIMING_SIMUL 2
+
+#if 0
+static void timings(EC_GROUP *group, int type, BN_CTX *ctx)
+	{
+	clock_t clck;
+	int i, j;
+	BIGNUM *s;
+	BIGNUM *r[10], *r0[10];
+	EC_POINT *P;
+		
+	s = BN_new();
+	if (s == NULL) ABORT;
+
+	fprintf(stdout, "Timings for %d-bit field, ", EC_GROUP_get_degree(group));
+	if (!EC_GROUP_get_order(group, s, ctx)) ABORT;
+	fprintf(stdout, "%d-bit scalars ", (int)BN_num_bits(s));
+	fflush(stdout);
+
+	P = EC_POINT_new(group);
+	if (P == NULL) ABORT;
+	EC_POINT_copy(P, EC_GROUP_get0_generator(group));
+
+	for (i = 0; i < 10; i++)
+		{
+		if ((r[i] = BN_new()) == NULL) ABORT;
+		if (!BN_pseudo_rand(r[i], BN_num_bits(s), 0, 0)) ABORT;
+		if (type != TIMING_BASE_PT)
+			{
+			if ((r0[i] = BN_new()) == NULL) ABORT;
+			if (!BN_pseudo_rand(r0[i], BN_num_bits(s), 0, 0)) ABORT;
+			}
+		}
+
+	clck = clock();
+	for (i = 0; i < 10; i++)
+		{
+		for (j = 0; j < 10; j++)
+			{
+			if (!EC_POINT_mul(group, P, (type != TIMING_RAND_PT) ? r[i] : NULL, 
+				(type != TIMING_BASE_PT) ? P : NULL, (type != TIMING_BASE_PT) ? r0[i] : NULL, ctx)) ABORT;
+			}
+		}
+	clck = clock() - clck;
+
+	fprintf(stdout, "\n");
+
+#ifdef CLOCKS_PER_SEC
+	/* "To determine the time in seconds, the value returned
+	 * by the clock function should be divided by the value
+	 * of the macro CLOCKS_PER_SEC."
+	 *                                       -- ISO/IEC 9899 */
+#	define UNIT "s"
+#else
+	/* "`CLOCKS_PER_SEC' undeclared (first use this function)"
+	 *                            -- cc on NeXTstep/OpenStep */
+#	define UNIT "units"
+#	define CLOCKS_PER_SEC 1
+#endif
+
+	if (type == TIMING_BASE_PT) {
+		fprintf(stdout, "%i %s in %.2f " UNIT "\n", i*j,
+			"base point multiplications", (double)clck/CLOCKS_PER_SEC);
+	} else if (type == TIMING_RAND_PT) {
+		fprintf(stdout, "%i %s in %.2f " UNIT "\n", i*j,
+			"random point multiplications", (double)clck/CLOCKS_PER_SEC);
+	} else if (type == TIMING_SIMUL) {
+		fprintf(stdout, "%i %s in %.2f " UNIT "\n", i*j,
+			"s*P+t*Q operations", (double)clck/CLOCKS_PER_SEC);
+	}
+	fprintf(stdout, "average: %.4f " UNIT "\n", (double)clck/(CLOCKS_PER_SEC*i*j));
+
+	EC_POINT_free(P);
+	BN_free(s);
+	for (i = 0; i < 10; i++)
+		{
+		BN_free(r[i]);
+		if (type != TIMING_BASE_PT) BN_free(r0[i]);
+		}
+	}
+#endif
+
+/* test multiplication with group order, long and negative scalars */
+static void group_order_tests(EC_GROUP *group)
+	{
+	BIGNUM *n1, *n2, *order;
+	EC_POINT *P = EC_POINT_new(group);
+	EC_POINT *Q = EC_POINT_new(group);
+	BN_CTX *ctx = BN_CTX_new();
+
+	n1 = BN_new(); n2 = BN_new(); order = BN_new();
+	fprintf(stdout, "verify group order ...");
+	fflush(stdout);
+	if (!EC_GROUP_get_order(group, order, ctx)) ABORT;
+	if (!EC_POINT_mul(group, Q, order, NULL, NULL, ctx)) ABORT;
+	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
+	fprintf(stdout, ".");
+	fflush(stdout);
+	if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
+	if (!EC_POINT_mul(group, Q, order, NULL, NULL, ctx)) ABORT;
+	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
+	fprintf(stdout, " ok\n");
+	fprintf(stdout, "long/negative scalar tests ... ");
+	if (!BN_one(n1)) ABORT;
+	/* n1 = 1 - order */
+	if (!BN_sub(n1, n1, order)) ABORT;
+	if(!EC_POINT_mul(group, Q, NULL, P, n1, ctx)) ABORT;
+	if (0 != EC_POINT_cmp(group, Q, P, ctx)) ABORT;
+	/* n2 = 1 + order */
+	if (!BN_add(n2, order, BN_value_one())) ABORT;
+	if(!EC_POINT_mul(group, Q, NULL, P, n2, ctx)) ABORT;
+	if (0 != EC_POINT_cmp(group, Q, P, ctx)) ABORT;
+	/* n2 = (1 - order) * (1 + order) */
+	if (!BN_mul(n2, n1, n2, ctx)) ABORT;
+	if(!EC_POINT_mul(group, Q, NULL, P, n2, ctx)) ABORT;
+	if (0 != EC_POINT_cmp(group, Q, P, ctx)) ABORT;
+	fprintf(stdout, "ok\n");
+	EC_POINT_free(P);
+	EC_POINT_free(Q);
+	BN_free(n1);
+	BN_free(n2);
+	BN_free(order);
+	BN_CTX_free(ctx);
+	}
+
+static void prime_field_tests(void)
+	{	
+	BN_CTX *ctx = NULL;
+	BIGNUM *p, *a, *b;
+	EC_GROUP *group;
+	EC_GROUP *P_160 = NULL, *P_192 = NULL, *P_224 = NULL, *P_256 = NULL, *P_384 = NULL, *P_521 = NULL;
+	EC_POINT *P, *Q, *R;
+	BIGNUM *x, *y, *z;
+	unsigned char buf[100];
+	size_t i, len;
+	int k;
+	
+#if 1 /* optional */
+	ctx = BN_CTX_new();
+	if (!ctx) ABORT;
+#endif
+
+	p = BN_new();
+	a = BN_new();
+	b = BN_new();
+	if (!p || !a || !b) ABORT;
+
+	if (!BN_hex2bn(&p, "17")) ABORT;
+	if (!BN_hex2bn(&a, "1")) ABORT;
+	if (!BN_hex2bn(&b, "1")) ABORT;
+	
+	group = EC_GROUP_new(EC_GFp_mont_method()); /* applications should use EC_GROUP_new_curve_GFp
+	                                             * so that the library gets to choose the EC_METHOD */
+	if (!group) ABORT;
+
+	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
+
+	{
+		EC_GROUP *tmp;
+		tmp = EC_GROUP_new(EC_GROUP_method_of(group));
+		if (!tmp) ABORT;
+		if (!EC_GROUP_copy(tmp, group)) ABORT;
+		EC_GROUP_free(group);
+		group = tmp;
+	}
+	
+	if (!EC_GROUP_get_curve_GFp(group, p, a, b, ctx)) ABORT;
+
+	fprintf(stdout, "Curve defined by Weierstrass equation\n     y^2 = x^3 + a*x + b  (mod 0x");
+	BN_print_fp(stdout, p);
+	fprintf(stdout, ")\n     a = 0x");
+	BN_print_fp(stdout, a);
+	fprintf(stdout, "\n     b = 0x");
+	BN_print_fp(stdout, b);
+	fprintf(stdout, "\n");
+
+	P = EC_POINT_new(group);
+	Q = EC_POINT_new(group);
+	R = EC_POINT_new(group);
+	if (!P || !Q || !R) ABORT;
+	
+	if (!EC_POINT_set_to_infinity(group, P)) ABORT;
+	if (!EC_POINT_is_at_infinity(group, P)) ABORT;
+
+	buf[0] = 0;
+	if (!EC_POINT_oct2point(group, Q, buf, 1, ctx)) ABORT;
+
+	if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;
+	if (!EC_POINT_is_at_infinity(group, P)) ABORT;
+
+	x = BN_new();
+	y = BN_new();
+	z = BN_new();
+	if (!x || !y || !z) ABORT;
+
+	if (!BN_hex2bn(&x, "D")) ABORT;
+	if (!EC_POINT_set_compressed_coordinates_GFp(group, Q, x, 1, ctx)) ABORT;
+	if (!EC_POINT_is_on_curve(group, Q, ctx))
+		{
+		if (!EC_POINT_get_affine_coordinates_GFp(group, Q, x, y, ctx)) ABORT;
+		fprintf(stderr, "Point is not on curve: x = 0x");
+		BN_print_fp(stderr, x);
+		fprintf(stderr, ", y = 0x");
+		BN_print_fp(stderr, y);
+		fprintf(stderr, "\n");
+		ABORT;
+		}
+
+	fprintf(stdout, "A cyclic subgroup:\n");
+	k = 100;
+	do
+		{
+		if (k-- == 0) ABORT;
+
+		if (EC_POINT_is_at_infinity(group, P))
+			fprintf(stdout, "     point at infinity\n");
+		else
+			{
+			if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
+
+			fprintf(stdout, "     x = 0x");
+			BN_print_fp(stdout, x);
+			fprintf(stdout, ", y = 0x");
+			BN_print_fp(stdout, y);
+			fprintf(stdout, "\n");
+			}
+		
+		if (!EC_POINT_copy(R, P)) ABORT;
+		if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;
+
+#if 0 /* optional */
+		{
+			EC_POINT *points[3];
+		
+			points[0] = R;
+			points[1] = Q;
+			points[2] = P;
+			if (!EC_POINTs_make_affine(group, 2, points, ctx)) ABORT;
+		}
+#endif
+
+		}
+	while (!EC_POINT_is_at_infinity(group, P));
+
+	if (!EC_POINT_add(group, P, Q, R, ctx)) ABORT;
+	if (!EC_POINT_is_at_infinity(group, P)) ABORT;
+
+	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf, sizeof buf, ctx);
+	if (len == 0) ABORT;
+	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
+	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
+	fprintf(stdout, "Generator as octet string, compressed form:\n     ");
+	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
+	
+	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx);
+	if (len == 0) ABORT;
+	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
+	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
+	fprintf(stdout, "\nGenerator as octet string, uncompressed form:\n     ");
+	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
+	
+	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx);
+	if (len == 0) ABORT;
+	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
+	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
+	fprintf(stdout, "\nGenerator as octet string, hybrid form:\n     ");
+	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
+	
+	if (!EC_POINT_get_Jprojective_coordinates_GFp(group, R, x, y, z, ctx)) ABORT;
+	fprintf(stdout, "\nA representation of the inverse of that generator in\nJacobian projective coordinates:\n     X = 0x");
+	BN_print_fp(stdout, x);
+	fprintf(stdout, ", Y = 0x");
+	BN_print_fp(stdout, y);
+	fprintf(stdout, ", Z = 0x");
+	BN_print_fp(stdout, z);
+	fprintf(stdout, "\n");
+
+	if (!EC_POINT_invert(group, P, ctx)) ABORT;
+	if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT;
+
+
+	/* Curve secp160r1 (Certicom Research SEC 2 Version 1.0, section 2.4.2, 2000)
+	 * -- not a NIST curve, but commonly used */
+	
+	if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF")) ABORT;
+	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
+	if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC")) ABORT;
+	if (!BN_hex2bn(&b, "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45")) ABORT;
+	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
+
+	if (!BN_hex2bn(&x, "4A96B5688EF573284664698968C38BB913CBFC82")) ABORT;
+	if (!BN_hex2bn(&y, "23a628553168947d59dcc912042351377ac5fb32")) ABORT;
+	if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
+	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (!BN_hex2bn(&z, "0100000000000000000001F4C8F927AED3CA752257")) ABORT;
+	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
+
+	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
+	fprintf(stdout, "\nSEC2 curve secp160r1 -- Generator:\n     x = 0x");
+	BN_print_fp(stdout, x);
+	fprintf(stdout, "\n     y = 0x");
+	BN_print_fp(stdout, y);
+	fprintf(stdout, "\n");
+	/* G_y value taken from the standard: */
+	if (!BN_hex2bn(&z, "23a628553168947d59dcc912042351377ac5fb32")) ABORT;
+	if (0 != BN_cmp(y, z)) ABORT;
+
+	fprintf(stdout, "verify degree ...");
+	if (EC_GROUP_get_degree(group) != 160) ABORT;
+	fprintf(stdout, " ok\n");
+	
+	group_order_tests(group);
+
+	if (!(P_160 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
+	if (!EC_GROUP_copy(P_160, group)) ABORT;
+
+
+	/* Curve P-192 (FIPS PUB 186-2, App. 6) */
+	
+	if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF")) ABORT;
+	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
+	if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC")) ABORT;
+	if (!BN_hex2bn(&b, "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1")) ABORT;
+	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
+
+	if (!BN_hex2bn(&x, "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012")) ABORT;
+	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT;
+	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831")) ABORT;
+	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
+
+	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
+	fprintf(stdout, "\nNIST curve P-192 -- Generator:\n     x = 0x");
+	BN_print_fp(stdout, x);
+	fprintf(stdout, "\n     y = 0x");
+	BN_print_fp(stdout, y);
+	fprintf(stdout, "\n");
+	/* G_y value taken from the standard: */
+	if (!BN_hex2bn(&z, "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811")) ABORT;
+	if (0 != BN_cmp(y, z)) ABORT;
+
+	fprintf(stdout, "verify degree ...");
+	if (EC_GROUP_get_degree(group) != 192) ABORT;
+	fprintf(stdout, " ok\n");
+	
+	group_order_tests(group);
+
+	if (!(P_192 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
+	if (!EC_GROUP_copy(P_192, group)) ABORT;
+
+
+	/* Curve P-224 (FIPS PUB 186-2, App. 6) */
+	
+	if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001")) ABORT;
+	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
+	if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE")) ABORT;
+	if (!BN_hex2bn(&b, "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4")) ABORT;
+	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
+
+	if (!BN_hex2bn(&x, "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21")) ABORT;
+	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT;
+	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D")) ABORT;
+	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
+
+	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
+	fprintf(stdout, "\nNIST curve P-224 -- Generator:\n     x = 0x");
+	BN_print_fp(stdout, x);
+	fprintf(stdout, "\n     y = 0x");
+	BN_print_fp(stdout, y);
+	fprintf(stdout, "\n");
+	/* G_y value taken from the standard: */
+	if (!BN_hex2bn(&z, "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34")) ABORT;
+	if (0 != BN_cmp(y, z)) ABORT;
+	
+	fprintf(stdout, "verify degree ...");
+	if (EC_GROUP_get_degree(group) != 224) ABORT;
+	fprintf(stdout, " ok\n");
+	
+	group_order_tests(group);
+
+	if (!(P_224 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
+	if (!EC_GROUP_copy(P_224, group)) ABORT;
+
+
+	/* Curve P-256 (FIPS PUB 186-2, App. 6) */
+	
+	if (!BN_hex2bn(&p, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF")) ABORT;
+	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
+	if (!BN_hex2bn(&a, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC")) ABORT;
+	if (!BN_hex2bn(&b, "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B")) ABORT;
+	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
+
+	if (!BN_hex2bn(&x, "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296")) ABORT;
+	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT;
+	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (!BN_hex2bn(&z, "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E"
+		"84F3B9CAC2FC632551")) ABORT;
+	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
+
+	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
+	fprintf(stdout, "\nNIST curve P-256 -- Generator:\n     x = 0x");
+	BN_print_fp(stdout, x);
+	fprintf(stdout, "\n     y = 0x");
+	BN_print_fp(stdout, y);
+	fprintf(stdout, "\n");
+	/* G_y value taken from the standard: */
+	if (!BN_hex2bn(&z, "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5")) ABORT;
+	if (0 != BN_cmp(y, z)) ABORT;
+	
+	fprintf(stdout, "verify degree ...");
+	if (EC_GROUP_get_degree(group) != 256) ABORT;
+	fprintf(stdout, " ok\n");
+	
+	group_order_tests(group);
+
+	if (!(P_256 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
+	if (!EC_GROUP_copy(P_256, group)) ABORT;
+
+
+	/* Curve P-384 (FIPS PUB 186-2, App. 6) */
+	
+	if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+		"FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF")) ABORT;
+	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
+	if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+		"FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC")) ABORT;
+	if (!BN_hex2bn(&b, "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141"
+		"120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF")) ABORT;
+	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
+
+	if (!BN_hex2bn(&x, "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B"
+		"9859F741E082542A385502F25DBF55296C3A545E3872760AB7")) ABORT;
+	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT;
+	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+		"FFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973")) ABORT;
+	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
+
+	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
+	fprintf(stdout, "\nNIST curve P-384 -- Generator:\n     x = 0x");
+	BN_print_fp(stdout, x);
+	fprintf(stdout, "\n     y = 0x");
+	BN_print_fp(stdout, y);
+	fprintf(stdout, "\n");
+	/* G_y value taken from the standard: */
+	if (!BN_hex2bn(&z, "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A14"
+		"7CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F")) ABORT;
+	if (0 != BN_cmp(y, z)) ABORT;
+	
+	fprintf(stdout, "verify degree ...");
+	if (EC_GROUP_get_degree(group) != 384) ABORT;
+	fprintf(stdout, " ok\n");
+
+	group_order_tests(group);
+
+	if (!(P_384 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
+	if (!EC_GROUP_copy(P_384, group)) ABORT;
+
+
+	/* Curve P-521 (FIPS PUB 186-2, App. 6) */
+	
+	if (!BN_hex2bn(&p, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+		"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+		"FFFFFFFFFFFFFFFFFFFFFFFFFFFF")) ABORT;
+	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
+	if (!BN_hex2bn(&a, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+		"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+		"FFFFFFFFFFFFFFFFFFFFFFFFFFFC")) ABORT;
+	if (!BN_hex2bn(&b, "051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B"
+		"315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573"
+		"DF883D2C34F1EF451FD46B503F00")) ABORT;
+	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
+
+	if (!BN_hex2bn(&x, "C6858E06B70404E9CD9E3ECB662395B4429C648139053F"
+		"B521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B"
+		"3C1856A429BF97E7E31C2E5BD66")) ABORT;
+	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT;
+	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (!BN_hex2bn(&z, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+		"FFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5"
+		"C9B8899C47AEBB6FB71E91386409")) ABORT;
+	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
+
+	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
+	fprintf(stdout, "\nNIST curve P-521 -- Generator:\n     x = 0x");
+	BN_print_fp(stdout, x);
+	fprintf(stdout, "\n     y = 0x");
+	BN_print_fp(stdout, y);
+	fprintf(stdout, "\n");
+	/* G_y value taken from the standard: */
+	if (!BN_hex2bn(&z, "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579"
+		"B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C"
+		"7086A272C24088BE94769FD16650")) ABORT;
+	if (0 != BN_cmp(y, z)) ABORT;
+	
+	fprintf(stdout, "verify degree ...");
+	if (EC_GROUP_get_degree(group) != 521) ABORT;
+	fprintf(stdout, " ok\n");
+
+ 	group_order_tests(group);
+
+	if (!(P_521 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
+	if (!EC_GROUP_copy(P_521, group)) ABORT;
+
+
+	/* more tests using the last curve */
+
+	if (!EC_POINT_copy(Q, P)) ABORT;
+	if (EC_POINT_is_at_infinity(group, Q)) ABORT;
+	if (!EC_POINT_dbl(group, P, P, ctx)) ABORT;
+	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (!EC_POINT_invert(group, Q, ctx)) ABORT; /* P = -2Q */
+
+	if (!EC_POINT_add(group, R, P, Q, ctx)) ABORT;
+	if (!EC_POINT_add(group, R, R, Q, ctx)) ABORT;
+	if (!EC_POINT_is_at_infinity(group, R)) ABORT; /* R = P + 2Q */
+
+	{
+		const EC_POINT *points[4];
+		const BIGNUM *scalars[4];
+		BIGNUM scalar3;
+	
+		if (EC_POINT_is_at_infinity(group, Q)) ABORT;
+		points[0] = Q;
+		points[1] = Q;
+		points[2] = Q;
+		points[3] = Q;
+
+		if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
+		if (!BN_add(y, z, BN_value_one())) ABORT;
+		if (BN_is_odd(y)) ABORT;
+		if (!BN_rshift1(y, y)) ABORT;
+		scalars[0] = y; /* (group order + 1)/2,  so  y*Q + y*Q = Q */
+		scalars[1] = y;
+
+		fprintf(stdout, "combined multiplication ...");
+		fflush(stdout);
+
+		/* z is still the group order */
+		if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT;
+		if (!EC_POINTs_mul(group, R, z, 2, points, scalars, ctx)) ABORT;
+		if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT;
+		if (0 != EC_POINT_cmp(group, R, Q, ctx)) ABORT;
+
+		fprintf(stdout, ".");
+		fflush(stdout);
+
+		if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0)) ABORT;
+		if (!BN_add(z, z, y)) ABORT;
+		BN_set_negative(z, 1);
+		scalars[0] = y;
+		scalars[1] = z; /* z = -(order + y) */
+
+		if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT;
+		if (!EC_POINT_is_at_infinity(group, P)) ABORT;
+
+		fprintf(stdout, ".");
+		fflush(stdout);
+
+		if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0)) ABORT;
+		if (!BN_add(z, x, y)) ABORT;
+		BN_set_negative(z, 1);
+		scalars[0] = x;
+		scalars[1] = y;
+		scalars[2] = z; /* z = -(x+y) */
+
+		BN_init(&scalar3);
+		BN_zero(&scalar3);
+		scalars[3] = &scalar3;
+
+		if (!EC_POINTs_mul(group, P, NULL, 4, points, scalars, ctx)) ABORT;
+		if (!EC_POINT_is_at_infinity(group, P)) ABORT;
+
+		fprintf(stdout, " ok\n\n");
+
+		BN_free(&scalar3);
+	}
+
+
+#if 0
+	timings(P_160, TIMING_BASE_PT, ctx);
+	timings(P_160, TIMING_RAND_PT, ctx);
+	timings(P_160, TIMING_SIMUL, ctx);
+	timings(P_192, TIMING_BASE_PT, ctx);
+	timings(P_192, TIMING_RAND_PT, ctx);
+	timings(P_192, TIMING_SIMUL, ctx);
+	timings(P_224, TIMING_BASE_PT, ctx);
+	timings(P_224, TIMING_RAND_PT, ctx);
+	timings(P_224, TIMING_SIMUL, ctx);
+	timings(P_256, TIMING_BASE_PT, ctx);
+	timings(P_256, TIMING_RAND_PT, ctx);
+	timings(P_256, TIMING_SIMUL, ctx);
+	timings(P_384, TIMING_BASE_PT, ctx);
+	timings(P_384, TIMING_RAND_PT, ctx);
+	timings(P_384, TIMING_SIMUL, ctx);
+	timings(P_521, TIMING_BASE_PT, ctx);
+	timings(P_521, TIMING_RAND_PT, ctx);
+	timings(P_521, TIMING_SIMUL, ctx);
+#endif
+
+
+	if (ctx)
+		BN_CTX_free(ctx);
+	BN_free(p); BN_free(a);	BN_free(b);
+	EC_GROUP_free(group);
+	EC_POINT_free(P);
+	EC_POINT_free(Q);
+	EC_POINT_free(R);
+	BN_free(x); BN_free(y); BN_free(z);
+
+	if (P_160) EC_GROUP_free(P_160);
+	if (P_192) EC_GROUP_free(P_192);
+	if (P_224) EC_GROUP_free(P_224);
+	if (P_256) EC_GROUP_free(P_256);
+	if (P_384) EC_GROUP_free(P_384);
+	if (P_521) EC_GROUP_free(P_521);
+
+	}
+
+/* Change test based on whether binary point compression is enabled or not. */
+#ifdef OPENSSL_EC_BIN_PT_COMP
+#define CHAR2_CURVE_TEST_INTERNAL(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \
+	if (!BN_hex2bn(&x, _x)) ABORT; \
+	if (!EC_POINT_set_compressed_coordinates_GF2m(group, P, x, _y_bit, ctx)) ABORT; \
+	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; \
+	if (!BN_hex2bn(&z, _order)) ABORT; \
+	if (!BN_hex2bn(&cof, _cof)) ABORT; \
+	if (!EC_GROUP_set_generator(group, P, z, cof)) ABORT; \
+	if (!EC_POINT_get_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT; \
+	fprintf(stdout, "\n%s -- Generator:\n     x = 0x", _name); \
+	BN_print_fp(stdout, x); \
+	fprintf(stdout, "\n     y = 0x"); \
+	BN_print_fp(stdout, y); \
+	fprintf(stdout, "\n"); \
+	/* G_y value taken from the standard: */ \
+	if (!BN_hex2bn(&z, _y)) ABORT; \
+	if (0 != BN_cmp(y, z)) ABORT;
+#else 
+#define CHAR2_CURVE_TEST_INTERNAL(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \
+	if (!BN_hex2bn(&x, _x)) ABORT; \
+	if (!BN_hex2bn(&y, _y)) ABORT; \
+	if (!EC_POINT_set_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT; \
+	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; \
+	if (!BN_hex2bn(&z, _order)) ABORT; \
+	if (!BN_hex2bn(&cof, _cof)) ABORT; \
+	if (!EC_GROUP_set_generator(group, P, z, cof)) ABORT; \
+	fprintf(stdout, "\n%s -- Generator:\n     x = 0x", _name); \
+	BN_print_fp(stdout, x); \
+	fprintf(stdout, "\n     y = 0x"); \
+	BN_print_fp(stdout, y); \
+	fprintf(stdout, "\n");
+#endif
+
+#define CHAR2_CURVE_TEST(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \
+	if (!BN_hex2bn(&p, _p)) ABORT; \
+	if (!BN_hex2bn(&a, _a)) ABORT; \
+	if (!BN_hex2bn(&b, _b)) ABORT; \
+	if (!EC_GROUP_set_curve_GF2m(group, p, a, b, ctx)) ABORT; \
+	CHAR2_CURVE_TEST_INTERNAL(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \
+	fprintf(stdout, "verify degree ..."); \
+	if (EC_GROUP_get_degree(group) != _degree) ABORT; \
+	fprintf(stdout, " ok\n"); \
+	group_order_tests(group); \
+	if (!(_variable = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; \
+	if (!EC_GROUP_copy(_variable, group)) ABORT; \
+
+#ifndef OPENSSL_NO_EC2M
+
+static void char2_field_tests(void)
+	{
+	BN_CTX *ctx = NULL;
+	BIGNUM *p, *a, *b;
+	EC_GROUP *group;
+	EC_GROUP *C2_K163 = NULL, *C2_K233 = NULL, *C2_K283 = NULL, *C2_K409 = NULL, *C2_K571 = NULL;
+	EC_GROUP *C2_B163 = NULL, *C2_B233 = NULL, *C2_B283 = NULL, *C2_B409 = NULL, *C2_B571 = NULL;
+	EC_POINT *P, *Q, *R;
+	BIGNUM *x, *y, *z, *cof;
+	unsigned char buf[100];
+	size_t i, len;
+	int k;
+	
+#if 1 /* optional */
+	ctx = BN_CTX_new();
+	if (!ctx) ABORT;
+#endif
+
+	p = BN_new();
+	a = BN_new();
+	b = BN_new();
+	if (!p || !a || !b) ABORT;
+
+	if (!BN_hex2bn(&p, "13")) ABORT;
+	if (!BN_hex2bn(&a, "3")) ABORT;
+	if (!BN_hex2bn(&b, "1")) ABORT;
+	
+	group = EC_GROUP_new(EC_GF2m_simple_method()); /* applications should use EC_GROUP_new_curve_GF2m
+	                                                * so that the library gets to choose the EC_METHOD */
+	if (!group) ABORT;
+	if (!EC_GROUP_set_curve_GF2m(group, p, a, b, ctx)) ABORT;
+
+	{
+		EC_GROUP *tmp;
+		tmp = EC_GROUP_new(EC_GROUP_method_of(group));
+		if (!tmp) ABORT;
+		if (!EC_GROUP_copy(tmp, group)) ABORT;
+		EC_GROUP_free(group);
+		group = tmp;
+	}
+	
+	if (!EC_GROUP_get_curve_GF2m(group, p, a, b, ctx)) ABORT;
+
+	fprintf(stdout, "Curve defined by Weierstrass equation\n     y^2 + x*y = x^3 + a*x^2 + b  (mod 0x");
+	BN_print_fp(stdout, p);
+	fprintf(stdout, ")\n     a = 0x");
+	BN_print_fp(stdout, a);
+	fprintf(stdout, "\n     b = 0x");
+	BN_print_fp(stdout, b);
+	fprintf(stdout, "\n(0x... means binary polynomial)\n");
+
+	P = EC_POINT_new(group);
+	Q = EC_POINT_new(group);
+	R = EC_POINT_new(group);
+	if (!P || !Q || !R) ABORT;
+	
+	if (!EC_POINT_set_to_infinity(group, P)) ABORT;
+	if (!EC_POINT_is_at_infinity(group, P)) ABORT;
+
+	buf[0] = 0;
+	if (!EC_POINT_oct2point(group, Q, buf, 1, ctx)) ABORT;
+
+	if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;
+	if (!EC_POINT_is_at_infinity(group, P)) ABORT;
+
+	x = BN_new();
+	y = BN_new();
+	z = BN_new();
+	cof = BN_new();
+	if (!x || !y || !z || !cof) ABORT;
+
+	if (!BN_hex2bn(&x, "6")) ABORT;
+/* Change test based on whether binary point compression is enabled or not. */
+#ifdef OPENSSL_EC_BIN_PT_COMP
+	if (!EC_POINT_set_compressed_coordinates_GF2m(group, Q, x, 1, ctx)) ABORT;
+#else
+	if (!BN_hex2bn(&y, "8")) ABORT;
+	if (!EC_POINT_set_affine_coordinates_GF2m(group, Q, x, y, ctx)) ABORT;
+#endif
+	if (!EC_POINT_is_on_curve(group, Q, ctx))
+		{
+/* Change test based on whether binary point compression is enabled or not. */
+#ifdef OPENSSL_EC_BIN_PT_COMP
+		if (!EC_POINT_get_affine_coordinates_GF2m(group, Q, x, y, ctx)) ABORT;
+#endif
+		fprintf(stderr, "Point is not on curve: x = 0x");
+		BN_print_fp(stderr, x);
+		fprintf(stderr, ", y = 0x");
+		BN_print_fp(stderr, y);
+		fprintf(stderr, "\n");
+		ABORT;
+		}
+
+	fprintf(stdout, "A cyclic subgroup:\n");
+	k = 100;
+	do
+		{
+		if (k-- == 0) ABORT;
+
+		if (EC_POINT_is_at_infinity(group, P))
+			fprintf(stdout, "     point at infinity\n");
+		else
+			{
+			if (!EC_POINT_get_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT;
+
+			fprintf(stdout, "     x = 0x");
+			BN_print_fp(stdout, x);
+			fprintf(stdout, ", y = 0x");
+			BN_print_fp(stdout, y);
+			fprintf(stdout, "\n");
+			}
+		
+		if (!EC_POINT_copy(R, P)) ABORT;
+		if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;
+		}
+	while (!EC_POINT_is_at_infinity(group, P));
+
+	if (!EC_POINT_add(group, P, Q, R, ctx)) ABORT;
+	if (!EC_POINT_is_at_infinity(group, P)) ABORT;
+
+/* Change test based on whether binary point compression is enabled or not. */
+#ifdef OPENSSL_EC_BIN_PT_COMP
+	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf, sizeof buf, ctx);
+	if (len == 0) ABORT;
+	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
+	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
+	fprintf(stdout, "Generator as octet string, compressed form:\n     ");
+	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
+#endif
+	
+	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx);
+	if (len == 0) ABORT;
+	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
+	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
+	fprintf(stdout, "\nGenerator as octet string, uncompressed form:\n     ");
+	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
+	
+/* Change test based on whether binary point compression is enabled or not. */
+#ifdef OPENSSL_EC_BIN_PT_COMP
+	len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx);
+	if (len == 0) ABORT;
+	if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
+	if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
+	fprintf(stdout, "\nGenerator as octet string, hybrid form:\n     ");
+	for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
+#endif
+
+	fprintf(stdout, "\n");
+	
+	if (!EC_POINT_invert(group, P, ctx)) ABORT;
+	if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT;
+
+
+	/* Curve K-163 (FIPS PUB 186-2, App. 6) */
+	CHAR2_CURVE_TEST
+		(
+		"NIST curve K-163",
+		"0800000000000000000000000000000000000000C9",
+		"1",
+		"1",
+		"02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8",
+		"0289070FB05D38FF58321F2E800536D538CCDAA3D9",
+		1,
+		"04000000000000000000020108A2E0CC0D99F8A5EF",
+		"2",
+		163,
+		C2_K163
+		);
+
+	/* Curve B-163 (FIPS PUB 186-2, App. 6) */
+	CHAR2_CURVE_TEST
+		(
+		"NIST curve B-163",
+		"0800000000000000000000000000000000000000C9",
+		"1",
+		"020A601907B8C953CA1481EB10512F78744A3205FD",
+		"03F0EBA16286A2D57EA0991168D4994637E8343E36",
+		"00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1",
+		1,
+		"040000000000000000000292FE77E70C12A4234C33",
+		"2",
+		163,
+		C2_B163
+		);
+
+	/* Curve K-233 (FIPS PUB 186-2, App. 6) */
+	CHAR2_CURVE_TEST
+		(
+		"NIST curve K-233",
+		"020000000000000000000000000000000000000004000000000000000001",
+		"0",
+		"1",
+		"017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126",
+		"01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3",
+		0,
+		"008000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF",
+		"4",
+		233,
+		C2_K233
+		);
+
+	/* Curve B-233 (FIPS PUB 186-2, App. 6) */
+	CHAR2_CURVE_TEST
+		(
+		"NIST curve B-233",
+		"020000000000000000000000000000000000000004000000000000000001",
+		"000000000000000000000000000000000000000000000000000000000001",
+		"0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD",
+		"00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B",
+		"01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052",
+		1,
+		"01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7",
+		"2",
+		233,
+		C2_B233
+		);
+
+	/* Curve K-283 (FIPS PUB 186-2, App. 6) */
+	CHAR2_CURVE_TEST
+		(
+		"NIST curve K-283",
+		"0800000000000000000000000000000000000000000000000000000000000000000010A1",
+		"0",
+		"1",
+		"0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836",
+		"01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259",
+		0,
+		"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61",
+		"4",
+		283,
+		C2_K283
+		);
+
+	/* Curve B-283 (FIPS PUB 186-2, App. 6) */
+	CHAR2_CURVE_TEST
+		(
+		"NIST curve B-283",
+		"0800000000000000000000000000000000000000000000000000000000000000000010A1",
+		"000000000000000000000000000000000000000000000000000000000000000000000001",
+		"027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5",
+		"05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053",
+		"03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4",
+		1,
+		"03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307",
+		"2",
+		283,
+		C2_B283
+		);
+
+	/* Curve K-409 (FIPS PUB 186-2, App. 6) */
+	CHAR2_CURVE_TEST
+		(
+		"NIST curve K-409",
+		"02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001",
+		"0",
+		"1",
+		"0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746",
+		"01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B",
+		1,
+		"007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF",
+		"4",
+		409,
+		C2_K409
+		);
+
+	/* Curve B-409 (FIPS PUB 186-2, App. 6) */
+	CHAR2_CURVE_TEST
+		(
+		"NIST curve B-409",
+		"02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001",
+		"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
+		"0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F",
+		"015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7",
+		"0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706",
+		1,
+		"010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173",
+		"2",
+		409,
+		C2_B409
+		);
+
+	/* Curve K-571 (FIPS PUB 186-2, App. 6) */
+	CHAR2_CURVE_TEST
+		(
+		"NIST curve K-571",
+		"80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425",
+		"0",
+		"1",
+		"026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972",
+		"0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3",
+		0,
+		"020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001",
+		"4",
+		571,
+		C2_K571
+		);
+
+	/* Curve B-571 (FIPS PUB 186-2, App. 6) */
+	CHAR2_CURVE_TEST
+		(
+		"NIST curve B-571",
+		"80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425",
+		"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
+		"02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A",
+		"0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19",
+		"037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B",
+		1,
+		"03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47",
+		"2",
+		571,
+		C2_B571
+		);
+
+	/* more tests using the last curve */
+
+	if (!EC_POINT_copy(Q, P)) ABORT;
+	if (EC_POINT_is_at_infinity(group, Q)) ABORT;
+	if (!EC_POINT_dbl(group, P, P, ctx)) ABORT;
+	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (!EC_POINT_invert(group, Q, ctx)) ABORT; /* P = -2Q */
+
+	if (!EC_POINT_add(group, R, P, Q, ctx)) ABORT;
+	if (!EC_POINT_add(group, R, R, Q, ctx)) ABORT;
+	if (!EC_POINT_is_at_infinity(group, R)) ABORT; /* R = P + 2Q */
+
+	{
+		const EC_POINT *points[3];
+		const BIGNUM *scalars[3];
+	
+		if (EC_POINT_is_at_infinity(group, Q)) ABORT;
+		points[0] = Q;
+		points[1] = Q;
+		points[2] = Q;
+
+		if (!BN_add(y, z, BN_value_one())) ABORT;
+		if (BN_is_odd(y)) ABORT;
+		if (!BN_rshift1(y, y)) ABORT;
+		scalars[0] = y; /* (group order + 1)/2,  so  y*Q + y*Q = Q */
+		scalars[1] = y;
+
+		fprintf(stdout, "combined multiplication ...");
+		fflush(stdout);
+
+		/* z is still the group order */
+		if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT;
+		if (!EC_POINTs_mul(group, R, z, 2, points, scalars, ctx)) ABORT;
+		if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT;
+		if (0 != EC_POINT_cmp(group, R, Q, ctx)) ABORT;
+
+		fprintf(stdout, ".");
+		fflush(stdout);
+
+		if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0)) ABORT;
+		if (!BN_add(z, z, y)) ABORT;
+		BN_set_negative(z, 1);
+		scalars[0] = y;
+		scalars[1] = z; /* z = -(order + y) */
+
+		if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT;
+		if (!EC_POINT_is_at_infinity(group, P)) ABORT;
+
+		fprintf(stdout, ".");
+		fflush(stdout);
+
+		if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0)) ABORT;
+		if (!BN_add(z, x, y)) ABORT;
+		BN_set_negative(z, 1);
+		scalars[0] = x;
+		scalars[1] = y;
+		scalars[2] = z; /* z = -(x+y) */
+
+		if (!EC_POINTs_mul(group, P, NULL, 3, points, scalars, ctx)) ABORT;
+		if (!EC_POINT_is_at_infinity(group, P)) ABORT;
+
+		fprintf(stdout, " ok\n\n");
+	}
+
+
+#if 0
+	timings(C2_K163, TIMING_BASE_PT, ctx);
+	timings(C2_K163, TIMING_RAND_PT, ctx);
+	timings(C2_K163, TIMING_SIMUL, ctx);
+	timings(C2_B163, TIMING_BASE_PT, ctx);
+	timings(C2_B163, TIMING_RAND_PT, ctx);
+	timings(C2_B163, TIMING_SIMUL, ctx);
+	timings(C2_K233, TIMING_BASE_PT, ctx);
+	timings(C2_K233, TIMING_RAND_PT, ctx);
+	timings(C2_K233, TIMING_SIMUL, ctx);
+	timings(C2_B233, TIMING_BASE_PT, ctx);
+	timings(C2_B233, TIMING_RAND_PT, ctx);
+	timings(C2_B233, TIMING_SIMUL, ctx);
+	timings(C2_K283, TIMING_BASE_PT, ctx);
+	timings(C2_K283, TIMING_RAND_PT, ctx);
+	timings(C2_K283, TIMING_SIMUL, ctx);
+	timings(C2_B283, TIMING_BASE_PT, ctx);
+	timings(C2_B283, TIMING_RAND_PT, ctx);
+	timings(C2_B283, TIMING_SIMUL, ctx);
+	timings(C2_K409, TIMING_BASE_PT, ctx);
+	timings(C2_K409, TIMING_RAND_PT, ctx);
+	timings(C2_K409, TIMING_SIMUL, ctx);
+	timings(C2_B409, TIMING_BASE_PT, ctx);
+	timings(C2_B409, TIMING_RAND_PT, ctx);
+	timings(C2_B409, TIMING_SIMUL, ctx);
+	timings(C2_K571, TIMING_BASE_PT, ctx);
+	timings(C2_K571, TIMING_RAND_PT, ctx);
+	timings(C2_K571, TIMING_SIMUL, ctx);
+	timings(C2_B571, TIMING_BASE_PT, ctx);
+	timings(C2_B571, TIMING_RAND_PT, ctx);
+	timings(C2_B571, TIMING_SIMUL, ctx);
+#endif
+
+
+	if (ctx)
+		BN_CTX_free(ctx);
+	BN_free(p); BN_free(a);	BN_free(b);
+	EC_GROUP_free(group);
+	EC_POINT_free(P);
+	EC_POINT_free(Q);
+	EC_POINT_free(R);
+	BN_free(x); BN_free(y); BN_free(z); BN_free(cof);
+
+	if (C2_K163) EC_GROUP_free(C2_K163);
+	if (C2_B163) EC_GROUP_free(C2_B163);
+	if (C2_K233) EC_GROUP_free(C2_K233);
+	if (C2_B233) EC_GROUP_free(C2_B233);
+	if (C2_K283) EC_GROUP_free(C2_K283);
+	if (C2_B283) EC_GROUP_free(C2_B283);
+	if (C2_K409) EC_GROUP_free(C2_K409);
+	if (C2_B409) EC_GROUP_free(C2_B409);
+	if (C2_K571) EC_GROUP_free(C2_K571);
+	if (C2_B571) EC_GROUP_free(C2_B571);
+
+	}
+#endif
+
+static void internal_curve_test(void)
+	{
+	EC_builtin_curve *curves = NULL;
+	size_t crv_len = 0, n = 0;
+	int    ok = 1;
+
+	crv_len = EC_get_builtin_curves(NULL, 0);
+
+	curves = OPENSSL_malloc(sizeof(EC_builtin_curve) * crv_len);
+
+	if (curves == NULL)
+		return;
+
+	if (!EC_get_builtin_curves(curves, crv_len))
+		{
+		OPENSSL_free(curves);
+		return;
+		}
+
+	fprintf(stdout, "testing internal curves: ");
+		
+	for (n = 0; n < crv_len; n++)
+		{
+		EC_GROUP *group = NULL;
+		int nid = curves[n].nid;
+		if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL)
+			{
+			ok = 0;
+			fprintf(stdout, "\nEC_GROUP_new_curve_name() failed with"
+				" curve %s\n", OBJ_nid2sn(nid));
+			/* try next curve */
+			continue;
+			}
+		if (!EC_GROUP_check(group, NULL))
+			{
+			ok = 0;
+			fprintf(stdout, "\nEC_GROUP_check() failed with"
+				" curve %s\n", OBJ_nid2sn(nid));
+			EC_GROUP_free(group);
+			/* try the next curve */
+			continue;
+			}
+		fprintf(stdout, ".");
+		fflush(stdout);
+		EC_GROUP_free(group);
+		}
+	if (ok)
+		fprintf(stdout, " ok\n\n");
+	else
+		{
+		fprintf(stdout, " failed\n\n");
+		ABORT;
+		}
+	OPENSSL_free(curves);
+	return;
+	}
+
+#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
+/* nistp_test_params contains magic numbers for testing our optimized
+ * implementations of several NIST curves with characteristic > 3. */
+struct nistp_test_params
+	{
+	const EC_METHOD* (*meth) ();
+	int degree;
+	/* Qx, Qy and D are taken from
+	 * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/ECDSA_Prime.pdf
+	 * Otherwise, values are standard curve parameters from FIPS 180-3 */
+	const char *p, *a, *b, *Qx, *Qy, *Gx, *Gy, *order, *d;
+	};
+
+static const struct nistp_test_params nistp_tests_params[] =
+	{
+		{
+		/* P-224 */
+		EC_GFp_nistp224_method,
+		224,
+		"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", /* p */
+		"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", /* a */
+		"B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", /* b */
+		"E84FB0B8E7000CB657D7973CF6B42ED78B301674276DF744AF130B3E", /* Qx */
+		"4376675C6FC5612C21A0FF2D2A89D2987DF7A2BC52183B5982298555", /* Qy */
+		"B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", /* Gx */
+		"BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", /* Gy */
+		"FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", /* order */
+		"3F0C488E987C80BE0FEE521F8D90BE6034EC69AE11CA72AA777481E8", /* d */
+		},
+		{
+		/* P-256 */
+		EC_GFp_nistp256_method,
+		256,
+		"ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", /* p */
+		"ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", /* a */
+		"5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", /* b */
+		"b7e08afdfe94bad3f1dc8c734798ba1c62b3a0ad1e9ea2a38201cd0889bc7a19", /* Qx */
+		"3603f747959dbf7a4bb226e41928729063adc7ae43529e61b563bbc606cc5e09", /* Qy */
+		"6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", /* Gx */
+		"4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", /* Gy */
+		"ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", /* order */
+		"c477f9f65c22cce20657faa5b2d1d8122336f851a508a1ed04e479c34985bf96", /* d */
+		},
+		{
+		/* P-521 */
+		EC_GFp_nistp521_method,
+		521,
+		"1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", /* p */
+		"1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc", /* a */
+		"051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", /* b */
+		"0098e91eef9a68452822309c52fab453f5f117c1da8ed796b255e9ab8f6410cca16e59df403a6bdc6ca467a37056b1e54b3005d8ac030decfeb68df18b171885d5c4", /* Qx */
+		"0164350c321aecfc1cca1ba4364c9b15656150b4b78d6a48d7d28e7f31985ef17be8554376b72900712c4b83ad668327231526e313f5f092999a4632fd50d946bc2e", /* Qy */
+		"c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", /* Gx */
+		"11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", /* Gy */
+		"1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409", /* order */
+		"0100085f47b8e1b8b11b7eb33028c0b2888e304bfc98501955b45bba1478dc184eeedf09b86a5f7c21994406072787205e69a63709fe35aa93ba333514b24f961722", /* d */
+		},
+	};
+
+void nistp_single_test(const struct nistp_test_params *test)
+	{
+	BN_CTX *ctx;
+	BIGNUM *p, *a, *b, *x, *y, *n, *m, *order;
+	EC_GROUP *NISTP;
+	EC_POINT *G, *P, *Q, *Q_CHECK;
+
+	fprintf(stdout, "\nNIST curve P-%d (optimised implementation):\n", test->degree);
+	ctx = BN_CTX_new();
+	p = BN_new();
+	a = BN_new();
+	b = BN_new();
+	x = BN_new(); y = BN_new();
+	m = BN_new(); n = BN_new(); order = BN_new();
+
+	NISTP = EC_GROUP_new(test->meth());
+	if(!NISTP) ABORT;
+	if (!BN_hex2bn(&p, test->p)) ABORT;
+	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
+	if (!BN_hex2bn(&a, test->a)) ABORT;
+	if (!BN_hex2bn(&b, test->b)) ABORT;
+	if (!EC_GROUP_set_curve_GFp(NISTP, p, a, b, ctx)) ABORT;
+	G = EC_POINT_new(NISTP);
+	P = EC_POINT_new(NISTP);
+	Q = EC_POINT_new(NISTP);
+	Q_CHECK = EC_POINT_new(NISTP);
+	if(!BN_hex2bn(&x, test->Qx)) ABORT;
+	if(!BN_hex2bn(&y, test->Qy)) ABORT;
+	if(!EC_POINT_set_affine_coordinates_GFp(NISTP, Q_CHECK, x, y, ctx)) ABORT;
+	if (!BN_hex2bn(&x, test->Gx)) ABORT;
+	if (!BN_hex2bn(&y, test->Gy)) ABORT;
+	if (!EC_POINT_set_affine_coordinates_GFp(NISTP, G, x, y, ctx)) ABORT;
+	if (!BN_hex2bn(&order, test->order)) ABORT;
+	if (!EC_GROUP_set_generator(NISTP, G, order, BN_value_one())) ABORT;
+
+	fprintf(stdout, "verify degree ... ");
+	if (EC_GROUP_get_degree(NISTP) != test->degree) ABORT;
+	fprintf(stdout, "ok\n");
+
+	fprintf(stdout, "NIST test vectors ... ");
+	if (!BN_hex2bn(&n, test->d)) ABORT;
+	/* fixed point multiplication */
+	EC_POINT_mul(NISTP, Q, n, NULL, NULL, ctx);
+	if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
+	/* random point multiplication */
+	EC_POINT_mul(NISTP, Q, NULL, G, n, ctx);
+	if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
+
+	/* set generator to P = 2*G, where G is the standard generator */
+	if (!EC_POINT_dbl(NISTP, P, G, ctx)) ABORT;
+	if (!EC_GROUP_set_generator(NISTP, P, order, BN_value_one())) ABORT;
+	/* set the scalar to m=n/2, where n is the NIST test scalar */
+	if (!BN_rshift(m, n, 1)) ABORT;
+
+	/* test the non-standard generator */
+	/* fixed point multiplication */
+	EC_POINT_mul(NISTP, Q, m, NULL, NULL, ctx);
+	if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
+	/* random point multiplication */
+	EC_POINT_mul(NISTP, Q, NULL, P, m, ctx);
+	if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
+
+	/* now repeat all tests with precomputation */
+	if (!EC_GROUP_precompute_mult(NISTP, ctx)) ABORT;
+
+	/* fixed point multiplication */
+	EC_POINT_mul(NISTP, Q, m, NULL, NULL, ctx);
+	if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
+	/* random point multiplication */
+	EC_POINT_mul(NISTP, Q, NULL, P, m, ctx);
+	if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
+
+	/* reset generator */
+	if (!EC_GROUP_set_generator(NISTP, G, order, BN_value_one())) ABORT;
+	/* fixed point multiplication */
+	EC_POINT_mul(NISTP, Q, n, NULL, NULL, ctx);
+	if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
+	/* random point multiplication */
+	EC_POINT_mul(NISTP, Q, NULL, G, n, ctx);
+	if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
+
+	fprintf(stdout, "ok\n");
+	group_order_tests(NISTP);
+#if 0
+	timings(NISTP, TIMING_BASE_PT, ctx);
+	timings(NISTP, TIMING_RAND_PT, ctx);
+#endif
+	EC_GROUP_free(NISTP);
+	EC_POINT_free(G);
+	EC_POINT_free(P);
+	EC_POINT_free(Q);
+	EC_POINT_free(Q_CHECK);
+	BN_free(n);
+	BN_free(m);
+	BN_free(p);
+	BN_free(a);
+	BN_free(b);
+	BN_free(x);
+	BN_free(y);
+	BN_free(order);
+	BN_CTX_free(ctx);
+	}
+
+void nistp_tests()
+	{
+	unsigned i;
+
+	for (i = 0; i < sizeof(nistp_tests_params) / sizeof(struct nistp_test_params); i++)
+		{
+		nistp_single_test(&nistp_tests_params[i]);
+		}
+	}
+#endif
+
+static const char rnd_seed[] = "string to make the random number generator think it has entropy";
+
+int main(int argc, char *argv[])
+	{	
+	
+	/* enable memory leak checking unless explicitly disabled */
+	if (!((getenv("OPENSSL_DEBUG_MEMORY") != NULL) && (0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off"))))
+		{
+		CRYPTO_malloc_debug_init();
+		CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
+		}
+	else
+		{
+		/* OPENSSL_DEBUG_MEMORY=off */
+		CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0);
+		}
+	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
+	ERR_load_crypto_strings();
+
+	RAND_seed(rnd_seed, sizeof rnd_seed); /* or BN_generate_prime may fail */
+
+	prime_field_tests();
+	puts("");
+#ifndef OPENSSL_NO_EC2M
+	char2_field_tests();
+#endif
+#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
+	nistp_tests();
+#endif
+	/* test the internal curves */
+	internal_curve_test();
+
+#ifndef OPENSSL_NO_ENGINE
+	ENGINE_cleanup();
+#endif
+	CRYPTO_cleanup_all_ex_data();
+	ERR_free_strings();
+	ERR_remove_thread_state(NULL);
+	CRYPTO_mem_leaks_fp(stderr);
+	
+	return 0;
+	}
+#endif