More 'TODO' items.
diff --git a/crypto/ec/ec.h b/crypto/ec/ec.h
index db410c1..1b50a96 100644
--- a/crypto/ec/ec.h
+++ b/crypto/ec/ec.h
@@ -122,11 +122,16 @@
 int EC_POINT_copy(EC_POINT *, const EC_POINT *);
  
 int EC_POINT_set_to_infinity(const EC_GROUP *, EC_POINT *);
+int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *, EC_POINT *,
+	const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *);
+int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *, const EC_POINT *,
+	BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *);
 int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *, EC_POINT *,
 	const BIGNUM *x, const BIGNUM *y, BN_CTX *);
 int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *, const EC_POINT *,
 	BIGNUM *x, BIGNUM *y, BN_CTX *);
-/* TODO: other 'set' and 'get' functions for EC_POINTs */
+int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *, EC_POINT *,
+	const BIGNUM *x, int y_bit, BN_CTX *);
 
 size_t EC_POINT_point2oct(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form,
         unsigned char *buf, size_t len, BN_CTX *);
@@ -135,9 +140,11 @@
 
 int EC_POINT_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *);
 int EC_POINT_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *);
+int EC_POINT_invert(const EC_GROUP *, EC_POINT *, BN_CTX *);
 
 int EC_POINT_is_at_infinity(const EC_GROUP *, const EC_POINT *);
 int EC_POINT_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *);
+int EC_POINT_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, BN_CTX *);
 
 int EC_POINT_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *);
 
@@ -155,6 +162,7 @@
 /* Error codes for the EC functions. */
 
 /* Function codes. */
+#define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP		 127
 #define EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR		 100
 #define EC_F_EC_GFP_SIMPLE_MAKE_AFFINE			 101
 #define EC_F_EC_GFP_SIMPLE_OCT2POINT			 102
@@ -167,9 +175,11 @@
 #define EC_F_EC_GROUP_SET_EXTRA_DATA			 109
 #define EC_F_EC_GROUP_SET_GENERATOR			 110
 #define EC_F_EC_POINT_ADD				 111
+#define EC_F_EC_POINT_CMP				 123
 #define EC_F_EC_POINT_COPY				 112
 #define EC_F_EC_POINT_DBL				 113
 #define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP	 114
+#define EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP	 124
 #define EC_F_EC_POINT_IS_AT_INFINITY			 115
 #define EC_F_EC_POINT_IS_ON_CURVE			 116
 #define EC_F_EC_POINT_MAKE_AFFINE			 117
@@ -177,12 +187,15 @@
 #define EC_F_EC_POINT_OCT2POINT				 119
 #define EC_F_EC_POINT_POINT2OCT				 120
 #define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP	 121
+#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			 122
 
 /* Reason codes. */
 #define EC_R_BUFFER_TOO_SMALL				 100
 #define EC_R_INCOMPATIBLE_OBJECTS			 101
 #define EC_R_INVALID_ENCODING				 102
+#define EC_R_INVALID_FIELD				 108
 #define EC_R_INVALID_FORM				 103
 #define EC_R_NO_SUCH_EXTRA_DATA				 104
 #define EC_R_POINT_AT_INFINITY				 105
