Add additional parameter to dsa_builtin_paramgen to output the generated
[openssl.git] / crypto / ec / ecp_smpl.c
index ad95b03ba60fc07765c81ce9ba5b7bd6af417f58..3e56b71a211aa421baa3da6696ffe9890d1937c6 100644 (file)
@@ -94,13 +94,14 @@ const EC_METHOD *EC_GFp_simple_method(void)
                ec_GFp_simple_add,
                ec_GFp_simple_dbl,
                ec_GFp_simple_invert,
-               0 /* mul */,
-               0 /* precompute_mult */,
                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 */,
@@ -112,6 +113,20 @@ const EC_METHOD *EC_GFp_simple_method(void)
        }
 
 
+/* 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);
@@ -177,7 +192,7 @@ int ec_GFp_simple_group_set_curve(EC_GROUP *group,
 
        /* group->field */
        if (!BN_copy(&group->field, p)) goto err;
-       BN_set_sign(&group->field, 0);
+       BN_set_negative(&group->field, 0);
 
        /* group->a */
        if (!BN_nnmod(tmp_a, a, p, ctx)) goto err;
@@ -321,7 +336,8 @@ int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
        ret = 1;
 
 err:
-       BN_CTX_end(ctx);
+       if (ctx != NULL)
+               BN_CTX_end(ctx);
        if (new_ctx != NULL)
                BN_CTX_free(new_ctx);
        return ret;
@@ -370,7 +386,8 @@ int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
 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));
+       BN_zero(&point->Z);
+       return 1;
        }
 
 
@@ -424,8 +441,11 @@ int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POIN
                        }
                point->Z_is_one = Z_is_one;
                }
-       
-       ret = 1;
+
+       if (BN_cmp(&point->X, x) || BN_cmp(&point->Y, y))
+               ret = 2;
+       else
+               ret = 1;
        
  err:
        if (new_ctx != NULL)
@@ -505,8 +525,8 @@ int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_P
        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_;
+       BIGNUM *Z, *Z_1, *Z_2, *Z_3;
+       const BIGNUM *Z_;
        int ret = 0;
 
        if (EC_POINT_is_at_infinity(group, point))
@@ -523,8 +543,6 @@ int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_P
                }
 
        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);
@@ -535,27 +553,37 @@ int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_P
        
        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;
+               Z_ = Z;
                }
        else
                {
-               X_ = &point->X;
-               Y_ = &point->Y;
                Z_ = &point->Z;
                }
        
        if (BN_is_one(Z_))
                {
-               if (x != NULL)
+               if (group->meth->field_decode)
                        {
-                       if (!BN_copy(x, X_)) goto err;
+                       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 (y != NULL)
+               else
                        {
-                       if (!BN_copy(y, Y_)) goto err;
+                       if (x != NULL)
+                               {
+                               if (!BN_copy(x, &point->X)) goto err;
+                               }
+                       if (y != NULL)
+                               {
+                               if (!BN_copy(y, &point->Y)) goto err;
+                               }
                        }
                }
        else
@@ -578,15 +606,8 @@ int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_P
        
                if (x != NULL)
                        {
-                       if (group->meth->field_encode == 0)
-                               {
-                               /* field_mul works on standard representation */
-                               if (!group->meth->field_mul(group, x, X_, Z_2, ctx)) goto err;
-                               }
-                       else
-                               {
-                               if (!BN_mod_mul(x, X_, Z_2, &group->field, ctx)) goto err;
-                               }
+                       /* 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)
@@ -595,14 +616,14 @@ int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_P
                                {
                                /* field_mul works on standard representation */
                                if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) goto err;
-                               if (!group->meth->field_mul(group, y, Y_, Z_3, ctx)) goto err;
-                               
                                }
                        else
                                {
                                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;
                                }
+
+                       /* 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;
                        }
                }
 
@@ -623,6 +644,9 @@ int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *po
        BIGNUM *tmp1, *tmp2, *x, *y;
        int ret = 0;
 
+       /* clear error queue*/
+       ERR_clear_error();
+
        if (ctx == NULL)
                {
                ctx = new_ctx = BN_CTX_new();
@@ -694,11 +718,11 @@ int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *po
        
        if (!BN_mod_sqrt(y, tmp1, &group->field, ctx))
                {
-               unsigned long err = ERR_peek_error();
+               unsigned long err = ERR_peek_last_error();
                
                if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE)
                        {
-                       (void)ERR_get_error();
+                       ERR_clear_error();
                        ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
                        }
                else
@@ -885,7 +909,7 @@ int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
                }
        form = buf[0];
        y_bit = form & 1;
