More method functions for EC_GFp_simple_method.
authorBodo Möller <bodo@openssl.org>
Thu, 8 Mar 2001 01:23:28 +0000 (01:23 +0000)
committerBodo Möller <bodo@openssl.org>
Thu, 8 Mar 2001 01:23:28 +0000 (01:23 +0000)
crypto/bn/bn.h
crypto/ec/ec.h
crypto/ec/ec_err.c
crypto/ec/ec_lcl.h
crypto/ec/ec_lib.c
crypto/ec/ecp_mont.c
crypto/ec/ecp_nist.c
crypto/ec/ecp_recp.c
crypto/ec/ecp_smpl.c
util/mkerr.pl

index 22e8c2d..ed8cba5 100644 (file)
@@ -553,4 +553,3 @@ int BN_bntest_rand(BIGNUM *rnd, int bits, int top,int bottom);
 }
 #endif
 #endif
-
index 93fde52..db410c1 100644 (file)
@@ -65,6 +65,7 @@ extern "C" {
 
 
 typedef enum {
+       /* values as defined in X9.62 (ECDSA) and elsewhere */
        POINT_CONVERSION_COMPRESSED = 2,
        POINT_CONVERSION_UNCOMPRESSED = 4,
        POINT_CONVERSION_HYBRID = 6
@@ -120,7 +121,12 @@ void EC_POINT_free(EC_POINT *);
 void EC_POINT_clear_free(EC_POINT *);
 int EC_POINT_copy(EC_POINT *, const EC_POINT *);
  
-/* TODO: 'set' and 'get' functions for EC_POINTs */
+int EC_POINT_set_to_infinity(const EC_GROUP *, EC_POINT *);
+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 */
 
 size_t EC_POINT_point2oct(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form,
         unsigned char *buf, size_t len, BN_CTX *);
@@ -149,33 +155,41 @@ int EC_POINT_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *);
 /* Error codes for the EC functions. */
 
 /* Function codes. */
-#define EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR          117
-#define EC_F_EC_GFP_SIMPLE_MAKE_AFFINE                  118
-#define EC_F_EC_GROUP_CLEAR_FREE                        103
-#define EC_F_EC_GROUP_COPY                              102
-#define EC_F_EC_GROUP_FREE                              104
-#define EC_F_EC_GROUP_GET_EXTRA_DATA                    115
-#define EC_F_EC_GROUP_NEW                               100
-#define EC_F_EC_GROUP_SET_CURVE_GFP                     101
-#define EC_F_EC_GROUP_SET_EXTRA_DATA                    116
-#define EC_F_EC_GROUP_SET_GENERATOR                     106
-#define EC_F_EC_POINT_ADD                               107
-#define EC_F_EC_POINT_COPY                              108
-#define EC_F_EC_POINT_DBL                               109
-#define EC_F_EC_POINT_IS_AT_INFINITY                    110
-#define EC_F_EC_POINT_IS_ON_CURVE                       111
-#define EC_F_EC_POINT_MAKE_AFFINE                       112
-#define EC_F_EC_POINT_NEW                               105
-#define EC_F_EC_POINT_OCT2POINT                                 113
-#define EC_F_EC_POINT_POINT2OCT                                 114
+#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
+#define EC_F_EC_GFP_SIMPLE_POINT2OCT                    103
+#define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP 104
+#define EC_F_EC_GROUP_COPY                              105
+#define EC_F_EC_GROUP_GET_EXTRA_DATA                    106
+#define EC_F_EC_GROUP_NEW                               107
+#define EC_F_EC_GROUP_SET_CURVE_GFP                     108
+#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_COPY                              112
+#define EC_F_EC_POINT_DBL                               113
+#define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP        114
+#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
+#define EC_F_EC_POINT_NEW                               118
+#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_TO_INFINITY                   122
 
 /* Reason codes. */
-#define EC_R_INCOMPATIBLE_OBJECTS                       100
-#define EC_R_NO_SUCH_EXTRA_DATA                                 101
-#define EC_R_SLOT_FULL                                  102
+#define EC_R_BUFFER_TOO_SMALL                           100
+#define EC_R_INCOMPATIBLE_OBJECTS                       101
+#define EC_R_INVALID_ENCODING                           102
+#define EC_R_INVALID_FORM                               103
+#define EC_R_NO_SUCH_EXTRA_DATA                                 104
+#define EC_R_POINT_AT_INFINITY                          105
+#define EC_R_POINT_IS_NOT_ON_CURVE                      106
+#define EC_R_SLOT_FULL                                  107
 
 #ifdef  __cplusplus
 }
 #endif
 #endif
