Implement dispatcher for EC_GROUP and EC_POINT method functions.
authorBodo Möller <bodo@openssl.org>
Wed, 7 Mar 2001 01:17:05 +0000 (01:17 +0000)
committerBodo Möller <bodo@openssl.org>
Wed, 7 Mar 2001 01:17:05 +0000 (01:17 +0000)
Initial EC_GROUP_new_curve_GFp implementation.

crypto/ec/ec.h
crypto/ec/ec_cvt.c
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

index 8d4dc833d4325b6909fa791da44a821a1f59912e..2211d2fa7f2e11a3c3391ebedbc12ad7a58e569d 100644 (file)
@@ -104,6 +104,7 @@ EC_GROUP *EC_GROUP_new(const EC_METHOD *);
  */
 int EC_GROUP_set_curve_GFp(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
 void EC_GROUP_free(EC_GROUP *);
+void EC_GROUP_clear_free(EC_GROUP *);
 int EC_GROUP_copy(EC_GROUP *, const EC_GROUP*);
 
 /* EC_GROUP_new_GFp() calls EC_GROUP_new() and EC_GROUP_set_GFp()
@@ -117,6 +118,7 @@ int EC_GROUP_set_generator(EC_GROUP *, const EC_POINT *generator, const BIGNUM *
 
 EC_POINT *EC_POINT_new(const EC_GROUP *);
 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 */
@@ -148,8 +150,24 @@ int EC_POINT_make_affine(const EC_GROUP *, const EC_POINT *, BN_CTX *);
 /* Error codes for the EC functions. */
 
 /* Function codes. */
+#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_NEW                               100
+#define EC_F_EC_GROUP_SET_CURVE_GFP                     101
+#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
 
 /* Reason codes. */
+#define EC_R_INCOMPATIBLE_OBJECTS                       100
 
 #ifdef  __cplusplus
 }
index be06d3d92f9405f02a6c36431d59e40b13f60507..361dcc3992dd505f0c82e804230c40105899abe9 100644 (file)
@@ -1,4 +1,3 @@
-/* TODO */
 /* crypto/ec/ec_cvt.c */
 /* ====================================================================
  * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
  */
 
 #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;
+       
+       /* Finally, this will use EC_GFp_nist_method if 'p' is a special
+        * prime with optimized modular arithmetics (for NIST curves)
+        * and EC_GFp_mont_method or EC_GFp_recp_method otherwise. */
+       meth = EC_GFp_simple_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;
+       }
index 6c2af969d1edc58a676980b4479d1f82691115d2..7a9b2b15ef8f14315c222543f39ba3fd2c13f2bc 100644 (file)
 #ifndef OPENSSL_NO_ERR
 static ERR_STRING_DATA EC_str_functs[]=
        {
+{ERR_PACK(0,EC_F_EC_GROUP_CLEAR_FREE,0),       "EC_GROUP_clear_free"},
+{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_NEW,0),      "EC_GROUP_new"},
+{ERR_PACK(0,EC_F_EC_GROUP_SET_CURVE_GFP,0),    "EC_GROUP_set_curve_GFp"},
+{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_COPY,0),     "EC_POINT_copy"},
+{ERR_PACK(0,EC_F_EC_POINT_DBL,0),      "EC_POINT_dbl"},
+{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"},
 {0,NULL}
        };
 
 static ERR_STRING_DATA EC_str_reasons[]=
        {
+{EC_R_INCOMPATIBLE_OBJECTS               ,"incompatible objects"},
 {0,NULL}
        };
 