diff --git a/crypto/ec/ec_err.c b/crypto/ec/ec_err.c
index 620dbd1..cc00532 100644
--- a/crypto/ec/ec_err.c
+++ b/crypto/ec/ec_err.c
@@ -66,6 +66,7 @@
 #ifndef OPENSSL_NO_ERR
 static ERR_STRING_DATA EC_str_functs[]=
 	{
+{ERR_PACK(0,EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP,0),	"EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP"},
 {ERR_PACK(0,EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR,0),	"EC_GFP_SIMPLE_GROUP_SET_GENERATOR"},
 {ERR_PACK(0,EC_F_EC_GFP_SIMPLE_MAKE_AFFINE,0),	"EC_GFP_SIMPLE_MAKE_AFFINE"},
 {ERR_PACK(0,EC_F_EC_GFP_SIMPLE_OCT2POINT,0),	"EC_GFP_SIMPLE_OCT2POINT"},
@@ -78,9 +79,11 @@
 {ERR_PACK(0,EC_F_EC_GROUP_SET_EXTRA_DATA,0),	"EC_GROUP_SET_EXTRA_DATA"},
 {ERR_PACK(0,EC_F_EC_GROUP_SET_GENERATOR,0),	"EC_GROUP_set_generator"},
 {ERR_PACK(0,EC_F_EC_POINT_ADD,0),	"EC_POINT_add"},
+{ERR_PACK(0,EC_F_EC_POINT_CMP,0),	"EC_POINT_cmp"},
 {ERR_PACK(0,EC_F_EC_POINT_COPY,0),	"EC_POINT_copy"},
 {ERR_PACK(0,EC_F_EC_POINT_DBL,0),	"EC_POINT_dbl"},
 {ERR_PACK(0,EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,0),	"EC_POINT_get_affine_coordinates_GFp"},
+{ERR_PACK(0,EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,0),	"EC_POINT_get_Jprojective_coordinates_GFp"},
 {ERR_PACK(0,EC_F_EC_POINT_IS_AT_INFINITY,0),	"EC_POINT_is_at_infinity"},
 {ERR_PACK(0,EC_F_EC_POINT_IS_ON_CURVE,0),	"EC_POINT_is_on_curve"},
 {ERR_PACK(0,EC_F_EC_POINT_MAKE_AFFINE,0),	"EC_POINT_make_affine"},
@@ -88,6 +91,8 @@
 {ERR_PACK(0,EC_F_EC_POINT_OCT2POINT,0),	"EC_POINT_oct2point"},
 {ERR_PACK(0,EC_F_EC_POINT_POINT2OCT,0),	"EC_POINT_point2oct"},
 {ERR_PACK(0,EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,0),	"EC_POINT_set_affine_coordinates_GFp"},
+{ERR_PACK(0,EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP,0),	"EC_POINT_set_compressed_coordinates_GFp"},
+{ERR_PACK(0,EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,0),	"EC_POINT_set_Jprojective_coordinates_GFp"},
 {ERR_PACK(0,EC_F_EC_POINT_SET_TO_INFINITY,0),	"EC_POINT_set_to_infinity"},
 {0,NULL}
 	};
@@ -97,6 +102,7 @@
 {EC_R_BUFFER_TOO_SMALL                   ,"buffer too small"},
 {EC_R_INCOMPATIBLE_OBJECTS               ,"incompatible objects"},
 {EC_R_INVALID_ENCODING                   ,"invalid encoding"},
+{EC_R_INVALID_FIELD                      ,"invalid field"},
 {EC_R_INVALID_FORM                       ,"invalid form"},
 {EC_R_NO_SUCH_EXTRA_DATA                 ,"no such extra data"},
 {EC_R_POINT_AT_INFINITY                  ,"point at infinity"},
