Fix bugs and typos.
[openssl.git] / crypto / ec / ecp_smpl.c
index 30178f7fcd065db3d153ed7325a492b73acacce9..8e062dc95126e9c5e610855d4fb004f898172dc8 100644 (file)
@@ -2,7 +2,7 @@
 /* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de>
  * for the OpenSSL project. */
 /* ====================================================================
- * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
+ * 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
@@ -73,6 +73,7 @@ const EC_METHOD *EC_GFp_simple_method(void)
                ec_GFp_simple_group_get0_generator,
                ec_GFp_simple_group_get_order,
                ec_GFp_simple_group_get_cofactor,
+               ec_GFp_simple_group_check,
                ec_GFp_simple_point_init,
                ec_GFp_simple_point_finish,
                ec_GFp_simple_point_clear_finish,
@@ -338,6 +339,112 @@ int ec_GFp_simple_group_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN
        }
 
 
+int ec_GFp_simple_group_check(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;
+       EC_POINT *point = NULL;
+
+       if (ctx == NULL)
+               {
+               ctx = new_ctx = BN_CTX_new();
+               if (ctx == NULL)
+                       {
+                       ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK, 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))
+                       {
+                       ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK, EC_R_DISCRIMINANT_IS_ZERO);
+                       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))
+                       {
+                       ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK, EC_R_DISCRIMINANT_IS_ZERO);
+                       goto err;
+                       }
+               }
+       
+       /* check the generator */
+       if (group->generator == NULL)
+               {
+               ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK, EC_R_UNDEFINED_GENERATOR);
+               goto err;
+               }
+       if (!ec_GFp_simple_is_on_curve(group, group->generator, ctx))
+               {
+               ECerr(EC_F_EC_GFP_SIMPLE_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_GFP_SIMPLE_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_GFP_SIMPLE_GROUP_CHECK, EC_R_INVALID_GROUP_ORDER);
+               goto err;
+               }
+
+       ret = 1;
+
+err:
+       BN_CTX_end(ctx);
+       if (new_ctx != NULL)
+               BN_CTX_free(new_ctx);
+       if (point)
+               EC_POINT_free(point);
+       return ret;
+       }
+
+
 int ec_GFp_simple_point_init(EC_POINT *point)
        {
        BN_init(&point->X);
@@ -889,7 +996,7 @@ int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
        size_t field_len, enc_len;
        int ret = 0;
 
-       if (len <= 0)
+       if (len == 0)
                {
                ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
                return 0;