From 0657bf9c14598f52fe3cacd0c32d99458d97659e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bodo=20M=C3=B6ller?= Date: Wed, 7 Mar 2001 01:17:05 +0000 Subject: [PATCH] Implement dispatcher for EC_GROUP and EC_POINT method functions. Initial EC_GROUP_new_curve_GFp implementation. --- crypto/ec/ec.h | 18 +++ crypto/ec/ec_cvt.c | 25 +++- crypto/ec/ec_err.c | 16 +++ crypto/ec/ec_lcl.h | 16 ++- crypto/ec/ec_lib.c | 289 ++++++++++++++++++++++++++++++++++++++++++- crypto/ec/ecp_mont.c | 11 ++ crypto/ec/ecp_nist.c | 11 ++ crypto/ec/ecp_recp.c | 11 ++ crypto/ec/ecp_smpl.c | 11 ++ 9 files changed, 402 insertions(+), 6 deletions(-) diff --git a/crypto/ec/ec.h b/crypto/ec/ec.h index 8d4dc833d4..2211d2fa7f 100644 --- a/crypto/ec/ec.h +++ b/crypto/ec/ec.h @@ -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 } diff --git a/crypto/ec/ec_cvt.c b/crypto/ec/ec_cvt.c index be06d3d92f..361dcc3992 100644 --- a/crypto/ec/ec_cvt.c +++ b/crypto/ec/ec_cvt.c @@ -1,4 +1,3 @@ -/* TODO */ /* crypto/ec/ec_cvt.c */ /* ==================================================================== * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. @@ -55,3 +54,27 @@ */ #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; + } diff --git a/crypto/ec/ec_err.c b/crypto/ec/ec_err.c index 6c2af969d1..7a9b2b15ef 100644 --- a/crypto/ec/ec_err.c +++ b/crypto/ec/ec_err.c @@ -66,11 +66,27 @@ #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} }; diff --git a/crypto/ec/ec_lcl.h b/crypto/ec/ec_lcl.h index 614d885a00..1b5ee4df46 100644 --- a/crypto/ec/ec_lcl.h +++ b/crypto/ec/ec_lcl.h @@ -64,11 +64,12 @@ * 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; diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c index c218a8d130..990eab51aa 100644 --- a/crypto/ec/ec_lib.c +++ b/crypto/ec/ec_lib.c @@ -1,4 +1,3 @@ -/* TODO */ /* crypto/ec/ec_lib.c */ /* ==================================================================== * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. @@ -54,4 +53,292 @@ * */ +#include + #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); + } diff --git a/crypto/ec/ecp_mont.c b/crypto/ec/ecp_mont.c index 80476320b9..78fcbae61f 100644 --- a/crypto/ec/ecp_mont.c +++ b/crypto/ec/ecp_mont.c @@ -55,3 +55,14 @@ */ #include "ec_lcl.h" + + +const EC_METHOD *EC_GFp_mont_method(void) + { + static const EC_METHOD ret = + { + 0 /* XXX */ + }; + + return &ret; + } diff --git a/crypto/ec/ecp_nist.c b/crypto/ec/ecp_nist.c index 1ecab88f8e..0c319c6aed 100644 --- a/crypto/ec/ecp_nist.c +++ b/crypto/ec/ecp_nist.c @@ -55,3 +55,14 @@ */ #include "ec_lcl.h" + + +const EC_METHOD *EC_GFp_nist_method(void) + { + static const EC_METHOD ret = + { + 0 /* XXX */ + }; + + return &ret; + } diff --git a/crypto/ec/ecp_recp.c b/crypto/ec/ecp_recp.c index 1306b76f36..4bc2b7ebc5 100644 --- a/crypto/ec/ecp_recp.c +++ b/crypto/ec/ecp_recp.c @@ -55,3 +55,14 @@ */ #include "ec_lcl.h" + + +const EC_METHOD *EC_GFp_recp_method(void) + { + static const EC_METHOD ret = + { + 0 /* XXX */ + }; + + return &ret; + } diff --git a/crypto/ec/ecp_smpl.c b/crypto/ec/ecp_smpl.c index 3d922ded13..e02765921c 100644 --- a/crypto/ec/ecp_smpl.c +++ b/crypto/ec/ecp_smpl.c @@ -55,3 +55,14 @@ */ #include "ec_lcl.h" + + +const EC_METHOD *EC_GFp_simple_method(void) + { + static const EC_METHOD ret = + { + 0 /* XXX */ + }; + + return &ret; + } -- 2.34.1