diff --git a/crypto/ec/ec_lcl.h b/crypto/ec/ec_lcl.h
index b3f8354..15007d8 100644
--- a/crypto/ec/ec_lcl.h
+++ b/crypto/ec/ec_lcl.h
@@ -63,9 +63,8 @@
  * so all this may change in future versions. */
 
 struct ec_method_st {
-	/* used by EC_GROUP_new, EC_GROUP_set_curve_GFp, EC_GROUP_free, EC_GROUP_copy: */
+	/* used by EC_GROUP_new, EC_GROUP_set_curve_GFp, EC_GROUP_free, EC_GROUP_clear_free, EC_GROUP_copy: */
 	int (*group_init)(EC_GROUP *);
-	/* int (*group_set)(EC_GROUP *, .....); */
 	int (*group_set_curve_GFp)(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
 	void (*group_finish)(EC_GROUP *);
 	void (*group_clear_finish)(EC_GROUP *);
@@ -78,18 +77,28 @@
 	/* TODO: 'set' and 'get' functions for EC_GROUPs */
 
 
-	/* used by EC_POINT_new, EC_POINT_free, EC_POINT_copy: */
+	/* 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, EC_POINT_get_affine_coordinates_GFp,
+	 * EC_POINT_set_compressed_coordinates_GFp:
+	 */
 	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_GFp)(const EC_GROUP *, EC_POINT *,
 		const BIGNUM *x, const BIGNUM *y, BN_CTX *);
 	int (*point_get_affine_coordinates_GFp)(const EC_GROUP *, const EC_POINT *,
 		BIGNUM *x, BIGNUM *y, BN_CTX *);
-	/* TODO: other 'set' and 'get' functions for EC_POINTs */
+	int (*point_set_compressed_coordinates_GFp)(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,
@@ -97,13 +106,17 @@
 	int (*oct2point)(const EC_GROUP *, EC_POINT *,
 	        const unsigned char *buf, size_t len, BN_CTX *);
 
-	/* used by EC_POINT_add, EC_POINT_dbl: */
+	/* 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_make_affine */
+	/* 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: */
 	int (*make_affine)(const EC_GROUP *, EC_POINT *, BN_CTX *);
 
 
@@ -194,19 +207,26 @@
 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_GFp(const EC_GROUP *, EC_POINT *,
 	const BIGNUM *x, const BIGNUM *y, BN_CTX *);
 int ec_GFp_simple_point_get_affine_coordinates_GFp(const EC_GROUP *, const EC_POINT *,
 	BIGNUM *x, BIGNUM *y, BN_CTX *);
-/* TODO: other 'set' and 'get' functions for EC_POINTs */
+int ec_GFp_simple_set_compressed_coordinates_GFp(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_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 *);
diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c
index d0af0d5..8154a17 100644
--- a/crypto/ec/ec_lib.c
+++ b/crypto/ec/ec_lib.c
@@ -149,6 +149,8 @@
 		ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
 		return 0;
 		}
+	if (dest == src)
+		return 1;
 	
 	EC_GROUP_clear_free_extra_data(dest);
 	if (src->extra_data_dup_func)
@@ -334,6 +336,40 @@
 	}
 
 
+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)
 	{
@@ -368,7 +404,21 @@
 	}
 
 
-/* TODO: other 'set' and 'get' functions for EC_POINTs */
+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_GFp == 0)
+		{
+		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;
+		}
+	return group->meth->point_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx);
+	}
 
 
 size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
@@ -437,6 +487,22 @@
 	}
 
 
+int EC_POINT_invert(const EC_GROUP *group, 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 != a->meth)
+		{
+		ECerr(EC_F_EC_POINT_DBL, 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)
@@ -469,6 +535,22 @@
 	}
 
 
+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)
diff --git a/crypto/ec/ecp_mont.c b/crypto/ec/ecp_mont.c
index 17d9a48..5db65ae 100644
--- a/crypto/ec/ecp_mont.c
+++ b/crypto/ec/ecp_mont.c
@@ -71,15 +71,19 @@
 		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_GFp,
 		ec_GFp_simple_point_get_affine_coordinates_GFp,
-		/* TODO: other 'set' and 'get' functions for EC_POINTs */
+		ec_GFp_simple_set_compressed_coordinates_GFp,
 		ec_GFp_simple_point2oct,
 		ec_GFp_simple_oct2point,
 		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_mont_field_mul,
 		ec_GFp_mont_field_sqr,
diff --git a/crypto/ec/ecp_nist.c b/crypto/ec/ecp_nist.c
index df2d614..089e2c6 100644
--- a/crypto/ec/ecp_nist.c
+++ b/crypto/ec/ecp_nist.c
@@ -71,15 +71,19 @@
 		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_GFp,
 		ec_GFp_simple_point_get_affine_coordinates_GFp,
-		/* TODO: other 'set' and 'get' functions for EC_POINTs */
+		ec_GFp_simple_set_compressed_coordinates_GFp,
 		ec_GFp_simple_point2oct,
 		ec_GFp_simple_oct2point,
 		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_nist_field_mul,
 		ec_GFp_nist_field_sqr,
diff --git a/crypto/ec/ecp_recp.c b/crypto/ec/ecp_recp.c
index df7b52b..8afdca1 100644
--- a/crypto/ec/ecp_recp.c
+++ b/crypto/ec/ecp_recp.c
@@ -71,15 +71,19 @@
 		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_GFp,
 		ec_GFp_simple_point_get_affine_coordinates_GFp,
-		/* TODO: other 'set' and 'get' functions for EC_POINTs */
+		ec_GFp_simple_set_compressed_coordinates_GFp,
 		ec_GFp_simple_point2oct,
 		ec_GFp_simple_oct2point,
 		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_recp_field_mul,
 		ec_GFp_recp_field_sqr,