-
index cd2d792..620dbd1 100644 (file)
@@ -68,9 +68,10 @@ static ERR_STRING_DATA EC_str_functs[]=
        {
 {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_GROUP_CLEAR_FREE,0),       "EC_GROUP_clear_free"},
+{ERR_PACK(0,EC_F_EC_GFP_SIMPLE_OCT2POINT,0),   "EC_GFP_SIMPLE_OCT2POINT"},
+{ERR_PACK(0,EC_F_EC_GFP_SIMPLE_POINT2OCT,0),   "EC_GFP_SIMPLE_POINT2OCT"},
+{ERR_PACK(0,EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP,0),    "EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP"},
 {ERR_PACK(0,EC_F_EC_GROUP_COPY,0),     "EC_GROUP_copy"},
-{ERR_PACK(0,EC_F_EC_GROUP_FREE,0),     "EC_GROUP_free"},
 {ERR_PACK(0,EC_F_EC_GROUP_GET_EXTRA_DATA,0),   "EC_GROUP_GET_EXTRA_DATA"},
 {ERR_PACK(0,EC_F_EC_GROUP_NEW,0),      "EC_GROUP_new"},
 {ERR_PACK(0,EC_F_EC_GROUP_SET_CURVE_GFP,0),    "EC_GROUP_set_curve_GFp"},
@@ -79,19 +80,27 @@ static ERR_STRING_DATA EC_str_functs[]=
 {ERR_PACK(0,EC_F_EC_POINT_ADD,0),      "EC_POINT_add"},
 {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_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"},
 {ERR_PACK(0,EC_F_EC_POINT_NEW,0),      "EC_POINT_new"},
 {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_TO_INFINITY,0),  "EC_POINT_set_to_infinity"},
 {0,NULL}
        };
 
 static ERR_STRING_DATA EC_str_reasons[]=
        {
+{EC_R_BUFFER_TOO_SMALL                   ,"buffer too small"},
 {EC_R_INCOMPATIBLE_OBJECTS               ,"incompatible objects"},
+{EC_R_INVALID_ENCODING                   ,"invalid encoding"},
+{EC_R_INVALID_FORM                       ,"invalid form"},
 {EC_R_NO_SUCH_EXTRA_DATA                 ,"no such extra data"},
+{EC_R_POINT_AT_INFINITY                  ,"point at infinity"},
+{EC_R_POINT_IS_NOT_ON_CURVE              ,"point is not on curve"},
 {EC_R_SLOT_FULL                          ,"slot full"},
 {0,NULL}
        };
index 4bfcc91..b3f8354 100644 (file)
@@ -84,7 +84,12 @@ struct ec_method_st {
        void (*point_clear_finish)(EC_POINT *);
        int (*point_copy)(EC_POINT *, const EC_POINT *);
 
-       /* TODO: 'set' and 'get' functions for EC_POINTs */
+       int (*point_set_to_infinity)(const EC_GROUP *, EC_POINT *);
+       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 */
 
        /* used by EC_POINT_point2oct, EC_POINT_oct2point: */
        size_t (*point2oct)(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form,
@@ -188,7 +193,12 @@ 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 *);
-/* TODO: 'set' and 'get' functions for EC_POINTs */
+int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *);
+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 */
 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 *,
index 90da84e..d0af0d5 100644 (file)
@@ -108,7 +108,6 @@ int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, co
                ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
                return 0;
                }
-       
        return group->meth->group_set_curve_GFp(group, p, a, b, ctx);
        }
 
@@ -315,12 +314,61 @@ int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
                ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS);
                return 0;
                }
-       
        return dest->meth->point_copy(dest, src);
        }
 
 
-/* TODO: 'set' and 'get' functions for EC_POINTs */
+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_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_GFp == 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_GFp(group, point, x, y, ctx);
+       }
+
+
+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_GFp == 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_GFp(group, point, x, y, ctx);
+       }
+
+
+/* TODO: other 'set' and 'get' functions for EC_POINTs */
 
 
 size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
index 04d21e5..17d9a48 100644 (file)
@@ -70,7 +70,10 @@ const EC_METHOD *EC_GFp_mont_method(void)
                ec_GFp_simple_point_finish,
                ec_GFp_simple_point_clear_finish,
                ec_GFp_simple_point_copy,
-               /* TODO: 'set' and 'get' functions for EC_POINTs */
+               ec_GFp_simple_point_set_to_infinity,
+               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_point2oct,
                ec_GFp_simple_oct2point,
                ec_GFp_simple_add,