-       form = form & ~1;
+       form = form & ~1U;
        if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
                && (form != POINT_CONVERSION_UNCOMPRESSED)
                && (form != POINT_CONVERSION_HYBRID))
@@ -1077,7 +1101,7 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, con
                else
                        {
                        /* a is the inverse of b */
-                       if (!BN_zero(&r->Z)) goto end;
+                       BN_zero(&r->Z);
                        r->Z_is_one = 0;
                        ret = 1;
                        goto end;
@@ -1153,7 +1177,7 @@ int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_
        
        if (EC_POINT_is_at_infinity(group, a))
                {
-               if (!BN_zero(&r->Z)) return 0;
+               BN_zero(&r->Z);
                r->Z_is_one = 0;
                return 1;
                }
@@ -1281,7 +1305,7 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_C
        int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
        const BIGNUM *p;
        BN_CTX *new_ctx = NULL;
-       BIGNUM *rh, *tmp1, *tmp2, *Z4, *Z6;
+       BIGNUM *rh, *tmp, *Z4, *Z6;
        int ret = -1;
 
        if (EC_POINT_is_at_infinity(group, point))
@@ -1300,8 +1324,7 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_C
 
        BN_CTX_start(ctx);
        rh = BN_CTX_get(ctx);
-       tmp1 = BN_CTX_get(ctx);
-       tmp2 = BN_CTX_get(ctx);
+       tmp = BN_CTX_get(ctx);
        Z4 = BN_CTX_get(ctx);
        Z6 = BN_CTX_get(ctx);
        if (Z6 == NULL) goto err;
@@ -1315,59 +1338,49 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_C
         * To test this, we add up the right-hand side in 'rh'.
         */
 
-       /* rh := X^3 */
+       /* rh := X^2 */
        if (!field_sqr(group, rh, &point->X, ctx)) goto err;
-       if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
 
        if (!point->Z_is_one)
                {
-               if (!field_sqr(group, tmp1, &point->Z, ctx)) goto err;
-               if (!field_sqr(group, Z4, tmp1, ctx)) goto err;
-               if (!field_mul(group, Z6, Z4, tmp1, ctx)) goto err;
+               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*X*Z^4 */
-               if (!field_mul(group, tmp1, &point->X, Z4, ctx)) goto err;
+               /* rh := (rh + a*Z^4)*X */
                if (group->a_is_minus3)
                        {
-                       if (!BN_mod_lshift1_quick(tmp2, tmp1, p)) goto err;
-                       if (!BN_mod_add_quick(tmp2, tmp2, tmp1, p)) goto err;
-                       if (!BN_mod_sub_quick(rh, rh, tmp2, p)) goto err;
+                       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, tmp2, tmp1, &group->a, ctx)) goto err;
-                       if (!BN_mod_add_quick(rh, rh, tmp2, p)) goto err;
+                       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, tmp1, &group->b, Z6, ctx)) goto err;
-               if (!BN_mod_add_quick(rh, rh, tmp1, p)) goto err;
+               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 (group->a_is_minus3)
-                       {
-                       if (!BN_mod_lshift1_quick(tmp2, &point->X, p)) goto err;
-                       if (!BN_mod_add_quick(tmp2, tmp2, &point->X, p)) goto err;
-                       if (!BN_mod_sub_quick(rh, rh, tmp2, p)) goto err;
-                       }
-               else
-                       {
-                       if (!field_mul(group, tmp2, &point->X, &group->a, ctx)) goto err;
-                       if (!BN_mod_add_quick(rh, rh, tmp2, p)) goto err;
-                       }
-
+               /* 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, tmp1, &point->Y, ctx)) goto err;
+       if (!field_sqr(group, tmp, &point->Y, ctx)) goto err;
 
-       ret = (0 == BN_cmp(tmp1, rh));
+       ret = (0 == BN_ucmp(tmp, rh));
 
  err:
        BN_CTX_end(ctx);
@@ -1396,6 +1409,9 @@ int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *
                {
                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)
                {
@@ -1484,7 +1500,6 @@ int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *
        return ret;
        }
 
-
 int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
        {
        BN_CTX *new_ctx = NULL;