diff --git a/crypto/ec/ecp_smpl.c b/crypto/ec/ecp_smpl.c
index 9d9fe86..d6c3f63 100644
--- a/crypto/ec/ecp_smpl.c
+++ b/crypto/ec/ecp_smpl.c
@@ -75,15 +75,19 @@
 		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_GFp,
 		ec_GFp_simple_point_get_affine_coordinates_GFp,
-		/* TODO: other 'set' and 'get' functions for EC_POINTs */
+		ec_GFp_simple_set_compressed_coordinates_GFp,
 		ec_GFp_simple_point2oct,
 		ec_GFp_simple_oct2point,
 		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_field_mul,
 		ec_GFp_simple_field_sqr,
@@ -114,6 +118,13 @@
 	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_GFP, EC_R_INVALID_FIELD);
+		return 0;
+		}
+
 	if (ctx == NULL)
 		{
 		ctx = new_ctx = BN_CTX_new();
@@ -295,6 +306,16 @@
 	}
 
 
+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);
+/* TODO */
+
+
+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);
+/* TODO */
+
+
 int ec_GFp_simple_point_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
 	const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
 	{
@@ -376,8 +397,14 @@
 	
 	if (BN_is_one(Z_))
 		{
-		if (!BN_copy(x, X_)) goto err;
-		if (!BN_copy(y, Y_)) goto err;
+		if (x != NULL)
+			{
+			if (!BN_copy(x, X_)) goto err;
+			}
+		if (y != NULL)
+			{
+			if (!BN_copy(y, Y_)) goto err;
+			}
 		}
 	else
 		{
@@ -387,10 +414,17 @@
 			goto err;
 			}
 		if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) goto err;
-		if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) goto err;
 	
-		if (!BN_mod_mul(x, X_, Z_2, &group->field, ctx)) goto err;
-		if (!BN_mod_mul(y, Y_, Z_3, &group->field, ctx)) goto err;
+		if (x != NULL)
+			{
+			if (!BN_mod_mul(x, X_, Z_2, &group->field, ctx)) goto err;
+			}
+
+		if (y != NULL)
+			{
+			if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) goto err;
+			if (!BN_mod_mul(y, Y_, Z_3, &group->field, ctx)) goto err;
+			}
 		}
 
 	ret = 1;
@@ -403,7 +437,9 @@
 	}
 
 
-/* TODO: other 'set' and 'get' functions for EC_POINTs */
+int ec_GFp_simple_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
+	const BIGNUM *x, int y_bit, BN_CTX *);
+/* TODO */
 
 
 size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
@@ -467,7 +503,7 @@
 
 		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_bit_set(y, 0))
+		if ((form == POINT_CONVERSION_COMPRESSED || form == POINT_CONVERSION_HYBRID) && BN_is_odd(y))
 			buf[0] = form + 1;
 		else
 			buf[0] = form;
@@ -612,7 +648,7 @@
 			}
 		if (form == POINT_CONVERSION_HYBRID)
 			{
-			if (y_bit != BN_is_bit_set(y, 0))
+			if (y_bit != BN_is_odd(y))
 				{
 				ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
 				goto err;
@@ -659,11 +695,16 @@
 			goto err;
 			}
 
-		if (y_bit != BN_is_bit_set(y, 0))
+		if (y_bit != BN_is_odd(y))
 			{
+			if (BN_is_zero(y))
+				{
+				ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+				goto err;
+				}
 			if (!BN_usub(y, &group->field, y)) goto err;
 			}
-		if (y_bit != BN_is_bit_set(y, 0))
+		if (y_bit != BN_is_odd(y))
 			{
 			ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, ERR_R_INTERNAL_ERROR);
 			goto err;
@@ -725,6 +766,11 @@
 	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)
 		{
@@ -881,6 +927,11 @@
 	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)
 		{
@@ -959,6 +1010,10 @@
 	}
 
 
+int ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx);
+/* TODO */
+
+
 int ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
 	{
 	return BN_is_zero(&point->Z);
@@ -1067,6 +1122,10 @@
 	}
 
 
+int ec_GFp_simple_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, BN_CTX *);
+/* TODO */
+
+
 int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
 	{
 	BN_CTX *new_ctx = NULL;