index 16fea7c..df2d614 100644 (file)
@@ -70,7 +70,10 @@ const EC_METHOD *EC_GFp_nist_method(void)
                ec_GFp_simple_point_finish,
                ec_GFp_simple_point_clear_finish,
                ec_GFp_simple_point_copy,
-               /* TODO: 'set' and 'get' functions for EC_POINTs */
+               ec_GFp_simple_point_set_to_infinity,
+               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_point2oct,
                ec_GFp_simple_oct2point,
                ec_GFp_simple_add,
index b2a8da9..df7b52b 100644 (file)
@@ -70,7 +70,10 @@ const EC_METHOD *EC_GFp_recp_method(void)
                ec_GFp_simple_point_finish,
                ec_GFp_simple_point_clear_finish,
                ec_GFp_simple_point_copy,
-               /* TODO: 'set' and 'get' functions for EC_POINTs */
+               ec_GFp_simple_point_set_to_infinity,
+               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_point2oct,
                ec_GFp_simple_oct2point,
                ec_GFp_simple_add,
index 5306efd..9d9fe86 100644 (file)
@@ -74,7 +74,10 @@ const EC_METHOD *EC_GFp_simple_method(void)
                ec_GFp_simple_point_finish,
                ec_GFp_simple_point_clear_finish,
                ec_GFp_simple_point_copy,
-               /* TODO: 'set' and 'get' functions for EC_POINTs */
+               ec_GFp_simple_point_set_to_infinity,
+               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_point2oct,
                ec_GFp_simple_oct2point,
                ec_GFp_simple_add,
@@ -117,8 +120,8 @@ int ec_GFp_simple_group_set_curve_GFp(EC_GROUP *group,
                if (ctx == NULL)
                        return 0;
                }
-       BN_CTX_start(ctx);
 
+       BN_CTX_start(ctx);
        tmp_a = BN_CTX_get(ctx);
        if (tmp_a == NULL) goto err;
 
@@ -285,17 +288,404 @@ int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
        }
 
 
-/* TODO: 'set' and 'get' functions for EC_POINTs */
+int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
+       {
+       point->Z_is_one = 0;
+       return (BN_zero(&point->Z));
+       }
+
+
+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)
+       {
+       BN_CTX *new_ctx = NULL;
+       int ret = 0;
+
+       if (!BN_copy(&point->X, x)) goto err;
+       if (!BN_copy(&point->Y, y)) goto err;
+       if (!BN_one(&point->Z)) goto err;
+
+       if (group->meth->field_encode)
+               {
+               if (ctx == NULL)
+                       {
+                       ctx = new_ctx = BN_CTX_new();
+                       if (ctx == NULL)
+                               return 0;
+                       }
+               
+               if (!group->meth->field_encode(group, &point->X, &point->X, ctx)) goto err;
+               if (!group->meth->field_encode(group, &point->Y, &point->Y, ctx)) goto err;
+               if (!group->meth->field_encode(group, &point->Z, &point->Z, ctx)) goto err;
+               }
+
+       point->Z_is_one = 1;
+       
+ err:
+       if (new_ctx != NULL)
+               BN_CTX_free(new_ctx);
+       return ret;
+       }
+
+
+int ec_GFp_simple_point_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
+       BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
+       {
+       BN_CTX *new_ctx = NULL;
+       BIGNUM *X, *Y, *Z, *Z_1, *Z_2, *Z_3;
+       const BIGNUM *X_, *Y_, *Z_;
+       int ret = 0;
+
+       if (EC_POINT_is_at_infinity(group, point))
+               {
+               ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP, 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);
+       X = BN_CTX_get(ctx);
+       Y = BN_CTX_get(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, X, &point->X, ctx)) goto err;
+               if (!group->meth->field_decode(group, Y, &point->Y, ctx)) goto err;
+               if (!group->meth->field_decode(group, Z, &point->Z, ctx)) goto err;
+               X_ = X; Y_ = Y; Z_ = Z;
+               }
+       else
+               {
+               X_ = &point->X;
+               Y_ = &point->Y;
+               Z_ = &point->Z;
+               }
+       
+       if (BN_is_one(Z_))
+               {
+               if (!BN_copy(x, X_)) goto err;
+               if (!BN_copy(y, Y_)) goto err;
+               }
+       else
+               {
+               if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx))
+                       {
+                       ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP, ERR_R_BN_LIB);
+                       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;
+               }
+
+       ret = 1;
+
+ err:
+       BN_CTX_end(ctx);
+       if (new_ctx != NULL)
+               BN_CTX_free(new_ctx);
+       return ret;
+       }
+
+
+/* TODO: other 'set' and 'get' functions for EC_POINTs */
 
 
 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);