index 614d885a003f84c7f7f4c751e2969d4f1701d8d8..1b5ee4df466a4c46bb68b520f2ac884e77fd1533 100644 (file)
  * so all this may change in future versions. */
 
 struct ec_method_st {
-       /* used by EC_GROUP_new, EC_GROUP_set_GFp, EC_GROUP_free, EC_GROUP_copy: */
+       /* used by EC_GROUP_new, EC_GROUP_set_curve_GFp, EC_GROUP_free, EC_GROUP_copy: */
        int (*group_init)(EC_GROUP *);
        /* int (*group_set)(EC_GROUP *, .....); */
-       int (*group_set_GFp)(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
+       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 *);
        int (*group_copy)(EC_GROUP *, const EC_GROUP *);
 
        /* used by EC_GROUP_set_generator: */
@@ -81,6 +82,7 @@ struct ec_method_st {
        /* used by EC_POINT_new, EC_POINT_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 *);
 
        /* TODO: 'set' and 'get' functions for EC_POINTs */
@@ -115,8 +117,11 @@ struct ec_method_st {
 
 
 struct ec_group_st {
-       EC_METHOD *meth;
+       const EC_METHOD *meth;
 
+       /* All members except 'meth' are handled by the method functions,
+        * even if they appear generic */
+       
        BIGNUM field; /* Field specification.
                       * For curves over GF(p), this is the modulus. */
        void *field_data; /* method-specific (e.g., Montgomery structure) */
@@ -138,7 +143,10 @@ struct ec_group_st {
 
 
 struct ec_point_st {
-       EC_METHOD *meth;
+       const EC_METHOD *meth;
+
+       /* All members except 'meth' are handled by the method functions,
+        * even if they appear generic */
 
        BIGNUM X;
        BIGNUM Y;
index c218a8d130b34a00b37b39d85e125d0406df4260..990eab51aa1dccd5eb75046baa251249833ab4b2 100644 (file)
@@ -1,4 +1,3 @@
-/* TODO */
 /* crypto/ec/ec_lib.c */
 /* ====================================================================
  * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
  *
  */
 
+#include <openssl/err.h>
+
 #include "ec_lcl.h"
+
+
+/* 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, ERR_R_PASSED_NULL_PARAMETER);
+               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;
+       
+       if (!meth->group_init(ret))
+               {
+               OPENSSL_free(ret);
+               return NULL;
+               }
+       
+       return ret;
+       }
+
+
+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_GFp == 0)
+               {
+               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);
+       }
+
+
+void EC_GROUP_free(EC_GROUP *group)
+       {
+       if (group->meth->group_finish != 0)
+               group->meth->group_finish(group);
+       OPENSSL_free(group);
+       }
+
+void EC_GROUP_clear_free(EC_GROUP *group)
+       {
+       if (group->meth->group_clear_finish != 0)
+               group->meth->group_clear_finish(group);
+       else if (group->meth != NULL && group->meth->group_finish != 0)
+               group->meth->group_finish(group);
+       OPENSSL_free(group);
+       }
+
+
+int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
+       {
+       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;
+               }
+       
+       return dest->meth->group_copy(dest, src);
+       }
+
+
+int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor)
+       {
+       if (group->meth->group_set_generator == 0)
+               {
+               ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+               return 0;
+               }
+       return group->meth->group_set_generator(group, generator, order, cofactor);
+       }
+
+
+/* TODO: 'get' functions for EC_GROUPs */
+
+
+
+/* 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->meth->point_finish != 0)
+               point->meth->point_finish(point);
+       OPENSSL_free(point);
+       }
+
+void EC_POINT_clear_free(EC_POINT *point)
+       {
+       if (point->meth->point_clear_finish != 0)
+               point->meth->point_clear_finish(point);
+       else if (point->meth != NULL && point->meth->point_finish != 0)
+               point->meth->point_finish(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;
+               }
+       
+       return dest->meth->point_copy(dest, src);
+       }
+
+
+/* TODO: '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,
+        unsigned char *buf, size_t len, BN_CTX *ctx)
+       {
+       if (group->meth->point2oct == 0)
+               {
+               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;
+               }
+       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)
+               {
+               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;
+               }
+       return group->meth->oct2point(group, point, buf, len, ctx);
+       }
+
+
+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_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_make_affine(const EC_GROUP *group, const 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);
+       }
index 80476320b9e0e0d01b808382cbba9d6afe8e80f5..78fcbae61fe293992d1493d76a63d25da2c7b2e2 100644 (file)
  */
 
 #include "ec_lcl.h"
+
+
+const EC_METHOD *EC_GFp_mont_method(void)
+       {
+       static const EC_METHOD ret =
+               {
+                       0 /* XXX */
+               };
+
+       return &ret;
+       }
index 1ecab88f8ed751f8ceb9970dec5ae86d919434d9..0c319c6aedb0ec735dc028fd740e6d774b838960 100644 (file)
  */
 
 #include "ec_lcl.h"
+
+
+const EC_METHOD *EC_GFp_nist_method(void)
+       {
+       static const EC_METHOD ret =
+               {
+                       0 /* XXX */
+               };
+
+       return &ret;
+       }
index 1306b76f361a228b21b61c7d7fb40fe82aa34d1c..4bc2b7ebc507df6c857f5c75e03084338b94964b 100644 (file)
  */
 
 #include "ec_lcl.h"
+
+
+const EC_METHOD *EC_GFp_recp_method(void)
+       {
+       static const EC_METHOD ret =
+               {
+                       0 /* XXX */
+               };
+
+       return &ret;
+       }
index 3d922ded13aeba1dc6426a7e94e361bea23f801d..e02765921c36e4081c6be4a1fe37d95915a80078 100644 (file)
  */
 
 #include "ec_lcl.h"
+
+
+const EC_METHOD *EC_GFp_simple_method(void)
+       {
+       static const EC_METHOD ret =
+               {
+                       0 /* XXX */
+               };
+
+       return &ret;
+       }