-/* TODO */
+       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_bit_set(y, 0))
+                       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 *);
-/* TODO */
+       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 & ~1;
+       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 (!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_bit_set(y, 0))
+                               {
+                               ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
+                               goto err;
+                               }
+                       }
+               }
+
+       if (form == POINT_CONVERSION_COMPRESSED)
+               {
+               /* 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.
+                */
+
+               BIGNUM *tmp1, *tmp2;
+               
+               tmp1 = BN_CTX_get(ctx);
+               tmp2 = BN_CTX_get(ctx);
+               if (tmp2 == NULL) goto err;
+               
+               /* tmp1 := x^3 */
+               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 (!BN_mod_mul(tmp2, &group->a, x, &group->field, ctx)) goto err;
+                       if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
+                       }
+               
+               /* tmp1 := tmp1 + b */
+               if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field)) goto err;
+
+               if (!BN_mod_sqrt(y, tmp1, &group->field, ctx))
+                       {
+                       ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, ERR_R_BN_LIB);
+                       goto err;
+                       }
+
+               if (y_bit != BN_is_bit_set(y, 0))
+                       {
+                       if (!BN_usub(y, &group->field, y)) goto err;
+                       }
+               if (y_bit != BN_is_bit_set(y, 0))
+                       {
+                       ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, ERR_R_INTERNAL_ERROR);
+                       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;
+       }
 
 
 int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
@@ -324,8 +714,8 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, con
                if (ctx == NULL)
                        return 0;
                }
-       BN_CTX_start(ctx);
 
+       BN_CTX_start(ctx);
        n0 = BN_CTX_get(ctx);
        n1 = BN_CTX_get(ctx);
        n2 = BN_CTX_get(ctx);
@@ -483,8 +873,8 @@ int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_
                if (ctx == NULL)
                        return 0;
                }
-       BN_CTX_start(ctx);
 
+       BN_CTX_start(ctx);
        n0 = BN_CTX_get(ctx);
        n1 = BN_CTX_get(ctx);
        n2 = BN_CTX_get(ctx);
@@ -595,10 +985,10 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_C
                {
                ctx = new_ctx = BN_CTX_new();
                if (ctx == NULL)
-                       return 0;
+                       return -1;
                }
-       BN_CTX_start(ctx);
 
+       BN_CTX_start(ctx);
        rh = BN_CTX_get(ctx);
        tmp1 = BN_CTX_get(ctx);
        tmp2 = BN_CTX_get(ctx);
@@ -680,7 +1070,7 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_C
 int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
        {
        BN_CTX *new_ctx = NULL;
-       BIGNUM *Z, *Z_1, *Z_2, *Z_3;
+       BIGNUM *x, *y;
        int ret = 0;
 
        if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
@@ -692,46 +1082,23 @@ int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ct
                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 end;
-
-       /* transform  (X, Y, Z)  into  (X/Z^2, Y/Z^3, 1) */
-       
-       if (group->meth->field_decode)
-               {
-               if (!group->meth->field_decode(group, Z, &point->Z, ctx)) goto end;
-               }
-       else
-               Z = &point->Z;
-       
-       if (BN_is_one(Z))
-               {
-               point->Z_is_one = 1;
-               ret = 1;
-               goto end;
-               }
+       BN_CTX_start(ctx);
+       x = BN_CTX_get(ctx);
+       y = BN_CTX_get(ctx);
+       if (y == NULL) goto err;
 
-       if (!BN_mod_inverse(Z_1, Z, &group->field, ctx))
+       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_BN_LIB);
-               goto end;
+               ECerr(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE, ERR_R_INTERNAL_ERROR);
+               goto err;
                }
-       if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) goto end;
-       if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) goto end;
        
-       if (!BN_mod_mul(&point->X, &point->X, Z_2, &group->field, ctx)) goto end;
-       if (!BN_mod_mul(&point->Y, &point->Y, Z_2, &group->field, ctx)) goto end;
-       if (!BN_set_word(&point->Z, 1)) goto end;
-       point->Z_is_one = 1;
-
        ret = 1;
 
- end:
+ err:
        BN_CTX_end(ctx);
        if (new_ctx != NULL)
                BN_CTX_free(new_ctx);
index 33b904f..b744c81 100644 (file)
@@ -288,7 +288,6 @@ EOF
 }
 #endif
 #endif
-
 EOF
        close OUT;