diff options
Diffstat (limited to 'openssl/crypto/ec')
27 files changed, 18636 insertions, 17302 deletions
diff --git a/openssl/crypto/ec/ec.h b/openssl/crypto/ec/ec.h index 572111f16..c4e7aea93 100644 --- a/openssl/crypto/ec/ec.h +++ b/openssl/crypto/ec/ec.h @@ -14,7 +14,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -62,81 +62,78 @@ /* ==================================================================== * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. * - * Portions of the attached software ("Contribution") are developed by + * Portions of the attached software ("Contribution") are developed by * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. * * The Contribution is licensed pursuant to the OpenSSL open source * license provided above. * - * The elliptic curve binary polynomial software is originally written by + * The elliptic curve binary polynomial software is originally written by * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories. * */ #ifndef HEADER_EC_H -#define HEADER_EC_H +# define HEADER_EC_H -#include <openssl/opensslconf.h> +# include <openssl/opensslconf.h> -#ifdef OPENSSL_NO_EC -#error EC is disabled. -#endif +# ifdef OPENSSL_NO_EC +# error EC is disabled. +# endif -#include <openssl/asn1.h> -#include <openssl/symhacks.h> -#ifndef OPENSSL_NO_DEPRECATED -#include <openssl/bn.h> -#endif +# include <openssl/asn1.h> +# include <openssl/symhacks.h> +# ifndef OPENSSL_NO_DEPRECATED +# include <openssl/bn.h> +# endif -#ifdef __cplusplus +# ifdef __cplusplus extern "C" { -#elif defined(__SUNPRO_C) -# if __SUNPRO_C >= 0x520 -# pragma error_messages (off,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE) +# elif defined(__SUNPRO_C) +# if __SUNPRO_C >= 0x520 +# pragma error_messages (off,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE) +# endif # endif -#endif - -#ifndef OPENSSL_ECC_MAX_FIELD_BITS -# define OPENSSL_ECC_MAX_FIELD_BITS 661 -#endif +# ifndef OPENSSL_ECC_MAX_FIELD_BITS +# define OPENSSL_ECC_MAX_FIELD_BITS 661 +# endif /** Enum for the point conversion form as defined in X9.62 (ECDSA) * for the encoding of a elliptic curve point (x,y) */ typedef enum { - /** the point is encoded as z||x, where the octet z specifies - * which solution of the quadratic equation y is */ - POINT_CONVERSION_COMPRESSED = 2, - /** the point is encoded as z||x||y, where z is the octet 0x02 */ - POINT_CONVERSION_UNCOMPRESSED = 4, - /** the point is encoded as z||x||y, where the octet z specifies + /** the point is encoded as z||x, where the octet z specifies * which solution of the quadratic equation y is */ - POINT_CONVERSION_HYBRID = 6 + POINT_CONVERSION_COMPRESSED = 2, + /** the point is encoded as z||x||y, where z is the octet 0x02 */ + POINT_CONVERSION_UNCOMPRESSED = 4, + /** the point is encoded as z||x||y, where the octet z specifies + * which solution of the quadratic equation y is */ + POINT_CONVERSION_HYBRID = 6 } point_conversion_form_t; - typedef struct ec_method_st EC_METHOD; typedef struct ec_group_st - /* - EC_METHOD *meth; - -- field definition - -- curve coefficients - -- optional generator with associated information (order, cofactor) - -- optional extra data (precomputed table for fast computation of multiples of generator) - -- ASN1 stuff - */ - EC_GROUP; + /*- + EC_METHOD *meth; + -- field definition + -- curve coefficients + -- optional generator with associated information (order, cofactor) + -- optional extra data (precomputed table for fast computation of multiples of generator) + -- ASN1 stuff + */ + EC_GROUP; typedef struct ec_point_st EC_POINT; - /********************************************************************/ -/* EC_METHODs for curves over GF(p) */ +/* EC_METHODs for curves over GF(p) */ /********************************************************************/ /** Returns the basic GFp ec methods which provides the basis for the - * optimized methods. + * optimized methods. * \return EC_METHOD object */ const EC_METHOD *EC_GFp_simple_method(void); @@ -151,7 +148,7 @@ const EC_METHOD *EC_GFp_mont_method(void); */ const EC_METHOD *EC_GFp_nist_method(void); -#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 +# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 /** Returns 64-bit optimized methods for nistp224 * \return EC_METHOD object */ @@ -166,20 +163,19 @@ const EC_METHOD *EC_GFp_nistp256_method(void); * \return EC_METHOD object */ const EC_METHOD *EC_GFp_nistp521_method(void); -#endif +# endif -#ifndef OPENSSL_NO_EC2M -/********************************************************************/ +# ifndef OPENSSL_NO_EC2M +/********************************************************************/ /* EC_METHOD for curves over GF(2^m) */ /********************************************************************/ -/** Returns the basic GF2m ec method +/** Returns the basic GF2m ec method * \return EC_METHOD object */ const EC_METHOD *EC_GF2m_simple_method(void); -#endif - +# endif /********************************************************************/ /* EC_GROUP functions */ @@ -216,7 +212,7 @@ int EC_GROUP_copy(EC_GROUP *dst, const EC_GROUP *src); EC_GROUP *EC_GROUP_dup(const EC_GROUP *src); /** Returns the EC_METHOD of the EC_GROUP object. - * \param group EC_GROUP object + * \param group EC_GROUP object * \return EC_METHOD used in this EC_GROUP object. */ const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group); @@ -228,14 +224,15 @@ const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group); int EC_METHOD_get_field_type(const EC_METHOD *meth); /** Sets the generator and it's order/cofactor of a EC_GROUP object. - * \param group EC_GROUP object + * \param group EC_GROUP object * \param generator EC_POINT object with the generator. * \param order the order of the group generated by the generator. * \param cofactor the index of the sub-group generated by the generator * in the group of all points on the elliptic curve. * \return 1 on success and 0 if an error occured */ -int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor); +int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, + const BIGNUM *order, const BIGNUM *cofactor); /** Returns the generator of a EC_GROUP object. * \param group EC_GROUP object @@ -257,7 +254,8 @@ int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx); * \param ctx BN_CTX object (optional) * \return 1 on success and 0 if an error occured */ -int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx); +int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, + BN_CTX *ctx); /** Sets the name of a EC_GROUP object * \param group EC_GROUP object @@ -274,7 +272,8 @@ int EC_GROUP_get_curve_name(const EC_GROUP *group); void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag); int EC_GROUP_get_asn1_flag(const EC_GROUP *group); -void EC_GROUP_set_point_conversion_form(EC_GROUP *group, point_conversion_form_t form); +void EC_GROUP_set_point_conversion_form(EC_GROUP *group, + point_conversion_form_t form); point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *); unsigned char *EC_GROUP_get0_seed(const EC_GROUP *x); @@ -289,7 +288,8 @@ size_t EC_GROUP_set_seed(EC_GROUP *, const unsigned char *, size_t len); * \param ctx BN_CTX object (optional) * \return 1 on success and 0 if an error occured */ -int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); +int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx); /** Gets the parameter of the ec over GFp defined by y^2 = x^3 + a*x + b * \param group EC_GROUP object @@ -299,9 +299,10 @@ int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, co * \param ctx BN_CTX object (optional) * \return 1 on success and 0 if an error occured */ -int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx); +int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, + BIGNUM *b, BN_CTX *ctx); -#ifndef OPENSSL_NO_EC2M +# ifndef OPENSSL_NO_EC2M /** Sets the parameter of a ec over GF2m defined by y^2 + x*y = x^3 + a*x^2 + b * \param group EC_GROUP object * \param p BIGNUM with the polynomial defining the underlying field @@ -310,7 +311,8 @@ int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM * * \param ctx BN_CTX object (optional) * \return 1 on success and 0 if an error occured */ -int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); +int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx); /** Gets the parameter of the ec over GF2m defined by y^2 + x*y = x^3 + a*x^2 + b * \param group EC_GROUP object @@ -320,9 +322,10 @@ int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, c * \param ctx BN_CTX object (optional) * \return 1 on success and 0 if an error occured */ -int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx); -#endif -/** Returns the number of bits needed to represent a field element +int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, + BIGNUM *b, BN_CTX *ctx); +# endif +/** Returns the number of bits needed to represent a field element * \param group EC_GROUP object * \return number of bits needed to represent a field element */ @@ -350,8 +353,10 @@ int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx); */ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx); -/* EC_GROUP_new_GF*() calls EC_GROUP_new() and EC_GROUP_set_GF*() - * after choosing an appropriate EC_METHOD */ +/* + * EC_GROUP_new_GF*() calls EC_GROUP_new() and EC_GROUP_set_GF*() after + * choosing an appropriate EC_METHOD + */ /** Creates a new EC_GROUP object with the specified parameters defined * over GFp (defined by the equation y^2 = x^3 + a*x + b) @@ -361,8 +366,9 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx); * \param ctx BN_CTX object (optional) * \return newly created EC_GROUP object with the specified parameters */ -EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); -#ifndef OPENSSL_NO_EC2M +EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx); +# ifndef OPENSSL_NO_EC2M /** Creates a new EC_GROUP object with the specified parameters defined * over GF2m (defined by the equation y^2 + x*y = x^3 + a*x^2 + b) * \param p BIGNUM with the polynomial defining the underlying field @@ -371,8 +377,9 @@ EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM * \param ctx BN_CTX object (optional) * \return newly created EC_GROUP object with the specified parameters */ -EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); -#endif +EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx); +# endif /** Creates a EC_GROUP object with a curve specified by a NID * \param nid NID of the OID of the curve name * \return newly created EC_GROUP object with specified curve or NULL @@ -380,23 +387,23 @@ EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM */ EC_GROUP *EC_GROUP_new_by_curve_name(int nid); - /********************************************************************/ /* handling of internal curves */ /********************************************************************/ -typedef struct { - int nid; - const char *comment; - } EC_builtin_curve; +typedef struct { + int nid; + const char *comment; +} EC_builtin_curve; -/* EC_builtin_curves(EC_builtin_curve *r, size_t size) returns number - * of all available curves or zero if a error occurred. - * In case r ist not zero nitems EC_builtin_curve structures - * are filled with the data of the first nitems internal groups */ +/* + * EC_builtin_curves(EC_builtin_curve *r, size_t size) returns number of all + * available curves or zero if a error occurred. In case r ist not zero + * nitems EC_builtin_curve structures are filled with the data of the first + * nitems internal groups + */ size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems); - /********************************************************************/ /* EC_POINT functions */ /********************************************************************/ @@ -428,11 +435,11 @@ int EC_POINT_copy(EC_POINT *dst, const EC_POINT *src); * EC_POINT * \param src source EC_POINT object * \param group underlying the EC_GROUP object - * \return newly created EC_POINT object or NULL if an error occurred + * \return newly created EC_POINT object or NULL if an error occurred */ EC_POINT *EC_POINT_dup(const EC_POINT *src, const EC_GROUP *group); - -/** Returns the EC_METHOD used in EC_POINT object + +/** Returns the EC_METHOD used in EC_POINT object * \param point EC_POINT object * \return the EC_METHOD used */ @@ -454,8 +461,10 @@ int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point); * \param ctx BN_CTX object (optional) * \return 1 on success and 0 if an error occured */ -int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *p, - const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx); +int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, + EC_POINT *p, const BIGNUM *x, + const BIGNUM *y, const BIGNUM *z, + BN_CTX *ctx); /** Gets the jacobian projective coordinates of a EC_POINT over GFp * \param group underlying EC_GROUP object @@ -467,7 +476,9 @@ int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *p, * \return 1 on success and 0 if an error occured */ int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, - const EC_POINT *p, BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx); + const EC_POINT *p, BIGNUM *x, + BIGNUM *y, BIGNUM *z, + BN_CTX *ctx); /** Sets the affine coordinates of a EC_POINT over GFp * \param group underlying EC_GROUP object @@ -478,7 +489,8 @@ int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, * \return 1 on success and 0 if an error occured */ int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *p, - const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx); + const BIGNUM *x, const BIGNUM *y, + BN_CTX *ctx); /** Gets the affine coordinates of a EC_POINT over GFp * \param group underlying EC_GROUP object @@ -489,7 +501,8 @@ int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *p, * \return 1 on success and 0 if an error occured */ int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, - const EC_POINT *p, BIGNUM *x, BIGNUM *y, BN_CTX *ctx); + const EC_POINT *p, BIGNUM *x, + BIGNUM *y, BN_CTX *ctx); /** Sets the x9.62 compressed coordinates of a EC_POINT over GFp * \param group underlying EC_GROUP object @@ -499,9 +512,10 @@ int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, * \param ctx BN_CTX object (optional) * \return 1 on success and 0 if an error occured */ -int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *p, - const BIGNUM *x, int y_bit, BN_CTX *ctx); -#ifndef OPENSSL_NO_EC2M +int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, + EC_POINT *p, const BIGNUM *x, + int y_bit, BN_CTX *ctx); +# ifndef OPENSSL_NO_EC2M /** Sets the affine coordinates of a EC_POINT over GF2m * \param group underlying EC_GROUP object * \param p EC_POINT object @@ -511,7 +525,8 @@ int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *p, * \return 1 on success and 0 if an error occured */ int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *p, - const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx); + const BIGNUM *x, const BIGNUM *y, + BN_CTX *ctx); /** Gets the affine coordinates of a EC_POINT over GF2m * \param group underlying EC_GROUP object @@ -522,7 +537,8 @@ int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *p, * \return 1 on success and 0 if an error occured */ int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, - const EC_POINT *p, BIGNUM *x, BIGNUM *y, BN_CTX *ctx); + const EC_POINT *p, BIGNUM *x, + BIGNUM *y, BN_CTX *ctx); /** Sets the x9.62 compressed coordinates of a EC_POINT over GF2m * \param group underlying EC_GROUP object @@ -532,9 +548,10 @@ int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, * \param ctx BN_CTX object (optional) * \return 1 on success and 0 if an error occured */ -int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, EC_POINT *p, - const BIGNUM *x, int y_bit, BN_CTX *ctx); -#endif +int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, + EC_POINT *p, const BIGNUM *x, + int y_bit, BN_CTX *ctx); +# endif /** Encodes a EC_POINT object to a octet string * \param group underlying EC_GROUP object * \param p EC_POINT object @@ -546,8 +563,8 @@ int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, EC_POINT *p, * \return the length of the encoded octet string or 0 if an error occurred */ size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *p, - point_conversion_form_t form, - unsigned char *buf, size_t len, BN_CTX *ctx); + point_conversion_form_t form, + unsigned char *buf, size_t len, BN_CTX *ctx); /** Decodes a EC_POINT from a octet string * \param group underlying EC_GROUP object @@ -558,24 +575,23 @@ size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *p, * \return 1 on success and 0 if an error occured */ int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *p, - const unsigned char *buf, size_t len, BN_CTX *ctx); + const unsigned char *buf, size_t len, BN_CTX *ctx); /* other interfaces to point2oct/oct2point: */ BIGNUM *EC_POINT_point2bn(const EC_GROUP *, const EC_POINT *, - point_conversion_form_t form, BIGNUM *, BN_CTX *); + point_conversion_form_t form, BIGNUM *, BN_CTX *); EC_POINT *EC_POINT_bn2point(const EC_GROUP *, const BIGNUM *, - EC_POINT *, BN_CTX *); + EC_POINT *, BN_CTX *); char *EC_POINT_point2hex(const EC_GROUP *, const EC_POINT *, - point_conversion_form_t form, BN_CTX *); + point_conversion_form_t form, BN_CTX *); EC_POINT *EC_POINT_hex2point(const EC_GROUP *, const char *, - EC_POINT *, BN_CTX *); - + EC_POINT *, BN_CTX *); /********************************************************************/ /* functions for doing EC_POINT arithmetic */ /********************************************************************/ -/** Computes the sum of two EC_POINT +/** Computes the sum of two EC_POINT * \param group underlying EC_GROUP object * \param r EC_POINT object for the result (r = a + b) * \param a EC_POINT object with the first summand @@ -583,16 +599,18 @@ EC_POINT *EC_POINT_hex2point(const EC_GROUP *, const char *, * \param ctx BN_CTX object (optional) * \return 1 on success and 0 if an error occured */ -int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx); +int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, + const EC_POINT *b, BN_CTX *ctx); /** Computes the double of a EC_POINT * \param group underlying EC_GROUP object * \param r EC_POINT object for the result (r = 2 * a) - * \param a EC_POINT object + * \param a EC_POINT object * \param ctx BN_CTX object (optional) * \return 1 on success and 0 if an error occured */ -int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx); +int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, + BN_CTX *ctx); /** Computes the inverse of a EC_POINT * \param group underlying EC_GROUP object @@ -609,25 +627,28 @@ int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx); */ int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *p); -/** Checks whether the point is on the curve +/** Checks whether the point is on the curve * \param group underlying EC_GROUP object * \param point EC_POINT object to check * \param ctx BN_CTX object (optional) * \return 1 if point if on the curve and 0 otherwise */ -int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx); +int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, + BN_CTX *ctx); -/** Compares two EC_POINTs +/** Compares two EC_POINTs * \param group underlying EC_GROUP object * \param a first EC_POINT object * \param b second EC_POINT object * \param ctx BN_CTX object (optional) * \return 0 if both points are equal and a value != 0 otherwise */ -int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx); +int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, + BN_CTX *ctx); int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx); -int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx); +int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, + EC_POINT *points[], BN_CTX *ctx); /** Computes r = generator * n sum_{i=0}^{num-1} p[i] * m[i] * \param group underlying EC_GROUP object @@ -639,7 +660,9 @@ int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], * \param ctx BN_CTX object (optional) * \return 1 on success and 0 if an error occured */ -int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, size_t num, const EC_POINT *p[], const BIGNUM *m[], BN_CTX *ctx); +int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, + size_t num, const EC_POINT *p[], const BIGNUM *m[], + BN_CTX *ctx); /** Computes r = generator * n + q * m * \param group underlying EC_GROUP object @@ -650,7 +673,8 @@ int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, size_t nu * \param ctx BN_CTX object (optional) * \return 1 on success and 0 if an error occured */ -int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, const EC_POINT *q, const BIGNUM *m, BN_CTX *ctx); +int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, + const EC_POINT *q, const BIGNUM *m, BN_CTX *ctx); /** Stores multiples of generator for faster point multiplication * \param group EC_GROUP object @@ -665,41 +689,41 @@ int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx); */ int EC_GROUP_have_precompute_mult(const EC_GROUP *group); - /********************************************************************/ /* ASN1 stuff */ /********************************************************************/ -/* EC_GROUP_get_basis_type() returns the NID of the basis type - * used to represent the field elements */ +/* + * EC_GROUP_get_basis_type() returns the NID of the basis type used to + * represent the field elements + */ int EC_GROUP_get_basis_type(const EC_GROUP *); -#ifndef OPENSSL_NO_EC2M +# ifndef OPENSSL_NO_EC2M int EC_GROUP_get_trinomial_basis(const EC_GROUP *, unsigned int *k); -int EC_GROUP_get_pentanomial_basis(const EC_GROUP *, unsigned int *k1, - unsigned int *k2, unsigned int *k3); -#endif +int EC_GROUP_get_pentanomial_basis(const EC_GROUP *, unsigned int *k1, + unsigned int *k2, unsigned int *k3); +# endif -#define OPENSSL_EC_NAMED_CURVE 0x001 +# define OPENSSL_EC_NAMED_CURVE 0x001 typedef struct ecpk_parameters_st ECPKPARAMETERS; EC_GROUP *d2i_ECPKParameters(EC_GROUP **, const unsigned char **in, long len); int i2d_ECPKParameters(const EC_GROUP *, unsigned char **out); -#define d2i_ECPKParameters_bio(bp,x) ASN1_d2i_bio_of(EC_GROUP,NULL,d2i_ECPKParameters,bp,x) -#define i2d_ECPKParameters_bio(bp,x) ASN1_i2d_bio_of_const(EC_GROUP,i2d_ECPKParameters,bp,x) -#define d2i_ECPKParameters_fp(fp,x) (EC_GROUP *)ASN1_d2i_fp(NULL, \ +# define d2i_ECPKParameters_bio(bp,x) ASN1_d2i_bio_of(EC_GROUP,NULL,d2i_ECPKParameters,bp,x) +# define i2d_ECPKParameters_bio(bp,x) ASN1_i2d_bio_of_const(EC_GROUP,i2d_ECPKParameters,bp,x) +# define d2i_ECPKParameters_fp(fp,x) (EC_GROUP *)ASN1_d2i_fp(NULL, \ (char *(*)())d2i_ECPKParameters,(fp),(unsigned char **)(x)) -#define i2d_ECPKParameters_fp(fp,x) ASN1_i2d_fp(i2d_ECPKParameters,(fp), \ - (unsigned char *)(x)) - -#ifndef OPENSSL_NO_BIO -int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off); -#endif -#ifndef OPENSSL_NO_FP_API -int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off); -#endif +# define i2d_ECPKParameters_fp(fp,x) ASN1_i2d_fp(i2d_ECPKParameters,(fp), \ + (unsigned char *)(x)) +# ifndef OPENSSL_NO_BIO +int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off); +# endif +# ifndef OPENSSL_NO_FP_API +int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off); +# endif /********************************************************************/ /* EC_KEY functions */ @@ -708,12 +732,12 @@ int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off); typedef struct ec_key_st EC_KEY; /* some values for the encoding_flag */ -#define EC_PKEY_NO_PARAMETERS 0x001 -#define EC_PKEY_NO_PUBKEY 0x002 +# define EC_PKEY_NO_PARAMETERS 0x001 +# define EC_PKEY_NO_PUBKEY 0x002 /* some values for the flags field */ -#define EC_FLAG_NON_FIPS_ALLOW 0x1 -#define EC_FLAG_FIPS_CHECKED 0x2 +# define EC_FLAG_NON_FIPS_ALLOW 0x1 +# define EC_FLAG_FIPS_CHECKED 0x2 /** Creates a new EC_KEY object. * \return EC_KEY object or NULL if an error occurred. @@ -729,7 +753,7 @@ void EC_KEY_clear_flags(EC_KEY *key, int flags); /** Creates a new EC_KEY object using a named curve as underlying * EC_GROUP object. * \param nid NID of the named curve. - * \return EC_KEY object or NULL if an error occurred. + * \return EC_KEY object or NULL if an error occurred. */ EC_KEY *EC_KEY_new_by_curve_name(int nid); @@ -804,8 +828,10 @@ void EC_KEY_set_enc_flags(EC_KEY *eckey, unsigned int flags); point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key); void EC_KEY_set_conv_form(EC_KEY *eckey, point_conversion_form_t cform); /* functions to set/get method specific data */ -void *EC_KEY_get_key_method_data(EC_KEY *key, - void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)); +void *EC_KEY_get_key_method_data(EC_KEY *key, + void *(*dup_func) (void *), + void (*free_func) (void *), + void (*clear_free_func) (void *)); /** Sets the key method data of an EC_KEY object, if none has yet been set. * \param key EC_KEY object * \param data opaque data to install. @@ -815,11 +841,13 @@ void *EC_KEY_get_key_method_data(EC_KEY *key, * \return the previously set data pointer, or NULL if |data| was inserted. */ void *EC_KEY_insert_key_method_data(EC_KEY *key, void *data, - void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)); + void *(*dup_func) (void *), + void (*free_func) (void *), + void (*clear_free_func) (void *)); /* wrapper functions for the underlying EC_GROUP object */ void EC_KEY_set_asn1_flag(EC_KEY *eckey, int asn1_flag); -/** Creates a table of pre-computed multiples of the generator to +/** Creates a table of pre-computed multiples of the generator to * accelerate further EC_KEY operations. * \param key EC_KEY object * \param ctx BN_CTX object (optional) @@ -846,8 +874,8 @@ int EC_KEY_check_key(const EC_KEY *key); * \param y public key y coordinate * \return 1 on success and 0 otherwise. */ -int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y); - +int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, + BIGNUM *y); /********************************************************************/ /* de- and encoding functions for SEC1 ECPrivateKey */ @@ -869,7 +897,6 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **key, const unsigned char **in, long len); */ int i2d_ECPrivateKey(EC_KEY *key, unsigned char **out); - /********************************************************************/ /* de- and encoding functions for EC parameters */ /********************************************************************/ @@ -891,7 +918,6 @@ EC_KEY *d2i_ECParameters(EC_KEY **key, const unsigned char **in, long len); */ int i2d_ECParameters(EC_KEY *key, unsigned char **out); - /********************************************************************/ /* de- and encoding functions for EC public key */ /* (octet string, not DER -- hence 'o2i' and 'i2o') */ @@ -914,60 +940,60 @@ EC_KEY *o2i_ECPublicKey(EC_KEY **key, const unsigned char **in, long len); */ int i2o_ECPublicKey(EC_KEY *key, unsigned char **out); -#ifndef OPENSSL_NO_BIO +# ifndef OPENSSL_NO_BIO /** Prints out the ec parameters on human readable form. * \param bp BIO object to which the information is printed * \param key EC_KEY object * \return 1 on success and 0 if an error occurred */ -int ECParameters_print(BIO *bp, const EC_KEY *key); +int ECParameters_print(BIO *bp, const EC_KEY *key); /** Prints out the contents of a EC_KEY object * \param bp BIO object to which the information is printed * \param key EC_KEY object - * \param off line offset + * \param off line offset * \return 1 on success and 0 if an error occurred */ -int EC_KEY_print(BIO *bp, const EC_KEY *key, int off); +int EC_KEY_print(BIO *bp, const EC_KEY *key, int off); -#endif -#ifndef OPENSSL_NO_FP_API +# endif +# ifndef OPENSSL_NO_FP_API /** Prints out the ec parameters on human readable form. * \param fp file descriptor to which the information is printed * \param key EC_KEY object * \return 1 on success and 0 if an error occurred */ -int ECParameters_print_fp(FILE *fp, const EC_KEY *key); +int ECParameters_print_fp(FILE *fp, const EC_KEY *key); /** Prints out the contents of a EC_KEY object * \param fp file descriptor to which the information is printed * \param key EC_KEY object - * \param off line offset + * \param off line offset * \return 1 on success and 0 if an error occurred */ -int EC_KEY_print_fp(FILE *fp, const EC_KEY *key, int off); +int EC_KEY_print_fp(FILE *fp, const EC_KEY *key, int off); -#endif +# endif -#define ECParameters_dup(x) ASN1_dup_of(EC_KEY,i2d_ECParameters,d2i_ECParameters,x) +# define ECParameters_dup(x) ASN1_dup_of(EC_KEY,i2d_ECParameters,d2i_ECParameters,x) -#ifndef __cplusplus -#if defined(__SUNPRO_C) -# if __SUNPRO_C >= 0x520 -# pragma error_messages (default,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE) +# ifndef __cplusplus +# if defined(__SUNPRO_C) +# if __SUNPRO_C >= 0x520 +# pragma error_messages (default,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE) +# endif # endif # endif -#endif - -#define EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid) \ - EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_PARAMGEN, \ - EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, nid, NULL) +# define EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, nid, NULL) -#define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 1) +# define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 1) /* BEGIN ERROR CODES */ -/* The following lines are auto generated by the script mkerr.pl. Any changes +/* + * The following lines are auto generated by the script mkerr.pl. Any changes * made after this point may be overwritten when the script is next run. */ void ERR_load_EC_strings(void); @@ -975,191 +1001,191 @@ void ERR_load_EC_strings(void); /* Error codes for the EC functions. */ /* Function codes. */ -#define EC_F_BN_TO_FELEM 224 -#define EC_F_COMPUTE_WNAF 143 -#define EC_F_D2I_ECPARAMETERS 144 -#define EC_F_D2I_ECPKPARAMETERS 145 -#define EC_F_D2I_ECPRIVATEKEY 146 -#define EC_F_DO_EC_KEY_PRINT 221 -#define EC_F_ECKEY_PARAM2TYPE 223 -#define EC_F_ECKEY_PARAM_DECODE 212 -#define EC_F_ECKEY_PRIV_DECODE 213 -#define EC_F_ECKEY_PRIV_ENCODE 214 -#define EC_F_ECKEY_PUB_DECODE 215 -#define EC_F_ECKEY_PUB_ENCODE 216 -#define EC_F_ECKEY_TYPE2PARAM 220 -#define EC_F_ECPARAMETERS_PRINT 147 -#define EC_F_ECPARAMETERS_PRINT_FP 148 -#define EC_F_ECPKPARAMETERS_PRINT 149 -#define EC_F_ECPKPARAMETERS_PRINT_FP 150 -#define EC_F_ECP_NIST_MOD_192 203 -#define EC_F_ECP_NIST_MOD_224 204 -#define EC_F_ECP_NIST_MOD_256 205 -#define EC_F_ECP_NIST_MOD_521 206 -#define EC_F_EC_ASN1_GROUP2CURVE 153 -#define EC_F_EC_ASN1_GROUP2FIELDID 154 -#define EC_F_EC_ASN1_GROUP2PARAMETERS 155 -#define EC_F_EC_ASN1_GROUP2PKPARAMETERS 156 -#define EC_F_EC_ASN1_PARAMETERS2GROUP 157 -#define EC_F_EC_ASN1_PKPARAMETERS2GROUP 158 -#define EC_F_EC_EX_DATA_SET_DATA 211 -#define EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY 208 -#define EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT 159 -#define EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE 195 -#define EC_F_EC_GF2M_SIMPLE_OCT2POINT 160 -#define EC_F_EC_GF2M_SIMPLE_POINT2OCT 161 -#define EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES 162 -#define EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES 163 -#define EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES 164 -#define EC_F_EC_GFP_MONT_FIELD_DECODE 133 -#define EC_F_EC_GFP_MONT_FIELD_ENCODE 134 -#define EC_F_EC_GFP_MONT_FIELD_MUL 131 -#define EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE 209 -#define EC_F_EC_GFP_MONT_FIELD_SQR 132 -#define EC_F_EC_GFP_MONT_GROUP_SET_CURVE 189 -#define EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP 135 -#define EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE 225 -#define EC_F_EC_GFP_NISTP224_POINTS_MUL 228 -#define EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES 226 -#define EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE 230 -#define EC_F_EC_GFP_NISTP256_POINTS_MUL 231 -#define EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES 232 -#define EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE 233 -#define EC_F_EC_GFP_NISTP521_POINTS_MUL 234 -#define EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES 235 -#define EC_F_EC_GFP_NIST_FIELD_MUL 200 -#define EC_F_EC_GFP_NIST_FIELD_SQR 201 -#define EC_F_EC_GFP_NIST_GROUP_SET_CURVE 202 -#define EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT 165 -#define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE 166 -#define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP 100 -#define EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR 101 -#define EC_F_EC_GFP_SIMPLE_MAKE_AFFINE 102 -#define EC_F_EC_GFP_SIMPLE_OCT2POINT 103 -#define EC_F_EC_GFP_SIMPLE_POINT2OCT 104 -#define EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE 137 -#define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES 167 -#define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP 105 -#define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES 168 -#define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP 128 -#define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES 169 -#define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP 129 -#define EC_F_EC_GROUP_CHECK 170 -#define EC_F_EC_GROUP_CHECK_DISCRIMINANT 171 -#define EC_F_EC_GROUP_COPY 106 -#define EC_F_EC_GROUP_GET0_GENERATOR 139 -#define EC_F_EC_GROUP_GET_COFACTOR 140 -#define EC_F_EC_GROUP_GET_CURVE_GF2M 172 -#define EC_F_EC_GROUP_GET_CURVE_GFP 130 -#define EC_F_EC_GROUP_GET_DEGREE 173 -#define EC_F_EC_GROUP_GET_ORDER 141 -#define EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS 193 -#define EC_F_EC_GROUP_GET_TRINOMIAL_BASIS 194 -#define EC_F_EC_GROUP_NEW 108 -#define EC_F_EC_GROUP_NEW_BY_CURVE_NAME 174 -#define EC_F_EC_GROUP_NEW_FROM_DATA 175 -#define EC_F_EC_GROUP_PRECOMPUTE_MULT 142 -#define EC_F_EC_GROUP_SET_CURVE_GF2M 176 -#define EC_F_EC_GROUP_SET_CURVE_GFP 109 -#define EC_F_EC_GROUP_SET_EXTRA_DATA 110 -#define EC_F_EC_GROUP_SET_GENERATOR 111 -#define EC_F_EC_KEY_CHECK_KEY 177 -#define EC_F_EC_KEY_COPY 178 -#define EC_F_EC_KEY_GENERATE_KEY 179 -#define EC_F_EC_KEY_NEW 182 -#define EC_F_EC_KEY_PRINT 180 -#define EC_F_EC_KEY_PRINT_FP 181 -#define EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES 229 -#define EC_F_EC_POINTS_MAKE_AFFINE 136 -#define EC_F_EC_POINT_ADD 112 -#define EC_F_EC_POINT_CMP 113 -#define EC_F_EC_POINT_COPY 114 -#define EC_F_EC_POINT_DBL 115 -#define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M 183 -#define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP 116 -#define EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP 117 -#define EC_F_EC_POINT_INVERT 210 -#define EC_F_EC_POINT_IS_AT_INFINITY 118 -#define EC_F_EC_POINT_IS_ON_CURVE 119 -#define EC_F_EC_POINT_MAKE_AFFINE 120 -#define EC_F_EC_POINT_MUL 184 -#define EC_F_EC_POINT_NEW 121 -#define EC_F_EC_POINT_OCT2POINT 122 -#define EC_F_EC_POINT_POINT2OCT 123 -#define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M 185 -#define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP 124 -#define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M 186 -#define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP 125 -#define EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP 126 -#define EC_F_EC_POINT_SET_TO_INFINITY 127 -#define EC_F_EC_PRE_COMP_DUP 207 -#define EC_F_EC_PRE_COMP_NEW 196 -#define EC_F_EC_WNAF_MUL 187 -#define EC_F_EC_WNAF_PRECOMPUTE_MULT 188 -#define EC_F_I2D_ECPARAMETERS 190 -#define EC_F_I2D_ECPKPARAMETERS 191 -#define EC_F_I2D_ECPRIVATEKEY 192 -#define EC_F_I2O_ECPUBLICKEY 151 -#define EC_F_NISTP224_PRE_COMP_NEW 227 -#define EC_F_NISTP256_PRE_COMP_NEW 236 -#define EC_F_NISTP521_PRE_COMP_NEW 237 -#define EC_F_O2I_ECPUBLICKEY 152 -#define EC_F_OLD_EC_PRIV_DECODE 222 -#define EC_F_PKEY_EC_CTRL 197 -#define EC_F_PKEY_EC_CTRL_STR 198 -#define EC_F_PKEY_EC_DERIVE 217 -#define EC_F_PKEY_EC_KEYGEN 199 -#define EC_F_PKEY_EC_PARAMGEN 219 -#define EC_F_PKEY_EC_SIGN 218 +# define EC_F_BN_TO_FELEM 224 +# define EC_F_COMPUTE_WNAF 143 +# define EC_F_D2I_ECPARAMETERS 144 +# define EC_F_D2I_ECPKPARAMETERS 145 +# define EC_F_D2I_ECPRIVATEKEY 146 +# define EC_F_DO_EC_KEY_PRINT 221 +# define EC_F_ECKEY_PARAM2TYPE 223 +# define EC_F_ECKEY_PARAM_DECODE 212 +# define EC_F_ECKEY_PRIV_DECODE 213 +# define EC_F_ECKEY_PRIV_ENCODE 214 +# define EC_F_ECKEY_PUB_DECODE 215 +# define EC_F_ECKEY_PUB_ENCODE 216 +# define EC_F_ECKEY_TYPE2PARAM 220 +# define EC_F_ECPARAMETERS_PRINT 147 +# define EC_F_ECPARAMETERS_PRINT_FP 148 +# define EC_F_ECPKPARAMETERS_PRINT 149 +# define EC_F_ECPKPARAMETERS_PRINT_FP 150 +# define EC_F_ECP_NIST_MOD_192 203 +# define EC_F_ECP_NIST_MOD_224 204 +# define EC_F_ECP_NIST_MOD_256 205 +# define EC_F_ECP_NIST_MOD_521 206 +# define EC_F_EC_ASN1_GROUP2CURVE 153 +# define EC_F_EC_ASN1_GROUP2FIELDID 154 +# define EC_F_EC_ASN1_GROUP2PARAMETERS 155 +# define EC_F_EC_ASN1_GROUP2PKPARAMETERS 156 +# define EC_F_EC_ASN1_PARAMETERS2GROUP 157 +# define EC_F_EC_ASN1_PKPARAMETERS2GROUP 158 +# define EC_F_EC_EX_DATA_SET_DATA 211 +# define EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY 208 +# define EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT 159 +# define EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE 195 +# define EC_F_EC_GF2M_SIMPLE_OCT2POINT 160 +# define EC_F_EC_GF2M_SIMPLE_POINT2OCT 161 +# define EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES 162 +# define EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES 163 +# define EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES 164 +# define EC_F_EC_GFP_MONT_FIELD_DECODE 133 +# define EC_F_EC_GFP_MONT_FIELD_ENCODE 134 +# define EC_F_EC_GFP_MONT_FIELD_MUL 131 +# define EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE 209 +# define EC_F_EC_GFP_MONT_FIELD_SQR 132 +# define EC_F_EC_GFP_MONT_GROUP_SET_CURVE 189 +# define EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP 135 +# define EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE 225 +# define EC_F_EC_GFP_NISTP224_POINTS_MUL 228 +# define EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES 226 +# define EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE 230 +# define EC_F_EC_GFP_NISTP256_POINTS_MUL 231 +# define EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES 232 +# define EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE 233 +# define EC_F_EC_GFP_NISTP521_POINTS_MUL 234 +# define EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES 235 +# define EC_F_EC_GFP_NIST_FIELD_MUL 200 +# define EC_F_EC_GFP_NIST_FIELD_SQR 201 +# define EC_F_EC_GFP_NIST_GROUP_SET_CURVE 202 +# define EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT 165 +# define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE 166 +# define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP 100 +# define EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR 101 +# define EC_F_EC_GFP_SIMPLE_MAKE_AFFINE 102 +# define EC_F_EC_GFP_SIMPLE_OCT2POINT 103 +# define EC_F_EC_GFP_SIMPLE_POINT2OCT 104 +# define EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE 137 +# define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES 167 +# define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP 105 +# define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES 168 +# define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP 128 +# define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES 169 +# define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP 129 +# define EC_F_EC_GROUP_CHECK 170 +# define EC_F_EC_GROUP_CHECK_DISCRIMINANT 171 +# define EC_F_EC_GROUP_COPY 106 +# define EC_F_EC_GROUP_GET0_GENERATOR 139 +# define EC_F_EC_GROUP_GET_COFACTOR 140 +# define EC_F_EC_GROUP_GET_CURVE_GF2M 172 +# define EC_F_EC_GROUP_GET_CURVE_GFP 130 +# define EC_F_EC_GROUP_GET_DEGREE 173 +# define EC_F_EC_GROUP_GET_ORDER 141 +# define EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS 193 +# define EC_F_EC_GROUP_GET_TRINOMIAL_BASIS 194 +# define EC_F_EC_GROUP_NEW 108 +# define EC_F_EC_GROUP_NEW_BY_CURVE_NAME 174 +# define EC_F_EC_GROUP_NEW_FROM_DATA 175 +# define EC_F_EC_GROUP_PRECOMPUTE_MULT 142 +# define EC_F_EC_GROUP_SET_CURVE_GF2M 176 +# define EC_F_EC_GROUP_SET_CURVE_GFP 109 +# define EC_F_EC_GROUP_SET_EXTRA_DATA 110 +# define EC_F_EC_GROUP_SET_GENERATOR 111 +# define EC_F_EC_KEY_CHECK_KEY 177 +# define EC_F_EC_KEY_COPY 178 +# define EC_F_EC_KEY_GENERATE_KEY 179 +# define EC_F_EC_KEY_NEW 182 +# define EC_F_EC_KEY_PRINT 180 +# define EC_F_EC_KEY_PRINT_FP 181 +# define EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES 229 +# define EC_F_EC_POINTS_MAKE_AFFINE 136 +# define EC_F_EC_POINT_ADD 112 +# define EC_F_EC_POINT_CMP 113 +# define EC_F_EC_POINT_COPY 114 +# define EC_F_EC_POINT_DBL 115 +# define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M 183 +# define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP 116 +# define EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP 117 +# define EC_F_EC_POINT_INVERT 210 +# define EC_F_EC_POINT_IS_AT_INFINITY 118 +# define EC_F_EC_POINT_IS_ON_CURVE 119 +# define EC_F_EC_POINT_MAKE_AFFINE 120 +# define EC_F_EC_POINT_MUL 184 +# define EC_F_EC_POINT_NEW 121 +# define EC_F_EC_POINT_OCT2POINT 122 +# define EC_F_EC_POINT_POINT2OCT 123 +# define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M 185 +# define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP 124 +# define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M 186 +# define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP 125 +# define EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP 126 +# define EC_F_EC_POINT_SET_TO_INFINITY 127 +# define EC_F_EC_PRE_COMP_DUP 207 +# define EC_F_EC_PRE_COMP_NEW 196 +# define EC_F_EC_WNAF_MUL 187 +# define EC_F_EC_WNAF_PRECOMPUTE_MULT 188 +# define EC_F_I2D_ECPARAMETERS 190 +# define EC_F_I2D_ECPKPARAMETERS 191 +# define EC_F_I2D_ECPRIVATEKEY 192 +# define EC_F_I2O_ECPUBLICKEY 151 +# define EC_F_NISTP224_PRE_COMP_NEW 227 +# define EC_F_NISTP256_PRE_COMP_NEW 236 +# define EC_F_NISTP521_PRE_COMP_NEW 237 +# define EC_F_O2I_ECPUBLICKEY 152 +# define EC_F_OLD_EC_PRIV_DECODE 222 +# define EC_F_PKEY_EC_CTRL 197 +# define EC_F_PKEY_EC_CTRL_STR 198 +# define EC_F_PKEY_EC_DERIVE 217 +# define EC_F_PKEY_EC_KEYGEN 199 +# define EC_F_PKEY_EC_PARAMGEN 219 +# define EC_F_PKEY_EC_SIGN 218 /* Reason codes. */ -#define EC_R_ASN1_ERROR 115 -#define EC_R_ASN1_UNKNOWN_FIELD 116 -#define EC_R_BIGNUM_OUT_OF_RANGE 144 -#define EC_R_BUFFER_TOO_SMALL 100 -#define EC_R_COORDINATES_OUT_OF_RANGE 146 -#define EC_R_D2I_ECPKPARAMETERS_FAILURE 117 -#define EC_R_DECODE_ERROR 142 -#define EC_R_DISCRIMINANT_IS_ZERO 118 -#define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE 119 -#define EC_R_FIELD_TOO_LARGE 143 -#define EC_R_GF2M_NOT_SUPPORTED 147 -#define EC_R_GROUP2PKPARAMETERS_FAILURE 120 -#define EC_R_I2D_ECPKPARAMETERS_FAILURE 121 -#define EC_R_INCOMPATIBLE_OBJECTS 101 -#define EC_R_INVALID_ARGUMENT 112 -#define EC_R_INVALID_COMPRESSED_POINT 110 -#define EC_R_INVALID_COMPRESSION_BIT 109 -#define EC_R_INVALID_CURVE 141 -#define EC_R_INVALID_DIGEST_TYPE 138 -#define EC_R_INVALID_ENCODING 102 -#define EC_R_INVALID_FIELD 103 -#define EC_R_INVALID_FORM 104 -#define EC_R_INVALID_GROUP_ORDER 122 -#define EC_R_INVALID_PENTANOMIAL_BASIS 132 -#define EC_R_INVALID_PRIVATE_KEY 123 -#define EC_R_INVALID_TRINOMIAL_BASIS 137 -#define EC_R_KEYS_NOT_SET 140 -#define EC_R_MISSING_PARAMETERS 124 -#define EC_R_MISSING_PRIVATE_KEY 125 -#define EC_R_NOT_A_NIST_PRIME 135 -#define EC_R_NOT_A_SUPPORTED_NIST_PRIME 136 -#define EC_R_NOT_IMPLEMENTED 126 -#define EC_R_NOT_INITIALIZED 111 -#define EC_R_NO_FIELD_MOD 133 -#define EC_R_NO_PARAMETERS_SET 139 -#define EC_R_PASSED_NULL_PARAMETER 134 -#define EC_R_PKPARAMETERS2GROUP_FAILURE 127 -#define EC_R_POINT_AT_INFINITY 106 -#define EC_R_POINT_IS_NOT_ON_CURVE 107 -#define EC_R_SLOT_FULL 108 -#define EC_R_UNDEFINED_GENERATOR 113 -#define EC_R_UNDEFINED_ORDER 128 -#define EC_R_UNKNOWN_GROUP 129 -#define EC_R_UNKNOWN_ORDER 114 -#define EC_R_UNSUPPORTED_FIELD 131 -#define EC_R_WRONG_CURVE_PARAMETERS 145 -#define EC_R_WRONG_ORDER 130 +# define EC_R_ASN1_ERROR 115 +# define EC_R_ASN1_UNKNOWN_FIELD 116 +# define EC_R_BIGNUM_OUT_OF_RANGE 144 +# define EC_R_BUFFER_TOO_SMALL 100 +# define EC_R_COORDINATES_OUT_OF_RANGE 146 +# define EC_R_D2I_ECPKPARAMETERS_FAILURE 117 +# define EC_R_DECODE_ERROR 142 +# define EC_R_DISCRIMINANT_IS_ZERO 118 +# define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE 119 +# define EC_R_FIELD_TOO_LARGE 143 +# define EC_R_GF2M_NOT_SUPPORTED 147 +# define EC_R_GROUP2PKPARAMETERS_FAILURE 120 +# define EC_R_I2D_ECPKPARAMETERS_FAILURE 121 +# define EC_R_INCOMPATIBLE_OBJECTS 101 +# define EC_R_INVALID_ARGUMENT 112 +# define EC_R_INVALID_COMPRESSED_POINT 110 +# define EC_R_INVALID_COMPRESSION_BIT 109 +# define EC_R_INVALID_CURVE 141 +# define EC_R_INVALID_DIGEST_TYPE 138 +# define EC_R_INVALID_ENCODING 102 +# define EC_R_INVALID_FIELD 103 +# define EC_R_INVALID_FORM 104 +# define EC_R_INVALID_GROUP_ORDER 122 +# define EC_R_INVALID_PENTANOMIAL_BASIS 132 +# define EC_R_INVALID_PRIVATE_KEY 123 +# define EC_R_INVALID_TRINOMIAL_BASIS 137 +# define EC_R_KEYS_NOT_SET 140 +# define EC_R_MISSING_PARAMETERS 124 +# define EC_R_MISSING_PRIVATE_KEY 125 +# define EC_R_NOT_A_NIST_PRIME 135 +# define EC_R_NOT_A_SUPPORTED_NIST_PRIME 136 +# define EC_R_NOT_IMPLEMENTED 126 +# define EC_R_NOT_INITIALIZED 111 +# define EC_R_NO_FIELD_MOD 133 +# define EC_R_NO_PARAMETERS_SET 139 +# define EC_R_PASSED_NULL_PARAMETER 134 +# define EC_R_PKPARAMETERS2GROUP_FAILURE 127 +# define EC_R_POINT_AT_INFINITY 106 +# define EC_R_POINT_IS_NOT_ON_CURVE 107 +# define EC_R_SLOT_FULL 108 +# define EC_R_UNDEFINED_GENERATOR 113 +# define EC_R_UNDEFINED_ORDER 128 +# define EC_R_UNKNOWN_GROUP 129 +# define EC_R_UNKNOWN_ORDER 114 +# define EC_R_UNSUPPORTED_FIELD 131 +# define EC_R_WRONG_CURVE_PARAMETERS 145 +# define EC_R_WRONG_ORDER 130 #ifdef __cplusplus } diff --git a/openssl/crypto/ec/ec2_mult.c b/openssl/crypto/ec/ec2_mult.c index 1c575dc47..68cc8771d 100644 --- a/openssl/crypto/ec/ec2_mult.c +++ b/openssl/crypto/ec/ec2_mult.c @@ -21,7 +21,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -73,323 +73,391 @@ #ifndef OPENSSL_NO_EC2M - -/* Compute the x-coordinate x/z for the point 2*(x/z) in Montgomery projective +/*- + * Compute the x-coordinate x/z for the point 2*(x/z) in Montgomery projective * coordinates. - * Uses algorithm Mdouble in appendix of - * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over + * Uses algorithm Mdouble in appendix of + * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over * GF(2^m) without precomputation" (CHES '99, LNCS 1717). * modified to not require precomputation of c=b^{2^{m-1}}. */ -static int gf2m_Mdouble(const EC_GROUP *group, BIGNUM *x, BIGNUM *z, BN_CTX *ctx) - { - BIGNUM *t1; - int ret = 0; - - /* Since Mdouble is static we can guarantee that ctx != NULL. */ - BN_CTX_start(ctx); - t1 = BN_CTX_get(ctx); - if (t1 == NULL) goto err; - - if (!group->meth->field_sqr(group, x, x, ctx)) goto err; - if (!group->meth->field_sqr(group, t1, z, ctx)) goto err; - if (!group->meth->field_mul(group, z, x, t1, ctx)) goto err; - if (!group->meth->field_sqr(group, x, x, ctx)) goto err; - if (!group->meth->field_sqr(group, t1, t1, ctx)) goto err; - if (!group->meth->field_mul(group, t1, &group->b, t1, ctx)) goto err; - if (!BN_GF2m_add(x, x, t1)) goto err; - - ret = 1; +static int gf2m_Mdouble(const EC_GROUP *group, BIGNUM *x, BIGNUM *z, + BN_CTX *ctx) +{ + BIGNUM *t1; + int ret = 0; + + /* Since Mdouble is static we can guarantee that ctx != NULL. */ + BN_CTX_start(ctx); + t1 = BN_CTX_get(ctx); + if (t1 == NULL) + goto err; + + if (!group->meth->field_sqr(group, x, x, ctx)) + goto err; + if (!group->meth->field_sqr(group, t1, z, ctx)) + goto err; + if (!group->meth->field_mul(group, z, x, t1, ctx)) + goto err; + if (!group->meth->field_sqr(group, x, x, ctx)) + goto err; + if (!group->meth->field_sqr(group, t1, t1, ctx)) + goto err; + if (!group->meth->field_mul(group, t1, &group->b, t1, ctx)) + goto err; + if (!BN_GF2m_add(x, x, t1)) + goto err; + + ret = 1; err: - BN_CTX_end(ctx); - return ret; - } + BN_CTX_end(ctx); + return ret; +} -/* Compute the x-coordinate x1/z1 for the point (x1/z1)+(x2/x2) in Montgomery +/*- + * Compute the x-coordinate x1/z1 for the point (x1/z1)+(x2/x2) in Montgomery * projective coordinates. - * Uses algorithm Madd in appendix of - * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over + * Uses algorithm Madd in appendix of + * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over * GF(2^m) without precomputation" (CHES '99, LNCS 1717). */ -static int gf2m_Madd(const EC_GROUP *group, const BIGNUM *x, BIGNUM *x1, BIGNUM *z1, - const BIGNUM *x2, const BIGNUM *z2, BN_CTX *ctx) - { - BIGNUM *t1, *t2; - int ret = 0; - - /* Since Madd is static we can guarantee that ctx != NULL. */ - BN_CTX_start(ctx); - t1 = BN_CTX_get(ctx); - t2 = BN_CTX_get(ctx); - if (t2 == NULL) goto err; - - if (!BN_copy(t1, x)) goto err; - if (!group->meth->field_mul(group, x1, x1, z2, ctx)) goto err; - if (!group->meth->field_mul(group, z1, z1, x2, ctx)) goto err; - if (!group->meth->field_mul(group, t2, x1, z1, ctx)) goto err; - if (!BN_GF2m_add(z1, z1, x1)) goto err; - if (!group->meth->field_sqr(group, z1, z1, ctx)) goto err; - if (!group->meth->field_mul(group, x1, z1, t1, ctx)) goto err; - if (!BN_GF2m_add(x1, x1, t2)) goto err; - - ret = 1; +static int gf2m_Madd(const EC_GROUP *group, const BIGNUM *x, BIGNUM *x1, + BIGNUM *z1, const BIGNUM *x2, const BIGNUM *z2, + BN_CTX *ctx) +{ + BIGNUM *t1, *t2; + int ret = 0; + + /* Since Madd is static we can guarantee that ctx != NULL. */ + BN_CTX_start(ctx); + t1 = BN_CTX_get(ctx); + t2 = BN_CTX_get(ctx); + if (t2 == NULL) + goto err; + + if (!BN_copy(t1, x)) + goto err; + if (!group->meth->field_mul(group, x1, x1, z2, ctx)) + goto err; + if (!group->meth->field_mul(group, z1, z1, x2, ctx)) + goto err; + if (!group->meth->field_mul(group, t2, x1, z1, ctx)) + goto err; + if (!BN_GF2m_add(z1, z1, x1)) + goto err; + if (!group->meth->field_sqr(group, z1, z1, ctx)) + goto err; + if (!group->meth->field_mul(group, x1, z1, t1, ctx)) + goto err; + if (!BN_GF2m_add(x1, x1, t2)) + goto err; + + ret = 1; err: - BN_CTX_end(ctx); - return ret; - } - -/* Compute the x, y affine coordinates from the point (x1, z1) (x2, z2) - * using Montgomery point multiplication algorithm Mxy() in appendix of - * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over + BN_CTX_end(ctx); + return ret; +} + +/*- + * Compute the x, y affine coordinates from the point (x1, z1) (x2, z2) + * using Montgomery point multiplication algorithm Mxy() in appendix of + * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over * GF(2^m) without precomputation" (CHES '99, LNCS 1717). * Returns: * 0 on error * 1 if return value should be the point at infinity * 2 otherwise */ -static int gf2m_Mxy(const EC_GROUP *group, const BIGNUM *x, const BIGNUM *y, BIGNUM *x1, - BIGNUM *z1, BIGNUM *x2, BIGNUM *z2, BN_CTX *ctx) - { - BIGNUM *t3, *t4, *t5; - int ret = 0; - - if (BN_is_zero(z1)) - { - BN_zero(x2); - BN_zero(z2); - return 1; - } - - if (BN_is_zero(z2)) - { - if (!BN_copy(x2, x)) return 0; - if (!BN_GF2m_add(z2, x, y)) return 0; - return 2; - } - - /* Since Mxy is static we can guarantee that ctx != NULL. */ - BN_CTX_start(ctx); - t3 = BN_CTX_get(ctx); - t4 = BN_CTX_get(ctx); - t5 = BN_CTX_get(ctx); - if (t5 == NULL) goto err; - - if (!BN_one(t5)) goto err; - - if (!group->meth->field_mul(group, t3, z1, z2, ctx)) goto err; - - if (!group->meth->field_mul(group, z1, z1, x, ctx)) goto err; - if (!BN_GF2m_add(z1, z1, x1)) goto err; - if (!group->meth->field_mul(group, z2, z2, x, ctx)) goto err; - if (!group->meth->field_mul(group, x1, z2, x1, ctx)) goto err; - if (!BN_GF2m_add(z2, z2, x2)) goto err; - - if (!group->meth->field_mul(group, z2, z2, z1, ctx)) goto err; - if (!group->meth->field_sqr(group, t4, x, ctx)) goto err; - if (!BN_GF2m_add(t4, t4, y)) goto err; - if (!group->meth->field_mul(group, t4, t4, t3, ctx)) goto err; - if (!BN_GF2m_add(t4, t4, z2)) goto err; - - if (!group->meth->field_mul(group, t3, t3, x, ctx)) goto err; - if (!group->meth->field_div(group, t3, t5, t3, ctx)) goto err; - if (!group->meth->field_mul(group, t4, t3, t4, ctx)) goto err; - if (!group->meth->field_mul(group, x2, x1, t3, ctx)) goto err; - if (!BN_GF2m_add(z2, x2, x)) goto err; - - if (!group->meth->field_mul(group, z2, z2, t4, ctx)) goto err; - if (!BN_GF2m_add(z2, z2, y)) goto err; - - ret = 2; +static int gf2m_Mxy(const EC_GROUP *group, const BIGNUM *x, const BIGNUM *y, + BIGNUM *x1, BIGNUM *z1, BIGNUM *x2, BIGNUM *z2, + BN_CTX *ctx) +{ + BIGNUM *t3, *t4, *t5; + int ret = 0; + + if (BN_is_zero(z1)) { + BN_zero(x2); + BN_zero(z2); + return 1; + } + + if (BN_is_zero(z2)) { + if (!BN_copy(x2, x)) + return 0; + if (!BN_GF2m_add(z2, x, y)) + return 0; + return 2; + } + + /* Since Mxy is static we can guarantee that ctx != NULL. */ + BN_CTX_start(ctx); + t3 = BN_CTX_get(ctx); + t4 = BN_CTX_get(ctx); + t5 = BN_CTX_get(ctx); + if (t5 == NULL) + goto err; + + if (!BN_one(t5)) + goto err; + + if (!group->meth->field_mul(group, t3, z1, z2, ctx)) + goto err; + + if (!group->meth->field_mul(group, z1, z1, x, ctx)) + goto err; + if (!BN_GF2m_add(z1, z1, x1)) + goto err; + if (!group->meth->field_mul(group, z2, z2, x, ctx)) + goto err; + if (!group->meth->field_mul(group, x1, z2, x1, ctx)) + goto err; + if (!BN_GF2m_add(z2, z2, x2)) + goto err; + + if (!group->meth->field_mul(group, z2, z2, z1, ctx)) + goto err; + if (!group->meth->field_sqr(group, t4, x, ctx)) + goto err; + if (!BN_GF2m_add(t4, t4, y)) + goto err; + if (!group->meth->field_mul(group, t4, t4, t3, ctx)) + goto err; + if (!BN_GF2m_add(t4, t4, z2)) + goto err; + + if (!group->meth->field_mul(group, t3, t3, x, ctx)) + goto err; + if (!group->meth->field_div(group, t3, t5, t3, ctx)) + goto err; + if (!group->meth->field_mul(group, t4, t3, t4, ctx)) + goto err; + if (!group->meth->field_mul(group, x2, x1, t3, ctx)) + goto err; + if (!BN_GF2m_add(z2, x2, x)) + goto err; + + if (!group->meth->field_mul(group, z2, z2, t4, ctx)) + goto err; + if (!BN_GF2m_add(z2, z2, y)) + goto err; + + ret = 2; err: - BN_CTX_end(ctx); - return ret; - } + BN_CTX_end(ctx); + return ret; +} - -/* Computes scalar*point and stores the result in r. +/*- + * Computes scalar*point and stores the result in r. * point can not equal r. * Uses a modified algorithm 2P of - * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over + * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over * GF(2^m) without precomputation" (CHES '99, LNCS 1717). * * To protect against side-channel attack the function uses constant time swap, * avoiding conditional branches. */ -static int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, - const EC_POINT *point, BN_CTX *ctx) - { - BIGNUM *x1, *x2, *z1, *z2; - int ret = 0, i; - BN_ULONG mask,word; - - if (r == point) - { - ECerr(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, EC_R_INVALID_ARGUMENT); - return 0; - } - - /* if result should be point at infinity */ - if ((scalar == NULL) || BN_is_zero(scalar) || (point == NULL) || - EC_POINT_is_at_infinity(group, point)) - { - return EC_POINT_set_to_infinity(group, r); - } - - /* only support affine coordinates */ - if (!point->Z_is_one) return 0; - - /* Since point_multiply is static we can guarantee that ctx != NULL. */ - BN_CTX_start(ctx); - x1 = BN_CTX_get(ctx); - z1 = BN_CTX_get(ctx); - if (z1 == NULL) goto err; - - x2 = &r->X; - z2 = &r->Y; - - bn_wexpand(x1, group->field.top); - bn_wexpand(z1, group->field.top); - bn_wexpand(x2, group->field.top); - bn_wexpand(z2, group->field.top); - - if (!BN_GF2m_mod_arr(x1, &point->X, group->poly)) goto err; /* x1 = x */ - if (!BN_one(z1)) goto err; /* z1 = 1 */ - if (!group->meth->field_sqr(group, z2, x1, ctx)) goto err; /* z2 = x1^2 = x^2 */ - if (!group->meth->field_sqr(group, x2, z2, ctx)) goto err; - if (!BN_GF2m_add(x2, x2, &group->b)) goto err; /* x2 = x^4 + b */ - - /* find top most bit and go one past it */ - i = scalar->top - 1; - mask = BN_TBIT; - word = scalar->d[i]; - while (!(word & mask)) mask >>= 1; - mask >>= 1; - /* if top most bit was at word break, go to next word */ - if (!mask) - { - i--; - mask = BN_TBIT; - } - - for (; i >= 0; i--) - { - word = scalar->d[i]; - while (mask) - { - BN_consttime_swap(word & mask, x1, x2, group->field.top); - BN_consttime_swap(word & mask, z1, z2, group->field.top); - if (!gf2m_Madd(group, &point->X, x2, z2, x1, z1, ctx)) goto err; - if (!gf2m_Mdouble(group, x1, z1, ctx)) goto err; - BN_consttime_swap(word & mask, x1, x2, group->field.top); - BN_consttime_swap(word & mask, z1, z2, group->field.top); - mask >>= 1; - } - mask = BN_TBIT; - } - - /* convert out of "projective" coordinates */ - i = gf2m_Mxy(group, &point->X, &point->Y, x1, z1, x2, z2, ctx); - if (i == 0) goto err; - else if (i == 1) - { - if (!EC_POINT_set_to_infinity(group, r)) goto err; - } - else - { - if (!BN_one(&r->Z)) goto err; - r->Z_is_one = 1; - } - - /* GF(2^m) field elements should always have BIGNUM::neg = 0 */ - BN_set_negative(&r->X, 0); - BN_set_negative(&r->Y, 0); - - ret = 1; +static int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group, + EC_POINT *r, + const BIGNUM *scalar, + const EC_POINT *point, + BN_CTX *ctx) +{ + BIGNUM *x1, *x2, *z1, *z2; + int ret = 0, i; + BN_ULONG mask, word; + + if (r == point) { + ECerr(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, EC_R_INVALID_ARGUMENT); + return 0; + } + + /* if result should be point at infinity */ + if ((scalar == NULL) || BN_is_zero(scalar) || (point == NULL) || + EC_POINT_is_at_infinity(group, point)) { + return EC_POINT_set_to_infinity(group, r); + } + + /* only support affine coordinates */ + if (!point->Z_is_one) + return 0; + + /* + * Since point_multiply is static we can guarantee that ctx != NULL. + */ + BN_CTX_start(ctx); + x1 = BN_CTX_get(ctx); + z1 = BN_CTX_get(ctx); + if (z1 == NULL) + goto err; + + x2 = &r->X; + z2 = &r->Y; + + bn_wexpand(x1, group->field.top); + bn_wexpand(z1, group->field.top); + bn_wexpand(x2, group->field.top); + bn_wexpand(z2, group->field.top); + + if (!BN_GF2m_mod_arr(x1, &point->X, group->poly)) + goto err; /* x1 = x */ + if (!BN_one(z1)) + goto err; /* z1 = 1 */ + if (!group->meth->field_sqr(group, z2, x1, ctx)) + goto err; /* z2 = x1^2 = x^2 */ + if (!group->meth->field_sqr(group, x2, z2, ctx)) + goto err; + if (!BN_GF2m_add(x2, x2, &group->b)) + goto err; /* x2 = x^4 + b */ + + /* find top most bit and go one past it */ + i = scalar->top - 1; + mask = BN_TBIT; + word = scalar->d[i]; + while (!(word & mask)) + mask >>= 1; + mask >>= 1; + /* if top most bit was at word break, go to next word */ + if (!mask) { + i--; + mask = BN_TBIT; + } + + for (; i >= 0; i--) { + word = scalar->d[i]; + while (mask) { + BN_consttime_swap(word & mask, x1, x2, group->field.top); + BN_consttime_swap(word & mask, z1, z2, group->field.top); + if (!gf2m_Madd(group, &point->X, x2, z2, x1, z1, ctx)) + goto err; + if (!gf2m_Mdouble(group, x1, z1, ctx)) + goto err; + BN_consttime_swap(word & mask, x1, x2, group->field.top); + BN_consttime_swap(word & mask, z1, z2, group->field.top); + mask >>= 1; + } + mask = BN_TBIT; + } + + /* convert out of "projective" coordinates */ + i = gf2m_Mxy(group, &point->X, &point->Y, x1, z1, x2, z2, ctx); + if (i == 0) + goto err; + else if (i == 1) { + if (!EC_POINT_set_to_infinity(group, r)) + goto err; + } else { + if (!BN_one(&r->Z)) + goto err; + r->Z_is_one = 1; + } + + /* GF(2^m) field elements should always have BIGNUM::neg = 0 */ + BN_set_negative(&r->X, 0); + BN_set_negative(&r->Y, 0); + + ret = 1; err: - BN_CTX_end(ctx); - return ret; - } - + BN_CTX_end(ctx); + return ret; +} -/* Computes the sum +/*- + * Computes the sum * scalar*group->generator + scalars[0]*points[0] + ... + scalars[num-1]*points[num-1] * gracefully ignoring NULL scalar values. */ -int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, - size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx) - { - BN_CTX *new_ctx = NULL; - int ret = 0; - size_t i; - EC_POINT *p=NULL; - EC_POINT *acc = NULL; - - if (ctx == NULL) - { - ctx = new_ctx = BN_CTX_new(); - if (ctx == NULL) - return 0; - } - - /* This implementation is more efficient than the wNAF implementation for 2 - * or fewer points. Use the ec_wNAF_mul implementation for 3 or more points, - * or if we can perform a fast multiplication based on precomputation. - */ - if ((scalar && (num > 1)) || (num > 2) || (num == 0 && EC_GROUP_have_precompute_mult(group))) - { - ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); - goto err; - } - - if ((p = EC_POINT_new(group)) == NULL) goto err; - if ((acc = EC_POINT_new(group)) == NULL) goto err; - - if (!EC_POINT_set_to_infinity(group, acc)) goto err; - - if (scalar) - { - if (!ec_GF2m_montgomery_point_multiply(group, p, scalar, group->generator, ctx)) goto err; - if (BN_is_negative(scalar)) - if (!group->meth->invert(group, p, ctx)) goto err; - if (!group->meth->add(group, acc, acc, p, ctx)) goto err; - } - - for (i = 0; i < num; i++) - { - if (!ec_GF2m_montgomery_point_multiply(group, p, scalars[i], points[i], ctx)) goto err; - if (BN_is_negative(scalars[i])) - if (!group->meth->invert(group, p, ctx)) goto err; - if (!group->meth->add(group, acc, acc, p, ctx)) goto err; - } - - if (!EC_POINT_copy(r, acc)) goto err; - - ret = 1; - - err: - if (p) EC_POINT_free(p); - if (acc) EC_POINT_free(acc); - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - return ret; - } - - -/* Precomputation for point multiplication: fall back to wNAF methods - * because ec_GF2m_simple_mul() uses ec_wNAF_mul() if appropriate */ +int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], const BIGNUM *scalars[], + BN_CTX *ctx) +{ + BN_CTX *new_ctx = NULL; + int ret = 0; + size_t i; + EC_POINT *p = NULL; + EC_POINT *acc = NULL; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + /* + * This implementation is more efficient than the wNAF implementation for + * 2 or fewer points. Use the ec_wNAF_mul implementation for 3 or more + * points, or if we can perform a fast multiplication based on + * precomputation. + */ + if ((scalar && (num > 1)) || (num > 2) + || (num == 0 && EC_GROUP_have_precompute_mult(group))) { + ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); + goto err; + } + + if ((p = EC_POINT_new(group)) == NULL) + goto err; + if ((acc = EC_POINT_new(group)) == NULL) + goto err; + + if (!EC_POINT_set_to_infinity(group, acc)) + goto err; + + if (scalar) { + if (!ec_GF2m_montgomery_point_multiply + (group, p, scalar, group->generator, ctx)) + goto err; + if (BN_is_negative(scalar)) + if (!group->meth->invert(group, p, ctx)) + goto err; + if (!group->meth->add(group, acc, acc, p, ctx)) + goto err; + } + + for (i = 0; i < num; i++) { + if (!ec_GF2m_montgomery_point_multiply + (group, p, scalars[i], points[i], ctx)) + goto err; + if (BN_is_negative(scalars[i])) + if (!group->meth->invert(group, p, ctx)) + goto err; + if (!group->meth->add(group, acc, acc, p, ctx)) + goto err; + } + + if (!EC_POINT_copy(r, acc)) + goto err; + + ret = 1; + + err: + if (p) + EC_POINT_free(p); + if (acc) + EC_POINT_free(acc); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; +} + +/* + * Precomputation for point multiplication: fall back to wNAF methods because + * ec_GF2m_simple_mul() uses ec_wNAF_mul() if appropriate + */ int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx) - { - return ec_wNAF_precompute_mult(group, ctx); - } +{ + return ec_wNAF_precompute_mult(group, ctx); +} int ec_GF2m_have_precompute_mult(const EC_GROUP *group) - { - return ec_wNAF_have_precompute_mult(group); - } +{ + return ec_wNAF_have_precompute_mult(group); +} #endif diff --git a/openssl/crypto/ec/ec2_oct.c b/openssl/crypto/ec/ec2_oct.c index f1d75e5dd..c245d886d 100644 --- a/openssl/crypto/ec/ec2_oct.c +++ b/openssl/crypto/ec/ec2_oct.c @@ -21,7 +21,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -73,12 +73,13 @@ #ifndef OPENSSL_NO_EC2M -/* Calculates and sets the affine coordinates of an EC_POINT from the given - * compressed coordinates. Uses algorithm 2.3.4 of SEC 1. +/*- + * Calculates and sets the affine coordinates of an EC_POINT from the given + * compressed coordinates. Uses algorithm 2.3.4 of SEC 1. * Note that the simple implementation only uses affine coordinates. * * The method is from the following publication: - * + * * Harper, Menezes, Vanstone: * "Public-Key Cryptosystems with Very Small Key Lengths", * EUROCRYPT '92, Springer-Verlag LNCS 658, @@ -88,320 +89,315 @@ * the same method, but claim no priority date earlier than July 29, 1994 * (and additionally fail to cite the EUROCRYPT '92 publication as prior art). */ -int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point, - const BIGNUM *x_, int y_bit, BN_CTX *ctx) - { - BN_CTX *new_ctx = NULL; - BIGNUM *tmp, *x, *y, *z; - int ret = 0, z0; - - /* clear error queue */ - ERR_clear_error(); - - if (ctx == NULL) - { - ctx = new_ctx = BN_CTX_new(); - if (ctx == NULL) - return 0; - } - - y_bit = (y_bit != 0) ? 1 : 0; - - BN_CTX_start(ctx); - tmp = BN_CTX_get(ctx); - x = BN_CTX_get(ctx); - y = BN_CTX_get(ctx); - z = BN_CTX_get(ctx); - if (z == NULL) goto err; - - if (!BN_GF2m_mod_arr(x, x_, group->poly)) goto err; - if (BN_is_zero(x)) - { - if (!BN_GF2m_mod_sqrt_arr(y, &group->b, group->poly, ctx)) goto err; - } - else - { - if (!group->meth->field_sqr(group, tmp, x, ctx)) goto err; - if (!group->meth->field_div(group, tmp, &group->b, tmp, ctx)) goto err; - if (!BN_GF2m_add(tmp, &group->a, tmp)) goto err; - if (!BN_GF2m_add(tmp, x, tmp)) goto err; - if (!BN_GF2m_mod_solve_quad_arr(z, tmp, group->poly, ctx)) - { - unsigned long err = ERR_peek_last_error(); - - if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NO_SOLUTION) - { - ERR_clear_error(); - ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT); - } - else - ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB); - goto err; - } - z0 = (BN_is_odd(z)) ? 1 : 0; - if (!group->meth->field_mul(group, y, x, z, ctx)) goto err; - if (z0 != y_bit) - { - if (!BN_GF2m_add(y, y, x)) goto err; - } - } - - if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err; - - ret = 1; +int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group, + EC_POINT *point, + const BIGNUM *x_, int y_bit, + BN_CTX *ctx) +{ + BN_CTX *new_ctx = NULL; + BIGNUM *tmp, *x, *y, *z; + int ret = 0, z0; + + /* clear error queue */ + ERR_clear_error(); + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + y_bit = (y_bit != 0) ? 1 : 0; + + BN_CTX_start(ctx); + tmp = BN_CTX_get(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + z = BN_CTX_get(ctx); + if (z == NULL) + goto err; + + if (!BN_GF2m_mod_arr(x, x_, group->poly)) + goto err; + if (BN_is_zero(x)) { + if (!BN_GF2m_mod_sqrt_arr(y, &group->b, group->poly, ctx)) + goto err; + } else { + if (!group->meth->field_sqr(group, tmp, x, ctx)) + goto err; + if (!group->meth->field_div(group, tmp, &group->b, tmp, ctx)) + goto err; + if (!BN_GF2m_add(tmp, &group->a, tmp)) + goto err; + if (!BN_GF2m_add(tmp, x, tmp)) + goto err; + if (!BN_GF2m_mod_solve_quad_arr(z, tmp, group->poly, ctx)) { + unsigned long err = ERR_peek_last_error(); + + if (ERR_GET_LIB(err) == ERR_LIB_BN + && ERR_GET_REASON(err) == BN_R_NO_SOLUTION) { + ERR_clear_error(); + ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, + EC_R_INVALID_COMPRESSED_POINT); + } else + ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, + ERR_R_BN_LIB); + goto err; + } + z0 = (BN_is_odd(z)) ? 1 : 0; + if (!group->meth->field_mul(group, y, x, z, ctx)) + goto err; + if (z0 != y_bit) { + if (!BN_GF2m_add(y, y, x)) + goto err; + } + } + + if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) + goto err; + + ret = 1; err: - BN_CTX_end(ctx); - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - return ret; - } - - -/* Converts an EC_POINT to an octet string. - * If buf is NULL, the encoded length will be returned. - * If the length len of buf is smaller than required an error will be returned. + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; +} + +/* + * Converts an EC_POINT to an octet string. If buf is NULL, the encoded + * length will be returned. If the length len of buf is smaller than required + * an error will be returned. */ -size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form, - unsigned char *buf, size_t len, BN_CTX *ctx) - { - size_t ret; - BN_CTX *new_ctx = NULL; - int used_ctx = 0; - BIGNUM *x, *y, *yxi; - size_t field_len, i, skip; - - if ((form != POINT_CONVERSION_COMPRESSED) - && (form != POINT_CONVERSION_UNCOMPRESSED) - && (form != POINT_CONVERSION_HYBRID)) - { - ECerr(EC_F_EC_GF2M_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_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); - return 0; - } - buf[0] = 0; - } - return 1; - } - - - /* ret := required output buffer length */ - field_len = (EC_GROUP_get_degree(group) + 7) / 8; - 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_GF2M_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); - yxi = BN_CTX_get(ctx); - if (yxi == NULL) goto err; - - if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err; - - buf[0] = form; - if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x)) - { - if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err; - if (BN_is_odd(yxi)) buf[0]++; - } - - i = 1; - - skip = field_len - BN_num_bytes(x); - if (skip > field_len) - { - ECerr(EC_F_EC_GF2M_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_GF2M_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_GF2M_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_GF2M_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; +size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, + point_conversion_form_t form, + unsigned char *buf, size_t len, BN_CTX *ctx) +{ + size_t ret; + BN_CTX *new_ctx = NULL; + int used_ctx = 0; + BIGNUM *x, *y, *yxi; + size_t field_len, i, skip; + + if ((form != POINT_CONVERSION_COMPRESSED) + && (form != POINT_CONVERSION_UNCOMPRESSED) + && (form != POINT_CONVERSION_HYBRID)) { + ECerr(EC_F_EC_GF2M_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_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); + return 0; + } + buf[0] = 0; + } + return 1; + } + + /* ret := required output buffer length */ + field_len = (EC_GROUP_get_degree(group) + 7) / 8; + 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_GF2M_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); + yxi = BN_CTX_get(ctx); + if (yxi == NULL) + goto err; + + if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) + goto err; + + buf[0] = form; + if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x)) { + if (!group->meth->field_div(group, yxi, y, x, ctx)) + goto err; + if (BN_is_odd(yxi)) + buf[0]++; + } + + i = 1; + + skip = field_len - BN_num_bytes(x); + if (skip > field_len) { + ECerr(EC_F_EC_GF2M_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_GF2M_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_GF2M_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_GF2M_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; - } - - -/* Converts an octet string representation to an EC_POINT. - * Note that the simple implementation only uses affine coordinates. + if (used_ctx) + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return 0; +} + +/* + * Converts an octet string representation to an EC_POINT. Note that the + * simple implementation only uses affine coordinates. */ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, - 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, *yxi; - size_t field_len, enc_len; - int ret = 0; - - if (len == 0) - { - ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL); - return 0; - } - form = buf[0]; - y_bit = form & 1; - form = form & ~1U; - if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED) - && (form != POINT_CONVERSION_UNCOMPRESSED) - && (form != POINT_CONVERSION_HYBRID)) - { - ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); - return 0; - } - if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) - { - ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); - return 0; - } - - if (form == 0) - { - if (len != 1) - { - ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); - return 0; - } - - return EC_POINT_set_to_infinity(group, point); - } - - field_len = (EC_GROUP_get_degree(group) + 7) / 8; - enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len; - - if (len != enc_len) - { - ECerr(EC_F_EC_GF2M_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); - yxi = BN_CTX_get(ctx); - if (yxi == NULL) goto err; - - if (!BN_bin2bn(buf + 1, field_len, x)) goto err; - if (BN_ucmp(x, &group->field) >= 0) - { - ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); - goto err; - } - - if (form == POINT_CONVERSION_COMPRESSED) - { - if (!EC_POINT_set_compressed_coordinates_GF2m(group, point, x, y_bit, ctx)) goto err; - } - else - { - if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err; - if (BN_ucmp(y, &group->field) >= 0) - { - ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); - goto err; - } - if (form == POINT_CONVERSION_HYBRID) - { - if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err; - if (y_bit != BN_is_odd(yxi)) - { - ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); - goto err; - } - } - - if (!EC_POINT_set_affine_coordinates_GF2m(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_GF2M_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE); - goto err; - } - - ret = 1; - + 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, *yxi; + size_t field_len, enc_len; + int ret = 0; + + if (len == 0) { + ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL); + return 0; + } + form = buf[0]; + y_bit = form & 1; + form = form & ~1U; + if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED) + && (form != POINT_CONVERSION_UNCOMPRESSED) + && (form != POINT_CONVERSION_HYBRID)) { + ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + return 0; + } + if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) { + ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + return 0; + } + + if (form == 0) { + if (len != 1) { + ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + return 0; + } + + return EC_POINT_set_to_infinity(group, point); + } + + field_len = (EC_GROUP_get_degree(group) + 7) / 8; + enc_len = + (form == + POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len; + + if (len != enc_len) { + ECerr(EC_F_EC_GF2M_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); + yxi = BN_CTX_get(ctx); + if (yxi == NULL) + goto err; + + if (!BN_bin2bn(buf + 1, field_len, x)) + goto err; + if (BN_ucmp(x, &group->field) >= 0) { + ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + goto err; + } + + if (form == POINT_CONVERSION_COMPRESSED) { + if (!EC_POINT_set_compressed_coordinates_GF2m + (group, point, x, y_bit, ctx)) + goto err; + } else { + if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) + goto err; + if (BN_ucmp(y, &group->field) >= 0) { + ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + goto err; + } + if (form == POINT_CONVERSION_HYBRID) { + if (!group->meth->field_div(group, yxi, y, x, ctx)) + goto err; + if (y_bit != BN_is_odd(yxi)) { + ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + goto err; + } + } + + if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) + goto err; + } + + /* test required by X9.62 */ + if (!EC_POINT_is_on_curve(group, point, ctx)) { + ECerr(EC_F_EC_GF2M_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; - } + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; +} #endif diff --git a/openssl/crypto/ec/ec2_smpl.c b/openssl/crypto/ec/ec2_smpl.c index 62223cbb0..077c7fc8d 100644 --- a/openssl/crypto/ec/ec2_smpl.c +++ b/openssl/crypto/ec/ec2_smpl.c @@ -21,7 +21,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -73,648 +73,725 @@ #ifndef OPENSSL_NO_EC2M -#ifdef OPENSSL_FIPS -#include <openssl/fips.h> -#endif - +# ifdef OPENSSL_FIPS +# include <openssl/fips.h> +# endif const EC_METHOD *EC_GF2m_simple_method(void) - { - static const EC_METHOD ret = { - EC_FLAGS_DEFAULT_OCT, - NID_X9_62_characteristic_two_field, - ec_GF2m_simple_group_init, - ec_GF2m_simple_group_finish, - ec_GF2m_simple_group_clear_finish, - ec_GF2m_simple_group_copy, - ec_GF2m_simple_group_set_curve, - ec_GF2m_simple_group_get_curve, - ec_GF2m_simple_group_get_degree, - ec_GF2m_simple_group_check_discriminant, - ec_GF2m_simple_point_init, - ec_GF2m_simple_point_finish, - ec_GF2m_simple_point_clear_finish, - ec_GF2m_simple_point_copy, - ec_GF2m_simple_point_set_to_infinity, - 0 /* set_Jprojective_coordinates_GFp */, - 0 /* get_Jprojective_coordinates_GFp */, - ec_GF2m_simple_point_set_affine_coordinates, - ec_GF2m_simple_point_get_affine_coordinates, - 0,0,0, - ec_GF2m_simple_add, - ec_GF2m_simple_dbl, - ec_GF2m_simple_invert, - ec_GF2m_simple_is_at_infinity, - ec_GF2m_simple_is_on_curve, - ec_GF2m_simple_cmp, - ec_GF2m_simple_make_affine, - ec_GF2m_simple_points_make_affine, - - /* the following three method functions are defined in ec2_mult.c */ - ec_GF2m_simple_mul, - ec_GF2m_precompute_mult, - ec_GF2m_have_precompute_mult, - - ec_GF2m_simple_field_mul, - ec_GF2m_simple_field_sqr, - ec_GF2m_simple_field_div, - 0 /* field_encode */, - 0 /* field_decode */, - 0 /* field_set_to_one */ }; - -#ifdef OPENSSL_FIPS - if (FIPS_mode()) - return fips_ec_gf2m_simple_method(); -#endif - - return &ret; - } - - -/* Initialize a GF(2^m)-based EC_GROUP structure. - * Note that all other members are handled by EC_GROUP_new. +{ + static const EC_METHOD ret = { + EC_FLAGS_DEFAULT_OCT, + NID_X9_62_characteristic_two_field, + ec_GF2m_simple_group_init, + ec_GF2m_simple_group_finish, + ec_GF2m_simple_group_clear_finish, + ec_GF2m_simple_group_copy, + ec_GF2m_simple_group_set_curve, + ec_GF2m_simple_group_get_curve, + ec_GF2m_simple_group_get_degree, + ec_GF2m_simple_group_check_discriminant, + ec_GF2m_simple_point_init, + ec_GF2m_simple_point_finish, + ec_GF2m_simple_point_clear_finish, + ec_GF2m_simple_point_copy, + ec_GF2m_simple_point_set_to_infinity, + 0 /* set_Jprojective_coordinates_GFp */ , + 0 /* get_Jprojective_coordinates_GFp */ , + ec_GF2m_simple_point_set_affine_coordinates, + ec_GF2m_simple_point_get_affine_coordinates, + 0, 0, 0, + ec_GF2m_simple_add, + ec_GF2m_simple_dbl, + ec_GF2m_simple_invert, + ec_GF2m_simple_is_at_infinity, + ec_GF2m_simple_is_on_curve, + ec_GF2m_simple_cmp, + ec_GF2m_simple_make_affine, + ec_GF2m_simple_points_make_affine, + + /* + * the following three method functions are defined in ec2_mult.c + */ + ec_GF2m_simple_mul, + ec_GF2m_precompute_mult, + ec_GF2m_have_precompute_mult, + + ec_GF2m_simple_field_mul, + ec_GF2m_simple_field_sqr, + ec_GF2m_simple_field_div, + 0 /* field_encode */ , + 0 /* field_decode */ , + 0 /* field_set_to_one */ + }; + +# ifdef OPENSSL_FIPS + if (FIPS_mode()) + return fips_ec_gf2m_simple_method(); +# endif + + return &ret; +} + +/* + * Initialize a GF(2^m)-based EC_GROUP structure. Note that all other members + * are handled by EC_GROUP_new. */ int ec_GF2m_simple_group_init(EC_GROUP *group) - { - BN_init(&group->field); - BN_init(&group->a); - BN_init(&group->b); - return 1; - } - - -/* Free a GF(2^m)-based EC_GROUP structure. - * Note that all other members are handled by EC_GROUP_free. +{ + BN_init(&group->field); + BN_init(&group->a); + BN_init(&group->b); + return 1; +} + +/* + * Free a GF(2^m)-based EC_GROUP structure. Note that all other members are + * handled by EC_GROUP_free. */ void ec_GF2m_simple_group_finish(EC_GROUP *group) - { - BN_free(&group->field); - BN_free(&group->a); - BN_free(&group->b); - } - - -/* Clear and free a GF(2^m)-based EC_GROUP structure. - * Note that all other members are handled by EC_GROUP_clear_free. +{ + BN_free(&group->field); + BN_free(&group->a); + BN_free(&group->b); +} + +/* + * Clear and free a GF(2^m)-based EC_GROUP structure. Note that all other + * members are handled by EC_GROUP_clear_free. */ void ec_GF2m_simple_group_clear_finish(EC_GROUP *group) - { - BN_clear_free(&group->field); - BN_clear_free(&group->a); - BN_clear_free(&group->b); - group->poly[0] = 0; - group->poly[1] = 0; - group->poly[2] = 0; - group->poly[3] = 0; - group->poly[4] = 0; - group->poly[5] = -1; - } - - -/* Copy a GF(2^m)-based EC_GROUP structure. - * Note that all other members are handled by EC_GROUP_copy. +{ + BN_clear_free(&group->field); + BN_clear_free(&group->a); + BN_clear_free(&group->b); + group->poly[0] = 0; + group->poly[1] = 0; + group->poly[2] = 0; + group->poly[3] = 0; + group->poly[4] = 0; + group->poly[5] = -1; +} + +/* + * Copy a GF(2^m)-based EC_GROUP structure. Note that all other members are + * handled by EC_GROUP_copy. */ int ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) - { - int i; - if (!BN_copy(&dest->field, &src->field)) return 0; - if (!BN_copy(&dest->a, &src->a)) return 0; - if (!BN_copy(&dest->b, &src->b)) return 0; - dest->poly[0] = src->poly[0]; - dest->poly[1] = src->poly[1]; - dest->poly[2] = src->poly[2]; - dest->poly[3] = src->poly[3]; - dest->poly[4] = src->poly[4]; - dest->poly[5] = src->poly[5]; - if (bn_wexpand(&dest->a, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) return 0; - if (bn_wexpand(&dest->b, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) return 0; - for (i = dest->a.top; i < dest->a.dmax; i++) dest->a.d[i] = 0; - for (i = dest->b.top; i < dest->b.dmax; i++) dest->b.d[i] = 0; - return 1; - } - +{ + int i; + if (!BN_copy(&dest->field, &src->field)) + return 0; + if (!BN_copy(&dest->a, &src->a)) + return 0; + if (!BN_copy(&dest->b, &src->b)) + return 0; + dest->poly[0] = src->poly[0]; + dest->poly[1] = src->poly[1]; + dest->poly[2] = src->poly[2]; + dest->poly[3] = src->poly[3]; + dest->poly[4] = src->poly[4]; + dest->poly[5] = src->poly[5]; + if (bn_wexpand(&dest->a, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) + == NULL) + return 0; + if (bn_wexpand(&dest->b, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) + == NULL) + return 0; + for (i = dest->a.top; i < dest->a.dmax; i++) + dest->a.d[i] = 0; + for (i = dest->b.top; i < dest->b.dmax; i++) + dest->b.d[i] = 0; + return 1; +} /* Set the curve parameters of an EC_GROUP structure. */ int ec_GF2m_simple_group_set_curve(EC_GROUP *group, - const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) - { - int ret = 0, i; - - /* group->field */ - if (!BN_copy(&group->field, p)) goto err; - i = BN_GF2m_poly2arr(&group->field, group->poly, 6) - 1; - if ((i != 5) && (i != 3)) - { - ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIELD); - goto err; - } - - /* group->a */ - if (!BN_GF2m_mod_arr(&group->a, a, group->poly)) goto err; - if(bn_wexpand(&group->a, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) goto err; - for (i = group->a.top; i < group->a.dmax; i++) group->a.d[i] = 0; - - /* group->b */ - if (!BN_GF2m_mod_arr(&group->b, b, group->poly)) goto err; - if(bn_wexpand(&group->b, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) goto err; - for (i = group->b.top; i < group->b.dmax; i++) group->b.d[i] = 0; - - ret = 1; - err: - return ret; - } - - -/* Get the curve parameters of an EC_GROUP structure. - * If p, a, or b are NULL then there values will not be set but the method will return with success. + const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx) +{ + int ret = 0, i; + + /* group->field */ + if (!BN_copy(&group->field, p)) + goto err; + i = BN_GF2m_poly2arr(&group->field, group->poly, 6) - 1; + if ((i != 5) && (i != 3)) { + ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIELD); + goto err; + } + + /* group->a */ + if (!BN_GF2m_mod_arr(&group->a, a, group->poly)) + goto err; + if (bn_wexpand(&group->a, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) + == NULL) + goto err; + for (i = group->a.top; i < group->a.dmax; i++) + group->a.d[i] = 0; + + /* group->b */ + if (!BN_GF2m_mod_arr(&group->b, b, group->poly)) + goto err; + if (bn_wexpand(&group->b, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) + == NULL) + goto err; + for (i = group->b.top; i < group->b.dmax; i++) + group->b.d[i] = 0; + + ret = 1; + err: + return ret; +} + +/* + * Get the curve parameters of an EC_GROUP structure. If p, a, or b are NULL + * then there values will not be set but the method will return with success. */ -int ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx) - { - int ret = 0; - - if (p != NULL) - { - if (!BN_copy(p, &group->field)) return 0; - } - - if (a != NULL) - { - if (!BN_copy(a, &group->a)) goto err; - } - - if (b != NULL) - { - if (!BN_copy(b, &group->b)) goto err; - } - - ret = 1; - - err: - return ret; - } - - -/* Gets the degree of the field. For a curve over GF(2^m) this is the value m. */ -int ec_GF2m_simple_group_get_degree(const EC_GROUP *group) - { - return BN_num_bits(&group->field)-1; - } +int ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, + BIGNUM *a, BIGNUM *b, BN_CTX *ctx) +{ + int ret = 0; + + if (p != NULL) { + if (!BN_copy(p, &group->field)) + return 0; + } + + if (a != NULL) { + if (!BN_copy(a, &group->a)) + goto err; + } + + if (b != NULL) { + if (!BN_copy(b, &group->b)) + goto err; + } + + ret = 1; + + err: + return ret; +} +/* + * Gets the degree of the field. For a curve over GF(2^m) this is the value + * m. + */ +int ec_GF2m_simple_group_get_degree(const EC_GROUP *group) +{ + return BN_num_bits(&group->field) - 1; +} -/* Checks the discriminant of the curve. - * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p) +/* + * Checks the discriminant of the curve. y^2 + x*y = x^3 + a*x^2 + b is an + * elliptic curve <=> b != 0 (mod p) */ -int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) - { - int ret = 0; - BIGNUM *b; - BN_CTX *new_ctx = NULL; - - if (ctx == NULL) - { - ctx = new_ctx = BN_CTX_new(); - if (ctx == NULL) - { - ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT, ERR_R_MALLOC_FAILURE); - goto err; - } - } - BN_CTX_start(ctx); - b = BN_CTX_get(ctx); - if (b == NULL) goto err; - - if (!BN_GF2m_mod_arr(b, &group->b, group->poly)) goto err; - - /* check the discriminant: - * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p) - */ - if (BN_is_zero(b)) goto err; - - ret = 1; - -err: - if (ctx != NULL) - BN_CTX_end(ctx); - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - return ret; - } +int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group, + BN_CTX *ctx) +{ + int ret = 0; + BIGNUM *b; + BN_CTX *new_ctx = NULL; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT, + ERR_R_MALLOC_FAILURE); + goto err; + } + } + BN_CTX_start(ctx); + b = BN_CTX_get(ctx); + if (b == NULL) + goto err; + + if (!BN_GF2m_mod_arr(b, &group->b, group->poly)) + goto err; + + /* + * check the discriminant: y^2 + x*y = x^3 + a*x^2 + b is an elliptic + * curve <=> b != 0 (mod p) + */ + if (BN_is_zero(b)) + goto err; + + ret = 1; + err: + if (ctx != NULL) + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; +} /* Initializes an EC_POINT. */ int ec_GF2m_simple_point_init(EC_POINT *point) - { - BN_init(&point->X); - BN_init(&point->Y); - BN_init(&point->Z); - return 1; - } - +{ + BN_init(&point->X); + BN_init(&point->Y); + BN_init(&point->Z); + return 1; +} /* Frees an EC_POINT. */ void ec_GF2m_simple_point_finish(EC_POINT *point) - { - BN_free(&point->X); - BN_free(&point->Y); - BN_free(&point->Z); - } - +{ + BN_free(&point->X); + BN_free(&point->Y); + BN_free(&point->Z); +} /* Clears and frees an EC_POINT. */ void ec_GF2m_simple_point_clear_finish(EC_POINT *point) - { - BN_clear_free(&point->X); - BN_clear_free(&point->Y); - BN_clear_free(&point->Z); - point->Z_is_one = 0; - } - - -/* Copy the contents of one EC_POINT into another. Assumes dest is initialized. */ -int ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src) - { - if (!BN_copy(&dest->X, &src->X)) return 0; - if (!BN_copy(&dest->Y, &src->Y)) return 0; - if (!BN_copy(&dest->Z, &src->Z)) return 0; - dest->Z_is_one = src->Z_is_one; - - return 1; - } - - -/* Set an EC_POINT to the point at infinity. - * A point at infinity is represented by having Z=0. +{ + BN_clear_free(&point->X); + BN_clear_free(&point->Y); + BN_clear_free(&point->Z); + point->Z_is_one = 0; +} + +/* + * Copy the contents of one EC_POINT into another. Assumes dest is + * initialized. */ -int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point) - { - point->Z_is_one = 0; - BN_zero(&point->Z); - return 1; - } - - -/* Set the coordinates of an EC_POINT using affine coordinates. - * Note that the simple implementation only uses affine coordinates. +int ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src) +{ + if (!BN_copy(&dest->X, &src->X)) + return 0; + if (!BN_copy(&dest->Y, &src->Y)) + return 0; + if (!BN_copy(&dest->Z, &src->Z)) + return 0; + dest->Z_is_one = src->Z_is_one; + + return 1; +} + +/* + * Set an EC_POINT to the point at infinity. A point at infinity is + * represented by having Z=0. */ -int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point, - const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) - { - int ret = 0; - if (x == NULL || y == NULL) - { - ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - - if (!BN_copy(&point->X, x)) goto err; - BN_set_negative(&point->X, 0); - if (!BN_copy(&point->Y, y)) goto err; - BN_set_negative(&point->Y, 0); - if (!BN_copy(&point->Z, BN_value_one())) goto err; - BN_set_negative(&point->Z, 0); - point->Z_is_one = 1; - ret = 1; - - err: - return ret; - } - - -/* Gets the affine coordinates of an EC_POINT. - * Note that the simple implementation only uses affine coordinates. +int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group, + EC_POINT *point) +{ + point->Z_is_one = 0; + BN_zero(&point->Z); + return 1; +} + +/* + * Set the coordinates of an EC_POINT using affine coordinates. Note that + * the simple implementation only uses affine coordinates. */ -int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point, - BIGNUM *x, BIGNUM *y, BN_CTX *ctx) - { - int ret = 0; - - if (EC_POINT_is_at_infinity(group, point)) - { - ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY); - return 0; - } - - if (BN_cmp(&point->Z, BN_value_one())) - { - ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } - if (x != NULL) - { - if (!BN_copy(x, &point->X)) goto err; - BN_set_negative(x, 0); - } - if (y != NULL) - { - if (!BN_copy(y, &point->Y)) goto err; - BN_set_negative(y, 0); - } - ret = 1; - +int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group, + EC_POINT *point, + const BIGNUM *x, + const BIGNUM *y, BN_CTX *ctx) +{ + int ret = 0; + if (x == NULL || y == NULL) { + ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (!BN_copy(&point->X, x)) + goto err; + BN_set_negative(&point->X, 0); + if (!BN_copy(&point->Y, y)) + goto err; + BN_set_negative(&point->Y, 0); + if (!BN_copy(&point->Z, BN_value_one())) + goto err; + BN_set_negative(&point->Z, 0); + point->Z_is_one = 1; + ret = 1; + err: - return ret; - } + return ret; +} -/* Computes a + b and stores the result in r. r could be a or b, a could be b. - * Uses algorithm A.10.2 of IEEE P1363. +/* + * Gets the affine coordinates of an EC_POINT. Note that the simple + * implementation only uses affine coordinates. */ -int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) - { - BN_CTX *new_ctx = NULL; - BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t; - int ret = 0; - - if (EC_POINT_is_at_infinity(group, a)) - { - if (!EC_POINT_copy(r, b)) return 0; - return 1; - } - - if (EC_POINT_is_at_infinity(group, b)) - { - if (!EC_POINT_copy(r, a)) return 0; - return 1; - } - - if (ctx == NULL) - { - ctx = new_ctx = BN_CTX_new(); - if (ctx == NULL) - return 0; - } - - BN_CTX_start(ctx); - x0 = BN_CTX_get(ctx); - y0 = BN_CTX_get(ctx); - x1 = BN_CTX_get(ctx); - y1 = BN_CTX_get(ctx); - x2 = BN_CTX_get(ctx); - y2 = BN_CTX_get(ctx); - s = BN_CTX_get(ctx); - t = BN_CTX_get(ctx); - if (t == NULL) goto err; - - if (a->Z_is_one) - { - if (!BN_copy(x0, &a->X)) goto err; - if (!BN_copy(y0, &a->Y)) goto err; - } - else - { - if (!EC_POINT_get_affine_coordinates_GF2m(group, a, x0, y0, ctx)) goto err; - } - if (b->Z_is_one) - { - if (!BN_copy(x1, &b->X)) goto err; - if (!BN_copy(y1, &b->Y)) goto err; - } - else - { - if (!EC_POINT_get_affine_coordinates_GF2m(group, b, x1, y1, ctx)) goto err; - } - - - if (BN_GF2m_cmp(x0, x1)) - { - if (!BN_GF2m_add(t, x0, x1)) goto err; - if (!BN_GF2m_add(s, y0, y1)) goto err; - if (!group->meth->field_div(group, s, s, t, ctx)) goto err; - if (!group->meth->field_sqr(group, x2, s, ctx)) goto err; - if (!BN_GF2m_add(x2, x2, &group->a)) goto err; - if (!BN_GF2m_add(x2, x2, s)) goto err; - if (!BN_GF2m_add(x2, x2, t)) goto err; - } - else - { - if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1)) - { - if (!EC_POINT_set_to_infinity(group, r)) goto err; - ret = 1; - goto err; - } - if (!group->meth->field_div(group, s, y1, x1, ctx)) goto err; - if (!BN_GF2m_add(s, s, x1)) goto err; - - if (!group->meth->field_sqr(group, x2, s, ctx)) goto err; - if (!BN_GF2m_add(x2, x2, s)) goto err; - if (!BN_GF2m_add(x2, x2, &group->a)) goto err; - } - - if (!BN_GF2m_add(y2, x1, x2)) goto err; - if (!group->meth->field_mul(group, y2, y2, s, ctx)) goto err; - if (!BN_GF2m_add(y2, y2, x2)) goto err; - if (!BN_GF2m_add(y2, y2, y1)) goto err; - - if (!EC_POINT_set_affine_coordinates_GF2m(group, r, x2, y2, ctx)) goto err; - - ret = 1; +int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx) +{ + int ret = 0; + + if (EC_POINT_is_at_infinity(group, point)) { + ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, + EC_R_POINT_AT_INFINITY); + return 0; + } + + if (BN_cmp(&point->Z, BN_value_one())) { + ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (x != NULL) { + if (!BN_copy(x, &point->X)) + goto err; + BN_set_negative(x, 0); + } + if (y != NULL) { + if (!BN_copy(y, &point->Y)) + goto err; + BN_set_negative(y, 0); + } + ret = 1; err: - BN_CTX_end(ctx); - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - return ret; - } - + return ret; +} -/* Computes 2 * a and stores the result in r. r could be a. - * Uses algorithm A.10.2 of IEEE P1363. +/* + * Computes a + b and stores the result in r. r could be a or b, a could be + * b. Uses algorithm A.10.2 of IEEE P1363. */ -int ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx) - { - return ec_GF2m_simple_add(group, r, a, a, ctx); - } +int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, + const EC_POINT *b, BN_CTX *ctx) +{ + BN_CTX *new_ctx = NULL; + BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t; + int ret = 0; + + if (EC_POINT_is_at_infinity(group, a)) { + if (!EC_POINT_copy(r, b)) + return 0; + return 1; + } + + if (EC_POINT_is_at_infinity(group, b)) { + if (!EC_POINT_copy(r, a)) + return 0; + return 1; + } + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + x0 = BN_CTX_get(ctx); + y0 = BN_CTX_get(ctx); + x1 = BN_CTX_get(ctx); + y1 = BN_CTX_get(ctx); + x2 = BN_CTX_get(ctx); + y2 = BN_CTX_get(ctx); + s = BN_CTX_get(ctx); + t = BN_CTX_get(ctx); + if (t == NULL) + goto err; + + if (a->Z_is_one) { + if (!BN_copy(x0, &a->X)) + goto err; + if (!BN_copy(y0, &a->Y)) + goto err; + } else { + if (!EC_POINT_get_affine_coordinates_GF2m(group, a, x0, y0, ctx)) + goto err; + } + if (b->Z_is_one) { + if (!BN_copy(x1, &b->X)) + goto err; + if (!BN_copy(y1, &b->Y)) + goto err; + } else { + if (!EC_POINT_get_affine_coordinates_GF2m(group, b, x1, y1, ctx)) + goto err; + } + + if (BN_GF2m_cmp(x0, x1)) { + if (!BN_GF2m_add(t, x0, x1)) + goto err; + if (!BN_GF2m_add(s, y0, y1)) + goto err; + if (!group->meth->field_div(group, s, s, t, ctx)) + goto err; + if (!group->meth->field_sqr(group, x2, s, ctx)) + goto err; + if (!BN_GF2m_add(x2, x2, &group->a)) + goto err; + if (!BN_GF2m_add(x2, x2, s)) + goto err; + if (!BN_GF2m_add(x2, x2, t)) + goto err; + } else { + if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1)) { + if (!EC_POINT_set_to_infinity(group, r)) + goto err; + ret = 1; + goto err; + } + if (!group->meth->field_div(group, s, y1, x1, ctx)) + goto err; + if (!BN_GF2m_add(s, s, x1)) + goto err; + + if (!group->meth->field_sqr(group, x2, s, ctx)) + goto err; + if (!BN_GF2m_add(x2, x2, s)) + goto err; + if (!BN_GF2m_add(x2, x2, &group->a)) + goto err; + } + + if (!BN_GF2m_add(y2, x1, x2)) + goto err; + if (!group->meth->field_mul(group, y2, y2, s, ctx)) + goto err; + if (!BN_GF2m_add(y2, y2, x2)) + goto err; + if (!BN_GF2m_add(y2, y2, y1)) + goto err; + + if (!EC_POINT_set_affine_coordinates_GF2m(group, r, x2, y2, ctx)) + goto err; + + ret = 1; + err: + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; +} + +/* + * Computes 2 * a and stores the result in r. r could be a. Uses algorithm + * A.10.2 of IEEE P1363. + */ +int ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, + BN_CTX *ctx) +{ + return ec_GF2m_simple_add(group, r, a, a, ctx); +} int ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) - { - if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y)) - /* point is its own inverse */ - return 1; - - if (!EC_POINT_make_affine(group, point, ctx)) return 0; - return BN_GF2m_add(&point->Y, &point->X, &point->Y); - } +{ + if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y)) + /* point is its own inverse */ + return 1; + if (!EC_POINT_make_affine(group, point, ctx)) + return 0; + return BN_GF2m_add(&point->Y, &point->X, &point->Y); +} /* Indicates whether the given point is the point at infinity. */ -int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) - { - return BN_is_zero(&point->Z); - } - - -/* Determines whether the given EC_POINT is an actual point on the curve defined +int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group, + const EC_POINT *point) +{ + return BN_is_zero(&point->Z); +} + +/*- + * Determines whether the given EC_POINT is an actual point on the curve defined * in the EC_GROUP. A point is valid if it satisfies the Weierstrass equation: * y^2 + x*y = x^3 + a*x^2 + b. */ -int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx) - { - int ret = -1; - BN_CTX *new_ctx = NULL; - BIGNUM *lh, *y2; - int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); - int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); - - if (EC_POINT_is_at_infinity(group, point)) - return 1; - - field_mul = group->meth->field_mul; - field_sqr = group->meth->field_sqr; - - /* only support affine coordinates */ - if (!point->Z_is_one) return -1; - - if (ctx == NULL) - { - ctx = new_ctx = BN_CTX_new(); - if (ctx == NULL) - return -1; - } - - BN_CTX_start(ctx); - y2 = BN_CTX_get(ctx); - lh = BN_CTX_get(ctx); - if (lh == NULL) goto err; - - /* We have a curve defined by a Weierstrass equation - * y^2 + x*y = x^3 + a*x^2 + b. - * <=> x^3 + a*x^2 + x*y + b + y^2 = 0 - * <=> ((x + a) * x + y ) * x + b + y^2 = 0 - */ - if (!BN_GF2m_add(lh, &point->X, &group->a)) goto err; - if (!field_mul(group, lh, lh, &point->X, ctx)) goto err; - if (!BN_GF2m_add(lh, lh, &point->Y)) goto err; - if (!field_mul(group, lh, lh, &point->X, ctx)) goto err; - if (!BN_GF2m_add(lh, lh, &group->b)) goto err; - if (!field_sqr(group, y2, &point->Y, ctx)) goto err; - if (!BN_GF2m_add(lh, lh, y2)) goto err; - ret = BN_is_zero(lh); +int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, + BN_CTX *ctx) +{ + int ret = -1; + BN_CTX *new_ctx = NULL; + BIGNUM *lh, *y2; + int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, + const BIGNUM *, BN_CTX *); + int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); + + if (EC_POINT_is_at_infinity(group, point)) + return 1; + + field_mul = group->meth->field_mul; + field_sqr = group->meth->field_sqr; + + /* only support affine coordinates */ + if (!point->Z_is_one) + return -1; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return -1; + } + + BN_CTX_start(ctx); + y2 = BN_CTX_get(ctx); + lh = BN_CTX_get(ctx); + if (lh == NULL) + goto err; + + /*- + * We have a curve defined by a Weierstrass equation + * y^2 + x*y = x^3 + a*x^2 + b. + * <=> x^3 + a*x^2 + x*y + b + y^2 = 0 + * <=> ((x + a) * x + y ) * x + b + y^2 = 0 + */ + if (!BN_GF2m_add(lh, &point->X, &group->a)) + goto err; + if (!field_mul(group, lh, lh, &point->X, ctx)) + goto err; + if (!BN_GF2m_add(lh, lh, &point->Y)) + goto err; + if (!field_mul(group, lh, lh, &point->X, ctx)) + goto err; + if (!BN_GF2m_add(lh, lh, &group->b)) + goto err; + if (!field_sqr(group, y2, &point->Y, ctx)) + goto err; + if (!BN_GF2m_add(lh, lh, y2)) + goto err; + ret = BN_is_zero(lh); err: - if (ctx) BN_CTX_end(ctx); - if (new_ctx) BN_CTX_free(new_ctx); - return ret; - } - - -/* Indicates whether two points are equal. + if (ctx) + BN_CTX_end(ctx); + if (new_ctx) + BN_CTX_free(new_ctx); + return ret; +} + +/*- + * Indicates whether two points are equal. * Return values: * -1 error * 0 equal (in affine coordinates) * 1 not equal */ -int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) - { - BIGNUM *aX, *aY, *bX, *bY; - BN_CTX *new_ctx = NULL; - int ret = -1; - - if (EC_POINT_is_at_infinity(group, a)) - { - 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) - { - return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1; - } - - if (ctx == NULL) - { - ctx = new_ctx = BN_CTX_new(); - if (ctx == NULL) - return -1; - } - - BN_CTX_start(ctx); - aX = BN_CTX_get(ctx); - aY = BN_CTX_get(ctx); - bX = BN_CTX_get(ctx); - bY = BN_CTX_get(ctx); - if (bY == NULL) goto err; - - if (!EC_POINT_get_affine_coordinates_GF2m(group, a, aX, aY, ctx)) goto err; - if (!EC_POINT_get_affine_coordinates_GF2m(group, b, bX, bY, ctx)) goto err; - ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1; - - err: - if (ctx) BN_CTX_end(ctx); - if (new_ctx) BN_CTX_free(new_ctx); - return ret; - } +int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a, + const EC_POINT *b, BN_CTX *ctx) +{ + BIGNUM *aX, *aY, *bX, *bY; + BN_CTX *new_ctx = NULL; + int ret = -1; + + if (EC_POINT_is_at_infinity(group, a)) { + 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) { + return ((BN_cmp(&a->X, &b->X) == 0) + && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1; + } + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return -1; + } + + BN_CTX_start(ctx); + aX = BN_CTX_get(ctx); + aY = BN_CTX_get(ctx); + bX = BN_CTX_get(ctx); + bY = BN_CTX_get(ctx); + if (bY == NULL) + goto err; + + if (!EC_POINT_get_affine_coordinates_GF2m(group, a, aX, aY, ctx)) + goto err; + if (!EC_POINT_get_affine_coordinates_GF2m(group, b, bX, bY, ctx)) + goto err; + ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1; + err: + if (ctx) + BN_CTX_end(ctx); + if (new_ctx) + BN_CTX_free(new_ctx); + return ret; +} /* Forces the given EC_POINT to internally use affine coordinates. */ -int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) - { - BN_CTX *new_ctx = NULL; - BIGNUM *x, *y; - int ret = 0; - - if (point->Z_is_one || EC_POINT_is_at_infinity(group, point)) - return 1; - - 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 (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err; - if (!BN_copy(&point->X, x)) goto err; - if (!BN_copy(&point->Y, y)) goto err; - if (!BN_one(&point->Z)) goto err; - - ret = 1; - - err: - if (ctx) BN_CTX_end(ctx); - if (new_ctx) BN_CTX_free(new_ctx); - return ret; - } - - -/* Forces each of the EC_POINTs in the given array to use affine coordinates. */ -int ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx) - { - size_t i; - - for (i = 0; i < num; i++) - { - if (!group->meth->make_affine(group, points[i], ctx)) return 0; - } - - return 1; - } +int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point, + BN_CTX *ctx) +{ + BN_CTX *new_ctx = NULL; + BIGNUM *x, *y; + int ret = 0; + + if (point->Z_is_one || EC_POINT_is_at_infinity(group, point)) + return 1; + + 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 (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) + goto err; + if (!BN_copy(&point->X, x)) + goto err; + if (!BN_copy(&point->Y, y)) + goto err; + if (!BN_one(&point->Z)) + goto err; + + ret = 1; + err: + if (ctx) + BN_CTX_end(ctx); + if (new_ctx) + BN_CTX_free(new_ctx); + return ret; +} + +/* + * Forces each of the EC_POINTs in the given array to use affine coordinates. + */ +int ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num, + EC_POINT *points[], BN_CTX *ctx) +{ + size_t i; -/* Wrapper to simple binary polynomial field multiplication implementation. */ -int ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) - { - return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx); - } + for (i = 0; i < num; i++) { + if (!group->meth->make_affine(group, points[i], ctx)) + return 0; + } + return 1; +} -/* Wrapper to simple binary polynomial field squaring implementation. */ -int ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) - { - return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx); - } +/* Wrapper to simple binary polynomial field multiplication implementation. */ +int ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r, + const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) +{ + return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx); +} +/* Wrapper to simple binary polynomial field squaring implementation. */ +int ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, + const BIGNUM *a, BN_CTX *ctx) +{ + return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx); +} /* Wrapper to simple binary polynomial field division implementation. */ -int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) - { - return BN_GF2m_mod_div(r, a, b, &group->field, ctx); - } +int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, + const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) +{ + return BN_GF2m_mod_div(r, a, b, &group->field, ctx); +} #endif diff --git a/openssl/crypto/ec/ec_ameth.c b/openssl/crypto/ec/ec_ameth.c index 11283769b..5cefb5ad3 100644 --- a/openssl/crypto/ec/ec_ameth.c +++ b/openssl/crypto/ec/ec_ameth.c @@ -1,5 +1,6 @@ -/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL - * project 2006. +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2006. */ /* ==================================================================== * Copyright (c) 2006 The OpenSSL Project. All rights reserved. @@ -9,7 +10,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -61,603 +62,566 @@ #include <openssl/ec.h> #include <openssl/bn.h> #ifndef OPENSSL_NO_CMS -#include <openssl/cms.h> +# include <openssl/cms.h> #endif #include "asn1_locl.h" static int eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key) - { - const EC_GROUP *group; - int nid; - if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) - { - ECerr(EC_F_ECKEY_PARAM2TYPE, EC_R_MISSING_PARAMETERS); - return 0; - } - if (EC_GROUP_get_asn1_flag(group) - && (nid = EC_GROUP_get_curve_name(group))) - /* we have a 'named curve' => just set the OID */ - { - *ppval = OBJ_nid2obj(nid); - *pptype = V_ASN1_OBJECT; - } - else /* explicit parameters */ - { - ASN1_STRING *pstr = NULL; - pstr = ASN1_STRING_new(); - if (!pstr) - return 0; - pstr->length = i2d_ECParameters(ec_key, &pstr->data); - if (pstr->length <= 0) - { - ASN1_STRING_free(pstr); - ECerr(EC_F_ECKEY_PARAM2TYPE, ERR_R_EC_LIB); - return 0; - } - *ppval = pstr; - *pptype = V_ASN1_SEQUENCE; - } - return 1; - } +{ + const EC_GROUP *group; + int nid; + if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) { + ECerr(EC_F_ECKEY_PARAM2TYPE, EC_R_MISSING_PARAMETERS); + return 0; + } + if (EC_GROUP_get_asn1_flag(group) + && (nid = EC_GROUP_get_curve_name(group))) + /* we have a 'named curve' => just set the OID */ + { + *ppval = OBJ_nid2obj(nid); + *pptype = V_ASN1_OBJECT; + } else { /* explicit parameters */ + + ASN1_STRING *pstr = NULL; + pstr = ASN1_STRING_new(); + if (!pstr) + return 0; + pstr->length = i2d_ECParameters(ec_key, &pstr->data); + if (pstr->length <= 0) { + ASN1_STRING_free(pstr); + ECerr(EC_F_ECKEY_PARAM2TYPE, ERR_R_EC_LIB); + return 0; + } + *ppval = pstr; + *pptype = V_ASN1_SEQUENCE; + } + return 1; +} static int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) - { - EC_KEY *ec_key = pkey->pkey.ec; - void *pval = NULL; - int ptype; - unsigned char *penc = NULL, *p; - int penclen; - - if (!eckey_param2type(&ptype, &pval, ec_key)) - { - ECerr(EC_F_ECKEY_PUB_ENCODE, ERR_R_EC_LIB); - return 0; - } - penclen = i2o_ECPublicKey(ec_key, NULL); - if (penclen <= 0) - goto err; - penc = OPENSSL_malloc(penclen); - if (!penc) - goto err; - p = penc; - penclen = i2o_ECPublicKey(ec_key, &p); - if (penclen <= 0) - goto err; - if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_EC), - ptype, pval, penc, penclen)) - return 1; - err: - if (ptype == V_ASN1_OBJECT) - ASN1_OBJECT_free(pval); - else - ASN1_STRING_free(pval); - if (penc) - OPENSSL_free(penc); - return 0; - } +{ + EC_KEY *ec_key = pkey->pkey.ec; + void *pval = NULL; + int ptype; + unsigned char *penc = NULL, *p; + int penclen; + + if (!eckey_param2type(&ptype, &pval, ec_key)) { + ECerr(EC_F_ECKEY_PUB_ENCODE, ERR_R_EC_LIB); + return 0; + } + penclen = i2o_ECPublicKey(ec_key, NULL); + if (penclen <= 0) + goto err; + penc = OPENSSL_malloc(penclen); + if (!penc) + goto err; + p = penc; + penclen = i2o_ECPublicKey(ec_key, &p); + if (penclen <= 0) + goto err; + if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_EC), + ptype, pval, penc, penclen)) + return 1; + err: + if (ptype == V_ASN1_OBJECT) + ASN1_OBJECT_free(pval); + else + ASN1_STRING_free(pval); + if (penc) + OPENSSL_free(penc); + return 0; +} static EC_KEY *eckey_type2param(int ptype, void *pval) - { - EC_KEY *eckey = NULL; - if (ptype == V_ASN1_SEQUENCE) - { - ASN1_STRING *pstr = pval; - const unsigned char *pm = NULL; - int pmlen; - pm = pstr->data; - pmlen = pstr->length; - if (!(eckey = d2i_ECParameters(NULL, &pm, pmlen))) - { - ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR); - goto ecerr; - } - } - else if (ptype == V_ASN1_OBJECT) - { - ASN1_OBJECT *poid = pval; - EC_GROUP *group; - - /* type == V_ASN1_OBJECT => the parameters are given - * by an asn1 OID - */ - if ((eckey = EC_KEY_new()) == NULL) - { - ECerr(EC_F_ECKEY_TYPE2PARAM, ERR_R_MALLOC_FAILURE); - goto ecerr; - } - group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(poid)); - if (group == NULL) - goto ecerr; - EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); - if (EC_KEY_set_group(eckey, group) == 0) - goto ecerr; - EC_GROUP_free(group); - } - else - { - ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR); - goto ecerr; - } - - return eckey; - - ecerr: - if (eckey) - EC_KEY_free(eckey); - return NULL; - } +{ + EC_KEY *eckey = NULL; + if (ptype == V_ASN1_SEQUENCE) { + ASN1_STRING *pstr = pval; + const unsigned char *pm = NULL; + int pmlen; + pm = pstr->data; + pmlen = pstr->length; + if (!(eckey = d2i_ECParameters(NULL, &pm, pmlen))) { + ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR); + goto ecerr; + } + } else if (ptype == V_ASN1_OBJECT) { + ASN1_OBJECT *poid = pval; + EC_GROUP *group; + + /* + * type == V_ASN1_OBJECT => the parameters are given by an asn1 OID + */ + if ((eckey = EC_KEY_new()) == NULL) { + ECerr(EC_F_ECKEY_TYPE2PARAM, ERR_R_MALLOC_FAILURE); + goto ecerr; + } + group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(poid)); + if (group == NULL) + goto ecerr; + EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); + if (EC_KEY_set_group(eckey, group) == 0) + goto ecerr; + EC_GROUP_free(group); + } else { + ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR); + goto ecerr; + } + + return eckey; + + ecerr: + if (eckey) + EC_KEY_free(eckey); + return NULL; +} static int eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) - { - const unsigned char *p = NULL; - void *pval; - int ptype, pklen; - EC_KEY *eckey = NULL; - X509_ALGOR *palg; - - if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) - return 0; - X509_ALGOR_get0(NULL, &ptype, &pval, palg); - - eckey = eckey_type2param(ptype, pval); - - if (!eckey) - { - ECerr(EC_F_ECKEY_PUB_DECODE, ERR_R_EC_LIB); - return 0; - } - - /* We have parameters now set public key */ - if (!o2i_ECPublicKey(&eckey, &p, pklen)) - { - ECerr(EC_F_ECKEY_PUB_DECODE, EC_R_DECODE_ERROR); - goto ecerr; - } - - EVP_PKEY_assign_EC_KEY(pkey, eckey); - return 1; - - ecerr: - if (eckey) - EC_KEY_free(eckey); - return 0; - } +{ + const unsigned char *p = NULL; + void *pval; + int ptype, pklen; + EC_KEY *eckey = NULL; + X509_ALGOR *palg; + + if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) + return 0; + X509_ALGOR_get0(NULL, &ptype, &pval, palg); + + eckey = eckey_type2param(ptype, pval); + + if (!eckey) { + ECerr(EC_F_ECKEY_PUB_DECODE, ERR_R_EC_LIB); + return 0; + } + + /* We have parameters now set public key */ + if (!o2i_ECPublicKey(&eckey, &p, pklen)) { + ECerr(EC_F_ECKEY_PUB_DECODE, EC_R_DECODE_ERROR); + goto ecerr; + } + + EVP_PKEY_assign_EC_KEY(pkey, eckey); + return 1; + + ecerr: + if (eckey) + EC_KEY_free(eckey); + return 0; +} static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) - { - int r; - const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec); - const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec), - *pb = EC_KEY_get0_public_key(b->pkey.ec); - r = EC_POINT_cmp(group, pa, pb, NULL); - if (r == 0) - return 1; - if (r == 1) - return 0; - return -2; - } +{ + int r; + const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec); + const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec), + *pb = EC_KEY_get0_public_key(b->pkey.ec); + r = EC_POINT_cmp(group, pa, pb, NULL); + if (r == 0) + return 1; + if (r == 1) + return 0; + return -2; +} static int eckey_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) - { - const unsigned char *p = NULL; - void *pval; - int ptype, pklen; - EC_KEY *eckey = NULL; - X509_ALGOR *palg; - - if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8)) - return 0; - X509_ALGOR_get0(NULL, &ptype, &pval, palg); - - eckey = eckey_type2param(ptype, pval); - - if (!eckey) - goto ecliberr; - - /* We have parameters now set private key */ - if (!d2i_ECPrivateKey(&eckey, &p, pklen)) - { - ECerr(EC_F_ECKEY_PRIV_DECODE, EC_R_DECODE_ERROR); - goto ecerr; - } - - /* calculate public key (if necessary) */ - if (EC_KEY_get0_public_key(eckey) == NULL) - { - const BIGNUM *priv_key; - const EC_GROUP *group; - EC_POINT *pub_key; - /* the public key was not included in the SEC1 private - * key => calculate the public key */ - group = EC_KEY_get0_group(eckey); - pub_key = EC_POINT_new(group); - if (pub_key == NULL) - { - ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); - goto ecliberr; - } - if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) - { - EC_POINT_free(pub_key); - ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); - goto ecliberr; - } - priv_key = EC_KEY_get0_private_key(eckey); - if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL)) - { - EC_POINT_free(pub_key); - ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); - goto ecliberr; - } - if (EC_KEY_set_public_key(eckey, pub_key) == 0) - { - EC_POINT_free(pub_key); - ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); - goto ecliberr; - } - EC_POINT_free(pub_key); - } - - EVP_PKEY_assign_EC_KEY(pkey, eckey); - return 1; - - ecliberr: - ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); - ecerr: - if (eckey) - EC_KEY_free(eckey); - return 0; - } +{ + const unsigned char *p = NULL; + void *pval; + int ptype, pklen; + EC_KEY *eckey = NULL; + X509_ALGOR *palg; + + if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8)) + return 0; + X509_ALGOR_get0(NULL, &ptype, &pval, palg); + + eckey = eckey_type2param(ptype, pval); + + if (!eckey) + goto ecliberr; + + /* We have parameters now set private key */ + if (!d2i_ECPrivateKey(&eckey, &p, pklen)) { + ECerr(EC_F_ECKEY_PRIV_DECODE, EC_R_DECODE_ERROR); + goto ecerr; + } + + /* calculate public key (if necessary) */ + if (EC_KEY_get0_public_key(eckey) == NULL) { + const BIGNUM *priv_key; + const EC_GROUP *group; + EC_POINT *pub_key; + /* + * the public key was not included in the SEC1 private key => + * calculate the public key + */ + group = EC_KEY_get0_group(eckey); + pub_key = EC_POINT_new(group); + if (pub_key == NULL) { + ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); + goto ecliberr; + } + if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) { + EC_POINT_free(pub_key); + ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); + goto ecliberr; + } + priv_key = EC_KEY_get0_private_key(eckey); + if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL)) { + EC_POINT_free(pub_key); + ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); + goto ecliberr; + } + if (EC_KEY_set_public_key(eckey, pub_key) == 0) { + EC_POINT_free(pub_key); + ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); + goto ecliberr; + } + EC_POINT_free(pub_key); + } + + EVP_PKEY_assign_EC_KEY(pkey, eckey); + return 1; + + ecliberr: + ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB); + ecerr: + if (eckey) + EC_KEY_free(eckey); + return 0; +} static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) { - EC_KEY *ec_key; - unsigned char *ep, *p; - int eplen, ptype; - void *pval; - unsigned int tmp_flags, old_flags; - - ec_key = pkey->pkey.ec; - - if (!eckey_param2type(&ptype, &pval, ec_key)) - { - ECerr(EC_F_ECKEY_PRIV_ENCODE, EC_R_DECODE_ERROR); - return 0; - } - - /* set the private key */ - - /* do not include the parameters in the SEC1 private key - * see PKCS#11 12.11 */ - old_flags = EC_KEY_get_enc_flags(ec_key); - tmp_flags = old_flags | EC_PKEY_NO_PARAMETERS; - EC_KEY_set_enc_flags(ec_key, tmp_flags); - eplen = i2d_ECPrivateKey(ec_key, NULL); - if (!eplen) - { - EC_KEY_set_enc_flags(ec_key, old_flags); - ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB); - return 0; - } - ep = (unsigned char *) OPENSSL_malloc(eplen); - if (!ep) - { - EC_KEY_set_enc_flags(ec_key, old_flags); - ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_MALLOC_FAILURE); - return 0; - } - p = ep; - if (!i2d_ECPrivateKey(ec_key, &p)) - { - EC_KEY_set_enc_flags(ec_key, old_flags); - OPENSSL_free(ep); - ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB); - return 0; - } - /* restore old encoding flags */ - EC_KEY_set_enc_flags(ec_key, old_flags); - - if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0, - ptype, pval, ep, eplen)) - return 0; - - return 1; + EC_KEY *ec_key; + unsigned char *ep, *p; + int eplen, ptype; + void *pval; + unsigned int tmp_flags, old_flags; + + ec_key = pkey->pkey.ec; + + if (!eckey_param2type(&ptype, &pval, ec_key)) { + ECerr(EC_F_ECKEY_PRIV_ENCODE, EC_R_DECODE_ERROR); + return 0; + } + + /* set the private key */ + + /* + * do not include the parameters in the SEC1 private key see PKCS#11 + * 12.11 + */ + old_flags = EC_KEY_get_enc_flags(ec_key); + tmp_flags = old_flags | EC_PKEY_NO_PARAMETERS; + EC_KEY_set_enc_flags(ec_key, tmp_flags); + eplen = i2d_ECPrivateKey(ec_key, NULL); + if (!eplen) { + EC_KEY_set_enc_flags(ec_key, old_flags); + ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB); + return 0; + } + ep = (unsigned char *)OPENSSL_malloc(eplen); + if (!ep) { + EC_KEY_set_enc_flags(ec_key, old_flags); + ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_MALLOC_FAILURE); + return 0; + } + p = ep; + if (!i2d_ECPrivateKey(ec_key, &p)) { + EC_KEY_set_enc_flags(ec_key, old_flags); + OPENSSL_free(ep); + ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB); + return 0; + } + /* restore old encoding flags */ + EC_KEY_set_enc_flags(ec_key, old_flags); + + if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0, + ptype, pval, ep, eplen)) + return 0; + + return 1; } static int int_ec_size(const EVP_PKEY *pkey) - { - return ECDSA_size(pkey->pkey.ec); - } +{ + return ECDSA_size(pkey->pkey.ec); +} static int ec_bits(const EVP_PKEY *pkey) - { - BIGNUM *order = BN_new(); - const EC_GROUP *group; - int ret; - - if (!order) - { - ERR_clear_error(); - return 0; - } - group = EC_KEY_get0_group(pkey->pkey.ec); - if (!EC_GROUP_get_order(group, order, NULL)) - { - ERR_clear_error(); - return 0; - } - - ret = BN_num_bits(order); - BN_free(order); - return ret; - } +{ + BIGNUM *order = BN_new(); + const EC_GROUP *group; + int ret; + + if (!order) { + ERR_clear_error(); + return 0; + } + group = EC_KEY_get0_group(pkey->pkey.ec); + if (!EC_GROUP_get_order(group, order, NULL)) { + ERR_clear_error(); + return 0; + } + + ret = BN_num_bits(order); + BN_free(order); + return ret; +} static int ec_missing_parameters(const EVP_PKEY *pkey) - { - if (EC_KEY_get0_group(pkey->pkey.ec) == NULL) - return 1; - return 0; - } +{ + if (EC_KEY_get0_group(pkey->pkey.ec) == NULL) + return 1; + return 0; +} static int ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) - { - EC_GROUP *group = EC_GROUP_dup(EC_KEY_get0_group(from->pkey.ec)); - if (group == NULL) - return 0; - if (EC_KEY_set_group(to->pkey.ec, group) == 0) - return 0; - EC_GROUP_free(group); - return 1; - } +{ + EC_GROUP *group = EC_GROUP_dup(EC_KEY_get0_group(from->pkey.ec)); + if (group == NULL) + return 0; + if (EC_KEY_set_group(to->pkey.ec, group) == 0) + return 0; + EC_GROUP_free(group); + return 1; +} static int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) - { - const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec), - *group_b = EC_KEY_get0_group(b->pkey.ec); - if (EC_GROUP_cmp(group_a, group_b, NULL)) - return 0; - else - return 1; - } +{ + const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec), + *group_b = EC_KEY_get0_group(b->pkey.ec); + if (EC_GROUP_cmp(group_a, group_b, NULL)) + return 0; + else + return 1; +} static void int_ec_free(EVP_PKEY *pkey) - { - EC_KEY_free(pkey->pkey.ec); - } +{ + EC_KEY_free(pkey->pkey.ec); +} static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) - { - unsigned char *buffer=NULL; - const char *ecstr; - size_t buf_len=0, i; - int ret=0, reason=ERR_R_BIO_LIB; - BIGNUM *pub_key=NULL, *order=NULL; - BN_CTX *ctx=NULL; - const EC_GROUP *group; - const EC_POINT *public_key; - const BIGNUM *priv_key; - - if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) - { - reason = ERR_R_PASSED_NULL_PARAMETER; - goto err; - } - - ctx = BN_CTX_new(); - if (ctx == NULL) - { - reason = ERR_R_MALLOC_FAILURE; - goto err; - } - - if (ktype > 0) - { - public_key = EC_KEY_get0_public_key(x); - if (public_key != NULL) - { - if ((pub_key = EC_POINT_point2bn(group, public_key, - EC_KEY_get_conv_form(x), NULL, ctx)) == NULL) - { - reason = ERR_R_EC_LIB; - goto err; - } - buf_len = (size_t)BN_num_bytes(pub_key); - } - } - - if (ktype == 2) - { - priv_key = EC_KEY_get0_private_key(x); - if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len) - buf_len = i; - } - else - priv_key = NULL; - - if (ktype > 0) - { - buf_len += 10; - if ((buffer = OPENSSL_malloc(buf_len)) == NULL) - { - reason = ERR_R_MALLOC_FAILURE; - goto err; - } - } - if (ktype == 2) - ecstr = "Private-Key"; - else if (ktype == 1) - ecstr = "Public-Key"; - else - ecstr = "ECDSA-Parameters"; - - if (!BIO_indent(bp, off, 128)) - goto err; - if ((order = BN_new()) == NULL) - goto err; - if (!EC_GROUP_get_order(group, order, NULL)) - goto err; - if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, - BN_num_bits(order)) <= 0) goto err; - - if ((priv_key != NULL) && !ASN1_bn_print(bp, "priv:", priv_key, - buffer, off)) - goto err; - if ((pub_key != NULL) && !ASN1_bn_print(bp, "pub: ", pub_key, - buffer, off)) - goto err; - if (!ECPKParameters_print(bp, group, off)) - goto err; - ret=1; -err: - if (!ret) - ECerr(EC_F_DO_EC_KEY_PRINT, reason); - if (pub_key) - BN_free(pub_key); - if (order) - BN_free(order); - if (ctx) - BN_CTX_free(ctx); - if (buffer != NULL) - OPENSSL_free(buffer); - return(ret); - } +{ + unsigned char *buffer = NULL; + const char *ecstr; + size_t buf_len = 0, i; + int ret = 0, reason = ERR_R_BIO_LIB; + BIGNUM *pub_key = NULL, *order = NULL; + BN_CTX *ctx = NULL; + const EC_GROUP *group; + const EC_POINT *public_key; + const BIGNUM *priv_key; + + if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) { + reason = ERR_R_PASSED_NULL_PARAMETER; + goto err; + } + + ctx = BN_CTX_new(); + if (ctx == NULL) { + reason = ERR_R_MALLOC_FAILURE; + goto err; + } + + if (ktype > 0) { + public_key = EC_KEY_get0_public_key(x); + if (public_key != NULL) { + if ((pub_key = EC_POINT_point2bn(group, public_key, + EC_KEY_get_conv_form(x), NULL, + ctx)) == NULL) { + reason = ERR_R_EC_LIB; + goto err; + } + buf_len = (size_t)BN_num_bytes(pub_key); + } + } + + if (ktype == 2) { + priv_key = EC_KEY_get0_private_key(x); + if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len) + buf_len = i; + } else + priv_key = NULL; + + if (ktype > 0) { + buf_len += 10; + if ((buffer = OPENSSL_malloc(buf_len)) == NULL) { + reason = ERR_R_MALLOC_FAILURE; + goto err; + } + } + if (ktype == 2) + ecstr = "Private-Key"; + else if (ktype == 1) + ecstr = "Public-Key"; + else + ecstr = "ECDSA-Parameters"; + + if (!BIO_indent(bp, off, 128)) + goto err; + if ((order = BN_new()) == NULL) + goto err; + if (!EC_GROUP_get_order(group, order, NULL)) + goto err; + if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0) + goto err; + + if ((priv_key != NULL) && !ASN1_bn_print(bp, "priv:", priv_key, + buffer, off)) + goto err; + if ((pub_key != NULL) && !ASN1_bn_print(bp, "pub: ", pub_key, + buffer, off)) + goto err; + if (!ECPKParameters_print(bp, group, off)) + goto err; + ret = 1; + err: + if (!ret) + ECerr(EC_F_DO_EC_KEY_PRINT, reason); + if (pub_key) + BN_free(pub_key); + if (order) + BN_free(order); + if (ctx) + BN_CTX_free(ctx); + if (buffer != NULL) + OPENSSL_free(buffer); + return (ret); +} static int eckey_param_decode(EVP_PKEY *pkey, - const unsigned char **pder, int derlen) - { - EC_KEY *eckey; - if (!(eckey = d2i_ECParameters(NULL, pder, derlen))) - { - ECerr(EC_F_ECKEY_PARAM_DECODE, ERR_R_EC_LIB); - return 0; - } - EVP_PKEY_assign_EC_KEY(pkey, eckey); - return 1; - } + const unsigned char **pder, int derlen) +{ + EC_KEY *eckey; + if (!(eckey = d2i_ECParameters(NULL, pder, derlen))) { + ECerr(EC_F_ECKEY_PARAM_DECODE, ERR_R_EC_LIB); + return 0; + } + EVP_PKEY_assign_EC_KEY(pkey, eckey); + return 1; +} static int eckey_param_encode(const EVP_PKEY *pkey, unsigned char **pder) - { - return i2d_ECParameters(pkey->pkey.ec, pder); - } +{ + return i2d_ECParameters(pkey->pkey.ec, pder); +} static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, - ASN1_PCTX *ctx) - { - return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0); - } + ASN1_PCTX *ctx) +{ + return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0); +} static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, - ASN1_PCTX *ctx) - { - return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1); - } - + ASN1_PCTX *ctx) +{ + return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1); +} static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, - ASN1_PCTX *ctx) - { - return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2); - } + ASN1_PCTX *ctx) +{ + return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2); +} static int old_ec_priv_decode(EVP_PKEY *pkey, - const unsigned char **pder, int derlen) - { - EC_KEY *ec; - if (!(ec = d2i_ECPrivateKey (NULL, pder, derlen))) - { - ECerr(EC_F_OLD_EC_PRIV_DECODE, EC_R_DECODE_ERROR); - return 0; - } - EVP_PKEY_assign_EC_KEY(pkey, ec); - return 1; - } + const unsigned char **pder, int derlen) +{ + EC_KEY *ec; + if (!(ec = d2i_ECPrivateKey(NULL, pder, derlen))) { + ECerr(EC_F_OLD_EC_PRIV_DECODE, EC_R_DECODE_ERROR); + return 0; + } + EVP_PKEY_assign_EC_KEY(pkey, ec); + return 1; +} static int old_ec_priv_encode(const EVP_PKEY *pkey, unsigned char **pder) - { - return i2d_ECPrivateKey(pkey->pkey.ec, pder); - } +{ + return i2d_ECPrivateKey(pkey->pkey.ec, pder); +} static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) - { - switch (op) - { - case ASN1_PKEY_CTRL_PKCS7_SIGN: - if (arg1 == 0) - { - int snid, hnid; - X509_ALGOR *alg1, *alg2; - PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2); - if (alg1 == NULL || alg1->algorithm == NULL) - return -1; - hnid = OBJ_obj2nid(alg1->algorithm); - if (hnid == NID_undef) - return -1; - if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey))) - return -1; - X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0); - } - return 1; +{ + switch (op) { + case ASN1_PKEY_CTRL_PKCS7_SIGN: + if (arg1 == 0) { + int snid, hnid; + X509_ALGOR *alg1, *alg2; + PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2); + if (alg1 == NULL || alg1->algorithm == NULL) + return -1; + hnid = OBJ_obj2nid(alg1->algorithm); + if (hnid == NID_undef) + return -1; + if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey))) + return -1; + X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0); + } + return 1; #ifndef OPENSSL_NO_CMS - case ASN1_PKEY_CTRL_CMS_SIGN: - if (arg1 == 0) - { - int snid, hnid; - X509_ALGOR *alg1, *alg2; - CMS_SignerInfo_get0_algs(arg2, NULL, NULL, - &alg1, &alg2); - if (alg1 == NULL || alg1->algorithm == NULL) - return -1; - hnid = OBJ_obj2nid(alg1->algorithm); - if (hnid == NID_undef) - return -1; - if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey))) - return -1; - X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0); - } - return 1; + case ASN1_PKEY_CTRL_CMS_SIGN: + if (arg1 == 0) { + int snid, hnid; + X509_ALGOR *alg1, *alg2; + CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2); + if (alg1 == NULL || alg1->algorithm == NULL) + return -1; + hnid = OBJ_obj2nid(alg1->algorithm); + if (hnid == NID_undef) + return -1; + if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey))) + return -1; + X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0); + } + return 1; #endif - case ASN1_PKEY_CTRL_DEFAULT_MD_NID: - *(int *)arg2 = NID_sha1; - return 2; - - default: - return -2; - - } - - } - -const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = - { - EVP_PKEY_EC, - EVP_PKEY_EC, - 0, - "EC", - "OpenSSL EC algorithm", - - eckey_pub_decode, - eckey_pub_encode, - eckey_pub_cmp, - eckey_pub_print, - - eckey_priv_decode, - eckey_priv_encode, - eckey_priv_print, - - int_ec_size, - ec_bits, - - eckey_param_decode, - eckey_param_encode, - ec_missing_parameters, - ec_copy_parameters, - ec_cmp_parameters, - eckey_param_print, - 0, - - int_ec_free, - ec_pkey_ctrl, - old_ec_priv_decode, - old_ec_priv_encode - }; + case ASN1_PKEY_CTRL_DEFAULT_MD_NID: + *(int *)arg2 = NID_sha1; + return 2; + + default: + return -2; + + } + +} + +const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = { + EVP_PKEY_EC, + EVP_PKEY_EC, + 0, + "EC", + "OpenSSL EC algorithm", + + eckey_pub_decode, + eckey_pub_encode, + eckey_pub_cmp, + eckey_pub_print, + + eckey_priv_decode, + eckey_priv_encode, + eckey_priv_print, + + int_ec_size, + ec_bits, + + eckey_param_decode, + eckey_param_encode, + ec_missing_parameters, + ec_copy_parameters, + ec_cmp_parameters, + eckey_param_print, + 0, + + int_ec_free, + ec_pkey_ctrl, + old_ec_priv_decode, + old_ec_priv_encode +}; diff --git a/openssl/crypto/ec/ec_asn1.c b/openssl/crypto/ec/ec_asn1.c index 52d31c2f9..b4b0e9f3b 100644 --- a/openssl/crypto/ec/ec_asn1.c +++ b/openssl/crypto/ec/ec_asn1.c @@ -10,7 +10,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -62,145 +62,148 @@ #include <openssl/asn1t.h> #include <openssl/objects.h> - int EC_GROUP_get_basis_type(const EC_GROUP *group) - { - int i=0; - - if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != - NID_X9_62_characteristic_two_field) - /* everything else is currently not supported */ - return 0; - - while (group->poly[i] != 0) - i++; - - if (i == 4) - return NID_X9_62_ppBasis; - else if (i == 2) - return NID_X9_62_tpBasis; - else - /* everything else is currently not supported */ - return 0; - } +{ + int i = 0; + + if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != + NID_X9_62_characteristic_two_field) + /* everything else is currently not supported */ + return 0; + + while (group->poly[i] != 0) + i++; + + if (i == 4) + return NID_X9_62_ppBasis; + else if (i == 2) + return NID_X9_62_tpBasis; + else + /* everything else is currently not supported */ + return 0; +} + #ifndef OPENSSL_NO_EC2M int EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k) - { - if (group == NULL) - return 0; - - if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != - NID_X9_62_characteristic_two_field - || !((group->poly[0] != 0) && (group->poly[1] != 0) && (group->poly[2] == 0))) - { - ECerr(EC_F_EC_GROUP_GET_TRINOMIAL_BASIS, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } - - if (k) - *k = group->poly[1]; - - return 1; - } +{ + if (group == NULL) + return 0; + + if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != + NID_X9_62_characteristic_two_field + || !((group->poly[0] != 0) && (group->poly[1] != 0) + && (group->poly[2] == 0))) { + ECerr(EC_F_EC_GROUP_GET_TRINOMIAL_BASIS, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + if (k) + *k = group->poly[1]; + + return 1; +} + int EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1, - unsigned int *k2, unsigned int *k3) - { - if (group == NULL) - return 0; - - if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != - NID_X9_62_characteristic_two_field - || !((group->poly[0] != 0) && (group->poly[1] != 0) && (group->poly[2] != 0) && (group->poly[3] != 0) && (group->poly[4] == 0))) - { - ECerr(EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } - - if (k1) - *k1 = group->poly[3]; - if (k2) - *k2 = group->poly[2]; - if (k3) - *k3 = group->poly[1]; - - return 1; - } + unsigned int *k2, unsigned int *k3) +{ + if (group == NULL) + return 0; + + if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != + NID_X9_62_characteristic_two_field + || !((group->poly[0] != 0) && (group->poly[1] != 0) + && (group->poly[2] != 0) && (group->poly[3] != 0) + && (group->poly[4] == 0))) { + ECerr(EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + if (k1) + *k1 = group->poly[3]; + if (k2) + *k2 = group->poly[2]; + if (k3) + *k3 = group->poly[1]; + + return 1; +} #endif - /* some structures needed for the asn1 encoding */ typedef struct x9_62_pentanomial_st { - long k1; - long k2; - long k3; - } X9_62_PENTANOMIAL; + long k1; + long k2; + long k3; +} X9_62_PENTANOMIAL; typedef struct x9_62_characteristic_two_st { - long m; - ASN1_OBJECT *type; - union { - char *ptr; - /* NID_X9_62_onBasis */ - ASN1_NULL *onBasis; - /* NID_X9_62_tpBasis */ - ASN1_INTEGER *tpBasis; - /* NID_X9_62_ppBasis */ - X9_62_PENTANOMIAL *ppBasis; - /* anything else */ - ASN1_TYPE *other; - } p; - } X9_62_CHARACTERISTIC_TWO; + long m; + ASN1_OBJECT *type; + union { + char *ptr; + /* NID_X9_62_onBasis */ + ASN1_NULL *onBasis; + /* NID_X9_62_tpBasis */ + ASN1_INTEGER *tpBasis; + /* NID_X9_62_ppBasis */ + X9_62_PENTANOMIAL *ppBasis; + /* anything else */ + ASN1_TYPE *other; + } p; +} X9_62_CHARACTERISTIC_TWO; typedef struct x9_62_fieldid_st { - ASN1_OBJECT *fieldType; - union { - char *ptr; - /* NID_X9_62_prime_field */ - ASN1_INTEGER *prime; - /* NID_X9_62_characteristic_two_field */ - X9_62_CHARACTERISTIC_TWO *char_two; - /* anything else */ - ASN1_TYPE *other; - } p; - } X9_62_FIELDID; + ASN1_OBJECT *fieldType; + union { + char *ptr; + /* NID_X9_62_prime_field */ + ASN1_INTEGER *prime; + /* NID_X9_62_characteristic_two_field */ + X9_62_CHARACTERISTIC_TWO *char_two; + /* anything else */ + ASN1_TYPE *other; + } p; +} X9_62_FIELDID; typedef struct x9_62_curve_st { - ASN1_OCTET_STRING *a; - ASN1_OCTET_STRING *b; - ASN1_BIT_STRING *seed; - } X9_62_CURVE; + ASN1_OCTET_STRING *a; + ASN1_OCTET_STRING *b; + ASN1_BIT_STRING *seed; +} X9_62_CURVE; typedef struct ec_parameters_st { - long version; - X9_62_FIELDID *fieldID; - X9_62_CURVE *curve; - ASN1_OCTET_STRING *base; - ASN1_INTEGER *order; - ASN1_INTEGER *cofactor; - } ECPARAMETERS; + long version; + X9_62_FIELDID *fieldID; + X9_62_CURVE *curve; + ASN1_OCTET_STRING *base; + ASN1_INTEGER *order; + ASN1_INTEGER *cofactor; +} ECPARAMETERS; struct ecpk_parameters_st { - int type; - union { - ASN1_OBJECT *named_curve; - ECPARAMETERS *parameters; - ASN1_NULL *implicitlyCA; - } value; - }/* ECPKPARAMETERS */; + int type; + union { + ASN1_OBJECT *named_curve; + ECPARAMETERS *parameters; + ASN1_NULL *implicitlyCA; + } value; +} /* ECPKPARAMETERS */ ; /* SEC1 ECPrivateKey */ typedef struct ec_privatekey_st { - long version; - ASN1_OCTET_STRING *privateKey; - ECPKPARAMETERS *parameters; - ASN1_BIT_STRING *publicKey; - } EC_PRIVATEKEY; + long version; + ASN1_OCTET_STRING *privateKey; + ECPKPARAMETERS *parameters; + ASN1_BIT_STRING *publicKey; +} EC_PRIVATEKEY; /* the OpenSSL ASN.1 definitions */ ASN1_SEQUENCE(X9_62_PENTANOMIAL) = { - ASN1_SIMPLE(X9_62_PENTANOMIAL, k1, LONG), - ASN1_SIMPLE(X9_62_PENTANOMIAL, k2, LONG), - ASN1_SIMPLE(X9_62_PENTANOMIAL, k3, LONG) + ASN1_SIMPLE(X9_62_PENTANOMIAL, k1, LONG), + ASN1_SIMPLE(X9_62_PENTANOMIAL, k2, LONG), + ASN1_SIMPLE(X9_62_PENTANOMIAL, k3, LONG) } ASN1_SEQUENCE_END(X9_62_PENTANOMIAL) DECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL) @@ -209,15 +212,15 @@ IMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL) ASN1_ADB_TEMPLATE(char_two_def) = ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.other, ASN1_ANY); ASN1_ADB(X9_62_CHARACTERISTIC_TWO) = { - ADB_ENTRY(NID_X9_62_onBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.onBasis, ASN1_NULL)), - ADB_ENTRY(NID_X9_62_tpBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.tpBasis, ASN1_INTEGER)), - ADB_ENTRY(NID_X9_62_ppBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.ppBasis, X9_62_PENTANOMIAL)) + ADB_ENTRY(NID_X9_62_onBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.onBasis, ASN1_NULL)), + ADB_ENTRY(NID_X9_62_tpBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.tpBasis, ASN1_INTEGER)), + ADB_ENTRY(NID_X9_62_ppBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.ppBasis, X9_62_PENTANOMIAL)) } ASN1_ADB_END(X9_62_CHARACTERISTIC_TWO, 0, type, 0, &char_two_def_tt, NULL); ASN1_SEQUENCE(X9_62_CHARACTERISTIC_TWO) = { - ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, m, LONG), - ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, type, ASN1_OBJECT), - ASN1_ADB_OBJECT(X9_62_CHARACTERISTIC_TWO) + ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, m, LONG), + ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, type, ASN1_OBJECT), + ASN1_ADB_OBJECT(X9_62_CHARACTERISTIC_TWO) } ASN1_SEQUENCE_END(X9_62_CHARACTERISTIC_TWO) DECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO) @@ -226,37 +229,37 @@ IMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO) ASN1_ADB_TEMPLATE(fieldID_def) = ASN1_SIMPLE(X9_62_FIELDID, p.other, ASN1_ANY); ASN1_ADB(X9_62_FIELDID) = { - ADB_ENTRY(NID_X9_62_prime_field, ASN1_SIMPLE(X9_62_FIELDID, p.prime, ASN1_INTEGER)), - ADB_ENTRY(NID_X9_62_characteristic_two_field, ASN1_SIMPLE(X9_62_FIELDID, p.char_two, X9_62_CHARACTERISTIC_TWO)) + ADB_ENTRY(NID_X9_62_prime_field, ASN1_SIMPLE(X9_62_FIELDID, p.prime, ASN1_INTEGER)), + ADB_ENTRY(NID_X9_62_characteristic_two_field, ASN1_SIMPLE(X9_62_FIELDID, p.char_two, X9_62_CHARACTERISTIC_TWO)) } ASN1_ADB_END(X9_62_FIELDID, 0, fieldType, 0, &fieldID_def_tt, NULL); ASN1_SEQUENCE(X9_62_FIELDID) = { - ASN1_SIMPLE(X9_62_FIELDID, fieldType, ASN1_OBJECT), - ASN1_ADB_OBJECT(X9_62_FIELDID) + ASN1_SIMPLE(X9_62_FIELDID, fieldType, ASN1_OBJECT), + ASN1_ADB_OBJECT(X9_62_FIELDID) } ASN1_SEQUENCE_END(X9_62_FIELDID) ASN1_SEQUENCE(X9_62_CURVE) = { - ASN1_SIMPLE(X9_62_CURVE, a, ASN1_OCTET_STRING), - ASN1_SIMPLE(X9_62_CURVE, b, ASN1_OCTET_STRING), - ASN1_OPT(X9_62_CURVE, seed, ASN1_BIT_STRING) + ASN1_SIMPLE(X9_62_CURVE, a, ASN1_OCTET_STRING), + ASN1_SIMPLE(X9_62_CURVE, b, ASN1_OCTET_STRING), + ASN1_OPT(X9_62_CURVE, seed, ASN1_BIT_STRING) } ASN1_SEQUENCE_END(X9_62_CURVE) ASN1_SEQUENCE(ECPARAMETERS) = { - ASN1_SIMPLE(ECPARAMETERS, version, LONG), - ASN1_SIMPLE(ECPARAMETERS, fieldID, X9_62_FIELDID), - ASN1_SIMPLE(ECPARAMETERS, curve, X9_62_CURVE), - ASN1_SIMPLE(ECPARAMETERS, base, ASN1_OCTET_STRING), - ASN1_SIMPLE(ECPARAMETERS, order, ASN1_INTEGER), - ASN1_OPT(ECPARAMETERS, cofactor, ASN1_INTEGER) + ASN1_SIMPLE(ECPARAMETERS, version, LONG), + ASN1_SIMPLE(ECPARAMETERS, fieldID, X9_62_FIELDID), + ASN1_SIMPLE(ECPARAMETERS, curve, X9_62_CURVE), + ASN1_SIMPLE(ECPARAMETERS, base, ASN1_OCTET_STRING), + ASN1_SIMPLE(ECPARAMETERS, order, ASN1_INTEGER), + ASN1_OPT(ECPARAMETERS, cofactor, ASN1_INTEGER) } ASN1_SEQUENCE_END(ECPARAMETERS) DECLARE_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS) IMPLEMENT_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS) ASN1_CHOICE(ECPKPARAMETERS) = { - ASN1_SIMPLE(ECPKPARAMETERS, value.named_curve, ASN1_OBJECT), - ASN1_SIMPLE(ECPKPARAMETERS, value.parameters, ECPARAMETERS), - ASN1_SIMPLE(ECPKPARAMETERS, value.implicitlyCA, ASN1_NULL) + ASN1_SIMPLE(ECPKPARAMETERS, value.named_curve, ASN1_OBJECT), + ASN1_SIMPLE(ECPKPARAMETERS, value.parameters, ECPARAMETERS), + ASN1_SIMPLE(ECPKPARAMETERS, value.implicitlyCA, ASN1_NULL) } ASN1_CHOICE_END(ECPKPARAMETERS) DECLARE_ASN1_FUNCTIONS_const(ECPKPARAMETERS) @@ -264,10 +267,10 @@ DECLARE_ASN1_ENCODE_FUNCTIONS_const(ECPKPARAMETERS, ECPKPARAMETERS) IMPLEMENT_ASN1_FUNCTIONS_const(ECPKPARAMETERS) ASN1_SEQUENCE(EC_PRIVATEKEY) = { - ASN1_SIMPLE(EC_PRIVATEKEY, version, LONG), - ASN1_SIMPLE(EC_PRIVATEKEY, privateKey, ASN1_OCTET_STRING), - ASN1_EXP_OPT(EC_PRIVATEKEY, parameters, ECPKPARAMETERS, 0), - ASN1_EXP_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING, 1) + ASN1_SIMPLE(EC_PRIVATEKEY, version, LONG), + ASN1_SIMPLE(EC_PRIVATEKEY, privateKey, ASN1_OCTET_STRING), + ASN1_EXP_OPT(EC_PRIVATEKEY, parameters, ECPKPARAMETERS, 0), + ASN1_EXP_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING, 1) } ASN1_SEQUENCE_END(EC_PRIVATEKEY) DECLARE_ASN1_FUNCTIONS_const(EC_PRIVATEKEY) @@ -276,1191 +279,1030 @@ IMPLEMENT_ASN1_FUNCTIONS_const(EC_PRIVATEKEY) /* some declarations of internal function */ -/* ec_asn1_group2field() sets the values in a X9_62_FIELDID object */ +/* ec_asn1_group2field() sets the values in a X9_62_FIELDID object */ static int ec_asn1_group2fieldid(const EC_GROUP *, X9_62_FIELDID *); -/* ec_asn1_group2curve() sets the values in a X9_62_CURVE object */ +/* ec_asn1_group2curve() sets the values in a X9_62_CURVE object */ static int ec_asn1_group2curve(const EC_GROUP *, X9_62_CURVE *); -/* ec_asn1_parameters2group() creates a EC_GROUP object from a - * ECPARAMETERS object */ -static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *); -/* ec_asn1_group2parameters() creates a ECPARAMETERS object from a - * EC_GROUP object */ -static ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *,ECPARAMETERS *); -/* ec_asn1_pkparameters2group() creates a EC_GROUP object from a - * ECPKPARAMETERS object */ -static EC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *); -/* ec_asn1_group2pkparameters() creates a ECPKPARAMETERS object from a - * EC_GROUP object */ -static ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *, - ECPKPARAMETERS *); - +/* + * ec_asn1_parameters2group() creates a EC_GROUP object from a ECPARAMETERS + * object + */ +static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *); +/* + * ec_asn1_group2parameters() creates a ECPARAMETERS object from a EC_GROUP + * object + */ +static ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *, + ECPARAMETERS *); +/* + * ec_asn1_pkparameters2group() creates a EC_GROUP object from a + * ECPKPARAMETERS object + */ +static EC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *); +/* + * ec_asn1_group2pkparameters() creates a ECPKPARAMETERS object from a + * EC_GROUP object + */ +static ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *, + ECPKPARAMETERS *); /* the function definitions */ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field) - { - int ok=0, nid; - BIGNUM *tmp = NULL; - - if (group == NULL || field == NULL) - return 0; - - /* clear the old values (if necessary) */ - if (field->fieldType != NULL) - ASN1_OBJECT_free(field->fieldType); - if (field->p.other != NULL) - ASN1_TYPE_free(field->p.other); - - nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group)); - /* set OID for the field */ - if ((field->fieldType = OBJ_nid2obj(nid)) == NULL) - { - ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB); - goto err; - } - - if (nid == NID_X9_62_prime_field) - { - if ((tmp = BN_new()) == NULL) - { - ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); - goto err; - } - /* the parameters are specified by the prime number p */ - if (!EC_GROUP_get_curve_GFp(group, tmp, NULL, NULL, NULL)) - { - ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB); - goto err; - } - /* set the prime number */ - field->p.prime = BN_to_ASN1_INTEGER(tmp,NULL); - if (field->p.prime == NULL) - { - ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB); - goto err; - } - } - else /* nid == NID_X9_62_characteristic_two_field */ +{ + int ok = 0, nid; + BIGNUM *tmp = NULL; + + if (group == NULL || field == NULL) + return 0; + + /* clear the old values (if necessary) */ + if (field->fieldType != NULL) + ASN1_OBJECT_free(field->fieldType); + if (field->p.other != NULL) + ASN1_TYPE_free(field->p.other); + + nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group)); + /* set OID for the field */ + if ((field->fieldType = OBJ_nid2obj(nid)) == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB); + goto err; + } + + if (nid == NID_X9_62_prime_field) { + if ((tmp = BN_new()) == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); + goto err; + } + /* the parameters are specified by the prime number p */ + if (!EC_GROUP_get_curve_GFp(group, tmp, NULL, NULL, NULL)) { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB); + goto err; + } + /* set the prime number */ + field->p.prime = BN_to_ASN1_INTEGER(tmp, NULL); + if (field->p.prime == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB); + goto err; + } + } else /* nid == NID_X9_62_characteristic_two_field */ #ifdef OPENSSL_NO_EC2M - { - ECerr(EC_F_EC_ASN1_GROUP2FIELDID, EC_R_GF2M_NOT_SUPPORTED); - goto err; - } + { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, EC_R_GF2M_NOT_SUPPORTED); + goto err; + } #else - { - int field_type; - X9_62_CHARACTERISTIC_TWO *char_two; - - field->p.char_two = X9_62_CHARACTERISTIC_TWO_new(); - char_two = field->p.char_two; - - if (char_two == NULL) - { - ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); - goto err; - } - - char_two->m = (long)EC_GROUP_get_degree(group); - - field_type = EC_GROUP_get_basis_type(group); - - if (field_type == 0) - { - ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB); - goto err; - } - /* set base type OID */ - if ((char_two->type = OBJ_nid2obj(field_type)) == NULL) - { - ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB); - goto err; - } - - if (field_type == NID_X9_62_tpBasis) - { - unsigned int k; - - if (!EC_GROUP_get_trinomial_basis(group, &k)) - goto err; - - char_two->p.tpBasis = ASN1_INTEGER_new(); - if (!char_two->p.tpBasis) - { - ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); - goto err; - } - if (!ASN1_INTEGER_set(char_two->p.tpBasis, (long)k)) - { - ECerr(EC_F_EC_ASN1_GROUP2FIELDID, - ERR_R_ASN1_LIB); - goto err; - } - } - else if (field_type == NID_X9_62_ppBasis) - { - unsigned int k1, k2, k3; - - if (!EC_GROUP_get_pentanomial_basis(group, &k1, &k2, &k3)) - goto err; - - char_two->p.ppBasis = X9_62_PENTANOMIAL_new(); - if (!char_two->p.ppBasis) - { - ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); - goto err; - } - - /* set k? values */ - char_two->p.ppBasis->k1 = (long)k1; - char_two->p.ppBasis->k2 = (long)k2; - char_two->p.ppBasis->k3 = (long)k3; - } - else /* field_type == NID_X9_62_onBasis */ - { - /* for ONB the parameters are (asn1) NULL */ - char_two->p.onBasis = ASN1_NULL_new(); - if (!char_two->p.onBasis) - { - ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); - goto err; - } - } - } + { + int field_type; + X9_62_CHARACTERISTIC_TWO *char_two; + + field->p.char_two = X9_62_CHARACTERISTIC_TWO_new(); + char_two = field->p.char_two; + + if (char_two == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); + goto err; + } + + char_two->m = (long)EC_GROUP_get_degree(group); + + field_type = EC_GROUP_get_basis_type(group); + + if (field_type == 0) { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB); + goto err; + } + /* set base type OID */ + if ((char_two->type = OBJ_nid2obj(field_type)) == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB); + goto err; + } + + if (field_type == NID_X9_62_tpBasis) { + unsigned int k; + + if (!EC_GROUP_get_trinomial_basis(group, &k)) + goto err; + + char_two->p.tpBasis = ASN1_INTEGER_new(); + if (!char_two->p.tpBasis) { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!ASN1_INTEGER_set(char_two->p.tpBasis, (long)k)) { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB); + goto err; + } + } else if (field_type == NID_X9_62_ppBasis) { + unsigned int k1, k2, k3; + + if (!EC_GROUP_get_pentanomial_basis(group, &k1, &k2, &k3)) + goto err; + + char_two->p.ppBasis = X9_62_PENTANOMIAL_new(); + if (!char_two->p.ppBasis) { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* set k? values */ + char_two->p.ppBasis->k1 = (long)k1; + char_two->p.ppBasis->k2 = (long)k2; + char_two->p.ppBasis->k3 = (long)k3; + } else { /* field_type == NID_X9_62_onBasis */ + + /* for ONB the parameters are (asn1) NULL */ + char_two->p.onBasis = ASN1_NULL_new(); + if (!char_two->p.onBasis) { + ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE); + goto err; + } + } + } #endif - ok = 1; + ok = 1; -err : if (tmp) - BN_free(tmp); - return(ok); + err:if (tmp) + BN_free(tmp); + return (ok); } static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve) - { - int ok=0, nid; - BIGNUM *tmp_1=NULL, *tmp_2=NULL; - unsigned char *buffer_1=NULL, *buffer_2=NULL, - *a_buf=NULL, *b_buf=NULL; - size_t len_1, len_2; - unsigned char char_zero = 0; - - if (!group || !curve || !curve->a || !curve->b) - return 0; - - if ((tmp_1 = BN_new()) == NULL || (tmp_2 = BN_new()) == NULL) - { - ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE); - goto err; - } - - nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group)); - - /* get a and b */ - if (nid == NID_X9_62_prime_field) - { - if (!EC_GROUP_get_curve_GFp(group, NULL, tmp_1, tmp_2, NULL)) - { - ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB); - goto err; - } - } +{ + int ok = 0, nid; + BIGNUM *tmp_1 = NULL, *tmp_2 = NULL; + unsigned char *buffer_1 = NULL, *buffer_2 = NULL, + *a_buf = NULL, *b_buf = NULL; + size_t len_1, len_2; + unsigned char char_zero = 0; + + if (!group || !curve || !curve->a || !curve->b) + return 0; + + if ((tmp_1 = BN_new()) == NULL || (tmp_2 = BN_new()) == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE); + goto err; + } + + nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group)); + + /* get a and b */ + if (nid == NID_X9_62_prime_field) { + if (!EC_GROUP_get_curve_GFp(group, NULL, tmp_1, tmp_2, NULL)) { + ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB); + goto err; + } + } #ifndef OPENSSL_NO_EC2M - else /* nid == NID_X9_62_characteristic_two_field */ - { - if (!EC_GROUP_get_curve_GF2m(group, NULL, tmp_1, tmp_2, NULL)) - { - ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB); - goto err; - } - } + else { /* nid == NID_X9_62_characteristic_two_field */ + + if (!EC_GROUP_get_curve_GF2m(group, NULL, tmp_1, tmp_2, NULL)) { + ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB); + goto err; + } + } #endif - len_1 = (size_t)BN_num_bytes(tmp_1); - len_2 = (size_t)BN_num_bytes(tmp_2); - - if (len_1 == 0) - { - /* len_1 == 0 => a == 0 */ - a_buf = &char_zero; - len_1 = 1; - } - else - { - if ((buffer_1 = OPENSSL_malloc(len_1)) == NULL) - { - ECerr(EC_F_EC_ASN1_GROUP2CURVE, - ERR_R_MALLOC_FAILURE); - goto err; - } - if ( (len_1 = BN_bn2bin(tmp_1, buffer_1)) == 0) - { - ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB); - goto err; - } - a_buf = buffer_1; - } - - if (len_2 == 0) - { - /* len_2 == 0 => b == 0 */ - b_buf = &char_zero; - len_2 = 1; - } - else - { - if ((buffer_2 = OPENSSL_malloc(len_2)) == NULL) - { - ECerr(EC_F_EC_ASN1_GROUP2CURVE, - ERR_R_MALLOC_FAILURE); - goto err; - } - if ( (len_2 = BN_bn2bin(tmp_2, buffer_2)) == 0) - { - ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB); - goto err; - } - b_buf = buffer_2; - } - - /* set a and b */ - if (!M_ASN1_OCTET_STRING_set(curve->a, a_buf, len_1) || - !M_ASN1_OCTET_STRING_set(curve->b, b_buf, len_2)) - { - ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB); - goto err; - } - - /* set the seed (optional) */ - if (group->seed) - { - if (!curve->seed) - if ((curve->seed = ASN1_BIT_STRING_new()) == NULL) - { - ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE); - goto err; - } - curve->seed->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); - curve->seed->flags |= ASN1_STRING_FLAG_BITS_LEFT; - if (!ASN1_BIT_STRING_set(curve->seed, group->seed, - (int)group->seed_len)) - { - ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB); - goto err; - } - } - else - { - if (curve->seed) - { - ASN1_BIT_STRING_free(curve->seed); - curve->seed = NULL; - } - } - - ok = 1; - -err: if (buffer_1) - OPENSSL_free(buffer_1); - if (buffer_2) - OPENSSL_free(buffer_2); - if (tmp_1) - BN_free(tmp_1); - if (tmp_2) - BN_free(tmp_2); - return(ok); - } + len_1 = (size_t)BN_num_bytes(tmp_1); + len_2 = (size_t)BN_num_bytes(tmp_2); + + if (len_1 == 0) { + /* len_1 == 0 => a == 0 */ + a_buf = &char_zero; + len_1 = 1; + } else { + if ((buffer_1 = OPENSSL_malloc(len_1)) == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE); + goto err; + } + if ((len_1 = BN_bn2bin(tmp_1, buffer_1)) == 0) { + ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB); + goto err; + } + a_buf = buffer_1; + } + + if (len_2 == 0) { + /* len_2 == 0 => b == 0 */ + b_buf = &char_zero; + len_2 = 1; + } else { + if ((buffer_2 = OPENSSL_malloc(len_2)) == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE); + goto err; + } + if ((len_2 = BN_bn2bin(tmp_2, buffer_2)) == 0) { + ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB); + goto err; + } + b_buf = buffer_2; + } + + /* set a and b */ + if (!M_ASN1_OCTET_STRING_set(curve->a, a_buf, len_1) || + !M_ASN1_OCTET_STRING_set(curve->b, b_buf, len_2)) { + ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB); + goto err; + } + + /* set the seed (optional) */ + if (group->seed) { + if (!curve->seed) + if ((curve->seed = ASN1_BIT_STRING_new()) == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE); + goto err; + } + curve->seed->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + curve->seed->flags |= ASN1_STRING_FLAG_BITS_LEFT; + if (!ASN1_BIT_STRING_set(curve->seed, group->seed, + (int)group->seed_len)) { + ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB); + goto err; + } + } else { + if (curve->seed) { + ASN1_BIT_STRING_free(curve->seed); + curve->seed = NULL; + } + } + + ok = 1; + + err:if (buffer_1) + OPENSSL_free(buffer_1); + if (buffer_2) + OPENSSL_free(buffer_2); + if (tmp_1) + BN_free(tmp_1); + if (tmp_2) + BN_free(tmp_2); + return (ok); +} static ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *group, ECPARAMETERS *param) - { - int ok=0; - size_t len=0; - ECPARAMETERS *ret=NULL; - BIGNUM *tmp=NULL; - unsigned char *buffer=NULL; - const EC_POINT *point=NULL; - point_conversion_form_t form; - - if ((tmp = BN_new()) == NULL) - { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE); - goto err; - } - - if (param == NULL) - { - if ((ret = ECPARAMETERS_new()) == NULL) - { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, - ERR_R_MALLOC_FAILURE); - goto err; - } - } - else - ret = param; - - /* set the version (always one) */ - ret->version = (long)0x1; - - /* set the fieldID */ - if (!ec_asn1_group2fieldid(group, ret->fieldID)) - { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); - goto err; - } - - /* set the curve */ - if (!ec_asn1_group2curve(group, ret->curve)) - { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); - goto err; - } - - /* set the base point */ - if ((point = EC_GROUP_get0_generator(group)) == NULL) - { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, EC_R_UNDEFINED_GENERATOR); - goto err; - } - - form = EC_GROUP_get_point_conversion_form(group); - - len = EC_POINT_point2oct(group, point, form, NULL, len, NULL); - if (len == 0) - { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); - goto err; - } - if ((buffer = OPENSSL_malloc(len)) == NULL) - { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE); - goto err; - } - if (!EC_POINT_point2oct(group, point, form, buffer, len, NULL)) - { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); - goto err; - } - if (ret->base == NULL && (ret->base = ASN1_OCTET_STRING_new()) == NULL) - { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE); - goto err; - } - if (!ASN1_OCTET_STRING_set(ret->base, buffer, len)) - { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB); - goto err; - } - - /* set the order */ - if (!EC_GROUP_get_order(group, tmp, NULL)) - { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); - goto err; - } - ret->order = BN_to_ASN1_INTEGER(tmp, ret->order); - if (ret->order == NULL) - { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB); - goto err; - } - - /* set the cofactor (optional) */ - if (EC_GROUP_get_cofactor(group, tmp, NULL)) - { - ret->cofactor = BN_to_ASN1_INTEGER(tmp, ret->cofactor); - if (ret->cofactor == NULL) - { - ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB); - goto err; - } - } - - ok = 1; - -err : if(!ok) - { - if (ret && !param) - ECPARAMETERS_free(ret); - ret = NULL; - } - if (tmp) - BN_free(tmp); - if (buffer) - OPENSSL_free(buffer); - return(ret); - } - -ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *group, +{ + int ok = 0; + size_t len = 0; + ECPARAMETERS *ret = NULL; + BIGNUM *tmp = NULL; + unsigned char *buffer = NULL; + const EC_POINT *point = NULL; + point_conversion_form_t form; + + if ((tmp = BN_new()) == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (param == NULL) { + if ((ret = ECPARAMETERS_new()) == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE); + goto err; + } + } else + ret = param; + + /* set the version (always one) */ + ret->version = (long)0x1; + + /* set the fieldID */ + if (!ec_asn1_group2fieldid(group, ret->fieldID)) { + ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); + goto err; + } + + /* set the curve */ + if (!ec_asn1_group2curve(group, ret->curve)) { + ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); + goto err; + } + + /* set the base point */ + if ((point = EC_GROUP_get0_generator(group)) == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, EC_R_UNDEFINED_GENERATOR); + goto err; + } + + form = EC_GROUP_get_point_conversion_form(group); + + len = EC_POINT_point2oct(group, point, form, NULL, len, NULL); + if (len == 0) { + ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); + goto err; + } + if ((buffer = OPENSSL_malloc(len)) == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!EC_POINT_point2oct(group, point, form, buffer, len, NULL)) { + ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); + goto err; + } + if (ret->base == NULL && (ret->base = ASN1_OCTET_STRING_new()) == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!ASN1_OCTET_STRING_set(ret->base, buffer, len)) { + ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB); + goto err; + } + + /* set the order */ + if (!EC_GROUP_get_order(group, tmp, NULL)) { + ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB); + goto err; + } + ret->order = BN_to_ASN1_INTEGER(tmp, ret->order); + if (ret->order == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB); + goto err; + } + + /* set the cofactor (optional) */ + if (EC_GROUP_get_cofactor(group, tmp, NULL)) { + ret->cofactor = BN_to_ASN1_INTEGER(tmp, ret->cofactor); + if (ret->cofactor == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB); + goto err; + } + } + + ok = 1; + + err:if (!ok) { + if (ret && !param) + ECPARAMETERS_free(ret); + ret = NULL; + } + if (tmp) + BN_free(tmp); + if (buffer) + OPENSSL_free(buffer); + return (ret); +} + +ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *group, ECPKPARAMETERS *params) - { - int ok = 1, tmp; - ECPKPARAMETERS *ret = params; - - if (ret == NULL) - { - if ((ret = ECPKPARAMETERS_new()) == NULL) - { - ECerr(EC_F_EC_ASN1_GROUP2PKPARAMETERS, - ERR_R_MALLOC_FAILURE); - return NULL; - } - } - else - { - if (ret->type == 0 && ret->value.named_curve) - ASN1_OBJECT_free(ret->value.named_curve); - else if (ret->type == 1 && ret->value.parameters) - ECPARAMETERS_free(ret->value.parameters); - } - - if (EC_GROUP_get_asn1_flag(group)) - { - /* use the asn1 OID to describe the - * the elliptic curve parameters - */ - tmp = EC_GROUP_get_curve_name(group); - if (tmp) - { - ret->type = 0; - if ((ret->value.named_curve = OBJ_nid2obj(tmp)) == NULL) - ok = 0; - } - else - /* we don't kmow the nid => ERROR */ - ok = 0; - } - else - { - /* use the ECPARAMETERS structure */ - ret->type = 1; - if ((ret->value.parameters = ec_asn1_group2parameters( - group, NULL)) == NULL) - ok = 0; - } - - if (!ok) - { - ECPKPARAMETERS_free(ret); - return NULL; - } - return ret; - } +{ + int ok = 1, tmp; + ECPKPARAMETERS *ret = params; + + if (ret == NULL) { + if ((ret = ECPKPARAMETERS_new()) == NULL) { + ECerr(EC_F_EC_ASN1_GROUP2PKPARAMETERS, ERR_R_MALLOC_FAILURE); + return NULL; + } + } else { + if (ret->type == 0 && ret->value.named_curve) + ASN1_OBJECT_free(ret->value.named_curve); + else if (ret->type == 1 && ret->value.parameters) + ECPARAMETERS_free(ret->value.parameters); + } + + if (EC_GROUP_get_asn1_flag(group)) { + /* + * use the asn1 OID to describe the the elliptic curve parameters + */ + tmp = EC_GROUP_get_curve_name(group); + if (tmp) { + ret->type = 0; + if ((ret->value.named_curve = OBJ_nid2obj(tmp)) == NULL) + ok = 0; + } else + /* we don't kmow the nid => ERROR */ + ok = 0; + } else { + /* use the ECPARAMETERS structure */ + ret->type = 1; + if ((ret->value.parameters = + ec_asn1_group2parameters(group, NULL)) == NULL) + ok = 0; + } + + if (!ok) { + ECPKPARAMETERS_free(ret); + return NULL; + } + return ret; +} static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params) - { - int ok = 0, tmp; - EC_GROUP *ret = NULL; - BIGNUM *p = NULL, *a = NULL, *b = NULL; - EC_POINT *point=NULL; - long field_bits; - - if (!params->fieldID || !params->fieldID->fieldType || - !params->fieldID->p.ptr) - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); - goto err; - } - - /* now extract the curve parameters a and b */ - if (!params->curve || !params->curve->a || - !params->curve->a->data || !params->curve->b || - !params->curve->b->data) - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); - goto err; - } - a = BN_bin2bn(params->curve->a->data, params->curve->a->length, NULL); - if (a == NULL) - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB); - goto err; - } - b = BN_bin2bn(params->curve->b->data, params->curve->b->length, NULL); - if (b == NULL) - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB); - goto err; - } - - /* get the field parameters */ - tmp = OBJ_obj2nid(params->fieldID->fieldType); - if (tmp == NID_X9_62_characteristic_two_field) +{ + int ok = 0, tmp; + EC_GROUP *ret = NULL; + BIGNUM *p = NULL, *a = NULL, *b = NULL; + EC_POINT *point = NULL; + long field_bits; + + if (!params->fieldID || !params->fieldID->fieldType || + !params->fieldID->p.ptr) { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); + goto err; + } + + /* now extract the curve parameters a and b */ + if (!params->curve || !params->curve->a || + !params->curve->a->data || !params->curve->b || + !params->curve->b->data) { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); + goto err; + } + a = BN_bin2bn(params->curve->a->data, params->curve->a->length, NULL); + if (a == NULL) { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB); + goto err; + } + b = BN_bin2bn(params->curve->b->data, params->curve->b->length, NULL); + if (b == NULL) { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB); + goto err; + } + + /* get the field parameters */ + tmp = OBJ_obj2nid(params->fieldID->fieldType); + if (tmp == NID_X9_62_characteristic_two_field) #ifdef OPENSSL_NO_EC2M - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_GF2M_NOT_SUPPORTED); - goto err; - } + { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_GF2M_NOT_SUPPORTED); + goto err; + } #else - { - X9_62_CHARACTERISTIC_TWO *char_two; - - char_two = params->fieldID->p.char_two; - - field_bits = char_two->m; - if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_FIELD_TOO_LARGE); - goto err; - } - - if ((p = BN_new()) == NULL) - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_MALLOC_FAILURE); - goto err; - } - - /* get the base type */ - tmp = OBJ_obj2nid(char_two->type); - - if (tmp == NID_X9_62_tpBasis) - { - long tmp_long; - - if (!char_two->p.tpBasis) - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); - goto err; - } - - tmp_long = ASN1_INTEGER_get(char_two->p.tpBasis); - - if (!(char_two->m > tmp_long && tmp_long > 0)) - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_TRINOMIAL_BASIS); - goto err; - } - - /* create the polynomial */ - if (!BN_set_bit(p, (int)char_two->m)) - goto err; - if (!BN_set_bit(p, (int)tmp_long)) - goto err; - if (!BN_set_bit(p, 0)) - goto err; - } - else if (tmp == NID_X9_62_ppBasis) - { - X9_62_PENTANOMIAL *penta; - - penta = char_two->p.ppBasis; - if (!penta) - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); - goto err; - } - - if (!(char_two->m > penta->k3 && penta->k3 > penta->k2 && penta->k2 > penta->k1 && penta->k1 > 0)) - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_PENTANOMIAL_BASIS); - goto err; - } - - /* create the polynomial */ - if (!BN_set_bit(p, (int)char_two->m)) goto err; - if (!BN_set_bit(p, (int)penta->k1)) goto err; - if (!BN_set_bit(p, (int)penta->k2)) goto err; - if (!BN_set_bit(p, (int)penta->k3)) goto err; - if (!BN_set_bit(p, 0)) goto err; - } - else if (tmp == NID_X9_62_onBasis) - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_NOT_IMPLEMENTED); - goto err; - } - else /* error */ - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); - goto err; - } - - /* create the EC_GROUP structure */ - ret = EC_GROUP_new_curve_GF2m(p, a, b, NULL); - } + { + X9_62_CHARACTERISTIC_TWO *char_two; + + char_two = params->fieldID->p.char_two; + + field_bits = char_two->m; + if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_FIELD_TOO_LARGE); + goto err; + } + + if ((p = BN_new()) == NULL) { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* get the base type */ + tmp = OBJ_obj2nid(char_two->type); + + if (tmp == NID_X9_62_tpBasis) { + long tmp_long; + + if (!char_two->p.tpBasis) { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); + goto err; + } + + tmp_long = ASN1_INTEGER_get(char_two->p.tpBasis); + + if (!(char_two->m > tmp_long && tmp_long > 0)) { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, + EC_R_INVALID_TRINOMIAL_BASIS); + goto err; + } + + /* create the polynomial */ + if (!BN_set_bit(p, (int)char_two->m)) + goto err; + if (!BN_set_bit(p, (int)tmp_long)) + goto err; + if (!BN_set_bit(p, 0)) + goto err; + } else if (tmp == NID_X9_62_ppBasis) { + X9_62_PENTANOMIAL *penta; + + penta = char_two->p.ppBasis; + if (!penta) { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); + goto err; + } + + if (! + (char_two->m > penta->k3 && penta->k3 > penta->k2 + && penta->k2 > penta->k1 && penta->k1 > 0)) { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, + EC_R_INVALID_PENTANOMIAL_BASIS); + goto err; + } + + /* create the polynomial */ + if (!BN_set_bit(p, (int)char_two->m)) + goto err; + if (!BN_set_bit(p, (int)penta->k1)) + goto err; + if (!BN_set_bit(p, (int)penta->k2)) + goto err; + if (!BN_set_bit(p, (int)penta->k3)) + goto err; + if (!BN_set_bit(p, 0)) + goto err; + } else if (tmp == NID_X9_62_onBasis) { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_NOT_IMPLEMENTED); + goto err; + } else { /* error */ + + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); + goto err; + } + + /* create the EC_GROUP structure */ + ret = EC_GROUP_new_curve_GF2m(p, a, b, NULL); + } #endif - else if (tmp == NID_X9_62_prime_field) - { - /* we have a curve over a prime field */ - /* extract the prime number */ - if (!params->fieldID->p.prime) - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); - goto err; - } - p = ASN1_INTEGER_to_BN(params->fieldID->p.prime, NULL); - if (p == NULL) - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB); - goto err; - } - - if (BN_is_negative(p) || BN_is_zero(p)) - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_FIELD); - goto err; - } - - field_bits = BN_num_bits(p); - if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_FIELD_TOO_LARGE); - goto err; - } - - /* create the EC_GROUP structure */ - ret = EC_GROUP_new_curve_GFp(p, a, b, NULL); - } - else - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_FIELD); - goto err; - } - - if (ret == NULL) - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB); - goto err; - } - - /* extract seed (optional) */ - if (params->curve->seed != NULL) - { - if (ret->seed != NULL) - OPENSSL_free(ret->seed); - if (!(ret->seed = OPENSSL_malloc(params->curve->seed->length))) - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, - ERR_R_MALLOC_FAILURE); - goto err; - } - memcpy(ret->seed, params->curve->seed->data, - params->curve->seed->length); - ret->seed_len = params->curve->seed->length; - } - - if (!params->order || !params->base || !params->base->data) - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); - goto err; - } - - if ((point = EC_POINT_new(ret)) == NULL) goto err; - - /* set the point conversion form */ - EC_GROUP_set_point_conversion_form(ret, (point_conversion_form_t) - (params->base->data[0] & ~0x01)); - - /* extract the ec point */ - if (!EC_POINT_oct2point(ret, point, params->base->data, - params->base->length, NULL)) - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB); - goto err; - } - - /* extract the order */ - if ((a = ASN1_INTEGER_to_BN(params->order, a)) == NULL) - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB); - goto err; - } - if (BN_is_negative(a) || BN_is_zero(a)) - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_GROUP_ORDER); - goto err; - } - if (BN_num_bits(a) > (int)field_bits + 1) /* Hasse bound */ - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_GROUP_ORDER); - goto err; - } - - /* extract the cofactor (optional) */ - if (params->cofactor == NULL) - { - if (b) - { - BN_free(b); - b = NULL; - } - } - else - if ((b = ASN1_INTEGER_to_BN(params->cofactor, b)) == NULL) - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB); - goto err; - } - /* set the generator, order and cofactor (if present) */ - if (!EC_GROUP_set_generator(ret, point, a, b)) - { - ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB); - goto err; - } - - ok = 1; - -err: if (!ok) - { - if (ret) - EC_GROUP_clear_free(ret); - ret = NULL; - } - - if (p) - BN_free(p); - if (a) - BN_free(a); - if (b) - BN_free(b); - if (point) - EC_POINT_free(point); - return(ret); + else if (tmp == NID_X9_62_prime_field) { + /* we have a curve over a prime field */ + /* extract the prime number */ + if (!params->fieldID->p.prime) { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); + goto err; + } + p = ASN1_INTEGER_to_BN(params->fieldID->p.prime, NULL); + if (p == NULL) { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB); + goto err; + } + + if (BN_is_negative(p) || BN_is_zero(p)) { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_FIELD); + goto err; + } + + field_bits = BN_num_bits(p); + if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_FIELD_TOO_LARGE); + goto err; + } + + /* create the EC_GROUP structure */ + ret = EC_GROUP_new_curve_GFp(p, a, b, NULL); + } else { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_FIELD); + goto err; + } + + if (ret == NULL) { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB); + goto err; + } + + /* extract seed (optional) */ + if (params->curve->seed != NULL) { + if (ret->seed != NULL) + OPENSSL_free(ret->seed); + if (!(ret->seed = OPENSSL_malloc(params->curve->seed->length))) { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_MALLOC_FAILURE); + goto err; + } + memcpy(ret->seed, params->curve->seed->data, + params->curve->seed->length); + ret->seed_len = params->curve->seed->length; + } + + if (!params->order || !params->base || !params->base->data) { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR); + goto err; + } + + if ((point = EC_POINT_new(ret)) == NULL) + goto err; + + /* set the point conversion form */ + EC_GROUP_set_point_conversion_form(ret, (point_conversion_form_t) + (params->base->data[0] & ~0x01)); + + /* extract the ec point */ + if (!EC_POINT_oct2point(ret, point, params->base->data, + params->base->length, NULL)) { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB); + goto err; + } + + /* extract the order */ + if ((a = ASN1_INTEGER_to_BN(params->order, a)) == NULL) { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB); + goto err; + } + if (BN_is_negative(a) || BN_is_zero(a)) { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_GROUP_ORDER); + goto err; + } + if (BN_num_bits(a) > (int)field_bits + 1) { /* Hasse bound */ + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_GROUP_ORDER); + goto err; + } + + /* extract the cofactor (optional) */ + if (params->cofactor == NULL) { + if (b) { + BN_free(b); + b = NULL; + } + } else if ((b = ASN1_INTEGER_to_BN(params->cofactor, b)) == NULL) { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB); + goto err; + } + /* set the generator, order and cofactor (if present) */ + if (!EC_GROUP_set_generator(ret, point, a, b)) { + ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB); + goto err; + } + + ok = 1; + + err:if (!ok) { + if (ret) + EC_GROUP_clear_free(ret); + ret = NULL; + } + + if (p) + BN_free(p); + if (a) + BN_free(a); + if (b) + BN_free(b); + if (point) + EC_POINT_free(point); + return (ret); } EC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *params) - { - EC_GROUP *ret=NULL; - int tmp=0; - - if (params == NULL) - { - ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, - EC_R_MISSING_PARAMETERS); - return NULL; - } - - if (params->type == 0) - { /* the curve is given by an OID */ - tmp = OBJ_obj2nid(params->value.named_curve); - if ((ret = EC_GROUP_new_by_curve_name(tmp)) == NULL) - { - ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, - EC_R_EC_GROUP_NEW_BY_NAME_FAILURE); - return NULL; - } - EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_NAMED_CURVE); - } - else if (params->type == 1) - { /* the parameters are given by a ECPARAMETERS - * structure */ - ret = ec_asn1_parameters2group(params->value.parameters); - if (!ret) - { - ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, ERR_R_EC_LIB); - return NULL; - } - EC_GROUP_set_asn1_flag(ret, 0x0); - } - else if (params->type == 2) - { /* implicitlyCA */ - return NULL; - } - else - { - ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, EC_R_ASN1_ERROR); - return NULL; - } - - return ret; - } +{ + EC_GROUP *ret = NULL; + int tmp = 0; + + if (params == NULL) { + ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, EC_R_MISSING_PARAMETERS); + return NULL; + } + + if (params->type == 0) { /* the curve is given by an OID */ + tmp = OBJ_obj2nid(params->value.named_curve); + if ((ret = EC_GROUP_new_by_curve_name(tmp)) == NULL) { + ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, + EC_R_EC_GROUP_NEW_BY_NAME_FAILURE); + return NULL; + } + EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_NAMED_CURVE); + } else if (params->type == 1) { /* the parameters are given by a + * ECPARAMETERS structure */ + ret = ec_asn1_parameters2group(params->value.parameters); + if (!ret) { + ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, ERR_R_EC_LIB); + return NULL; + } + EC_GROUP_set_asn1_flag(ret, 0x0); + } else if (params->type == 2) { /* implicitlyCA */ + return NULL; + } else { + ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, EC_R_ASN1_ERROR); + return NULL; + } + + return ret; +} /* EC_GROUP <-> DER encoding of ECPKPARAMETERS */ EC_GROUP *d2i_ECPKParameters(EC_GROUP **a, const unsigned char **in, long len) - { - EC_GROUP *group = NULL; - ECPKPARAMETERS *params = NULL; - - if ((params = d2i_ECPKPARAMETERS(NULL, in, len)) == NULL) - { - ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_D2I_ECPKPARAMETERS_FAILURE); - ECPKPARAMETERS_free(params); - return NULL; - } - - if ((group = ec_asn1_pkparameters2group(params)) == NULL) - { - ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_PKPARAMETERS2GROUP_FAILURE); - ECPKPARAMETERS_free(params); - return NULL; - } - - - if (a && *a) - EC_GROUP_clear_free(*a); - if (a) - *a = group; - - ECPKPARAMETERS_free(params); - return(group); - } +{ + EC_GROUP *group = NULL; + ECPKPARAMETERS *params = NULL; + + if ((params = d2i_ECPKPARAMETERS(NULL, in, len)) == NULL) { + ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_D2I_ECPKPARAMETERS_FAILURE); + ECPKPARAMETERS_free(params); + return NULL; + } + + if ((group = ec_asn1_pkparameters2group(params)) == NULL) { + ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_PKPARAMETERS2GROUP_FAILURE); + ECPKPARAMETERS_free(params); + return NULL; + } + + if (a && *a) + EC_GROUP_clear_free(*a); + if (a) + *a = group; + + ECPKPARAMETERS_free(params); + return (group); +} int i2d_ECPKParameters(const EC_GROUP *a, unsigned char **out) - { - int ret=0; - ECPKPARAMETERS *tmp = ec_asn1_group2pkparameters(a, NULL); - if (tmp == NULL) - { - ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_GROUP2PKPARAMETERS_FAILURE); - return 0; - } - if ((ret = i2d_ECPKPARAMETERS(tmp, out)) == 0) - { - ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_I2D_ECPKPARAMETERS_FAILURE); - ECPKPARAMETERS_free(tmp); - return 0; - } - ECPKPARAMETERS_free(tmp); - return(ret); - } +{ + int ret = 0; + ECPKPARAMETERS *tmp = ec_asn1_group2pkparameters(a, NULL); + if (tmp == NULL) { + ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_GROUP2PKPARAMETERS_FAILURE); + return 0; + } + if ((ret = i2d_ECPKPARAMETERS(tmp, out)) == 0) { + ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_I2D_ECPKPARAMETERS_FAILURE); + ECPKPARAMETERS_free(tmp); + return 0; + } + ECPKPARAMETERS_free(tmp); + return (ret); +} /* some EC_KEY functions */ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len) - { - int ok=0; - EC_KEY *ret=NULL; - EC_PRIVATEKEY *priv_key=NULL; - - if ((priv_key = EC_PRIVATEKEY_new()) == NULL) - { - ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); - return NULL; - } - - if ((priv_key = d2i_EC_PRIVATEKEY(&priv_key, in, len)) == NULL) - { - ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); - EC_PRIVATEKEY_free(priv_key); - return NULL; - } - - if (a == NULL || *a == NULL) - { - if ((ret = EC_KEY_new()) == NULL) - { - ECerr(EC_F_D2I_ECPRIVATEKEY, - ERR_R_MALLOC_FAILURE); - goto err; - } - if (a) - *a = ret; - } - else - ret = *a; - - if (priv_key->parameters) - { - if (ret->group) - EC_GROUP_clear_free(ret->group); - ret->group = ec_asn1_pkparameters2group(priv_key->parameters); - } - - if (ret->group == NULL) - { - ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); - goto err; - } - - ret->version = priv_key->version; - - if (priv_key->privateKey) - { - ret->priv_key = BN_bin2bn( - M_ASN1_STRING_data(priv_key->privateKey), - M_ASN1_STRING_length(priv_key->privateKey), - ret->priv_key); - if (ret->priv_key == NULL) - { - ECerr(EC_F_D2I_ECPRIVATEKEY, - ERR_R_BN_LIB); - goto err; - } - } - else - { - ECerr(EC_F_D2I_ECPRIVATEKEY, - EC_R_MISSING_PRIVATE_KEY); - goto err; - } - - if (ret->pub_key) - EC_POINT_clear_free(ret->pub_key); - ret->pub_key = EC_POINT_new(ret->group); - if (ret->pub_key == NULL) - { - ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); - goto err; - } - - if (priv_key->publicKey) - { - const unsigned char *pub_oct; - int pub_oct_len; - - pub_oct = M_ASN1_STRING_data(priv_key->publicKey); - pub_oct_len = M_ASN1_STRING_length(priv_key->publicKey); - /* The first byte - point conversion form - must be present. */ - if (pub_oct_len <= 0) - { - ECerr(EC_F_D2I_ECPRIVATEKEY, EC_R_BUFFER_TOO_SMALL); - goto err; - } - /* Save the point conversion form. */ - ret->conv_form = (point_conversion_form_t)(pub_oct[0] & ~0x01); - if (!EC_POINT_oct2point(ret->group, ret->pub_key, - pub_oct, (size_t)(pub_oct_len), NULL)) - { - ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); - goto err; - } - } - else - { - if (!EC_POINT_mul(ret->group, ret->pub_key, ret->priv_key, NULL, NULL, NULL)) - { - ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); - goto err; - } - /* Remember the original private-key-only encoding. */ - ret->enc_flag |= EC_PKEY_NO_PUBKEY; - } - - ok = 1; -err: - if (!ok) - { - if (ret) - EC_KEY_free(ret); - ret = NULL; - } - - if (priv_key) - EC_PRIVATEKEY_free(priv_key); - - return(ret); - } - -int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out) - { - int ret=0, ok=0; - unsigned char *buffer=NULL; - size_t buf_len=0, tmp_len; - EC_PRIVATEKEY *priv_key=NULL; - - if (a == NULL || a->group == NULL || a->priv_key == NULL || - (!(a->enc_flag & EC_PKEY_NO_PUBKEY) && a->pub_key == NULL)) - { - ECerr(EC_F_I2D_ECPRIVATEKEY, - ERR_R_PASSED_NULL_PARAMETER); - goto err; - } - - if ((priv_key = EC_PRIVATEKEY_new()) == NULL) - { - ECerr(EC_F_I2D_ECPRIVATEKEY, - ERR_R_MALLOC_FAILURE); - goto err; - } - - priv_key->version = a->version; - - buf_len = (size_t)BN_num_bytes(a->priv_key); - buffer = OPENSSL_malloc(buf_len); - if (buffer == NULL) - { - ECerr(EC_F_I2D_ECPRIVATEKEY, - ERR_R_MALLOC_FAILURE); - goto err; - } - - if (!BN_bn2bin(a->priv_key, buffer)) - { - ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_BN_LIB); - goto err; - } - - if (!M_ASN1_OCTET_STRING_set(priv_key->privateKey, buffer, buf_len)) - { - ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB); - goto err; - } - - if (!(a->enc_flag & EC_PKEY_NO_PARAMETERS)) - { - if ((priv_key->parameters = ec_asn1_group2pkparameters( - a->group, priv_key->parameters)) == NULL) - { - ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); - goto err; - } - } - - if (!(a->enc_flag & EC_PKEY_NO_PUBKEY)) - { - priv_key->publicKey = M_ASN1_BIT_STRING_new(); - if (priv_key->publicKey == NULL) - { - ECerr(EC_F_I2D_ECPRIVATEKEY, - ERR_R_MALLOC_FAILURE); - goto err; - } - - tmp_len = EC_POINT_point2oct(a->group, a->pub_key, - a->conv_form, NULL, 0, NULL); - - if (tmp_len > buf_len) - { - unsigned char *tmp_buffer = OPENSSL_realloc(buffer, tmp_len); - if (!tmp_buffer) - { - ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); - goto err; - } - buffer = tmp_buffer; - buf_len = tmp_len; - } - - if (!EC_POINT_point2oct(a->group, a->pub_key, - a->conv_form, buffer, buf_len, NULL)) - { - ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); - goto err; - } - - priv_key->publicKey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); - priv_key->publicKey->flags |= ASN1_STRING_FLAG_BITS_LEFT; - if (!M_ASN1_BIT_STRING_set(priv_key->publicKey, buffer, - buf_len)) - { - ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB); - goto err; - } - } - - if ((ret = i2d_EC_PRIVATEKEY(priv_key, out)) == 0) - { - ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); - goto err; - } - ok=1; -err: - if (buffer) - OPENSSL_free(buffer); - if (priv_key) - EC_PRIVATEKEY_free(priv_key); - return(ok?ret:0); - } +{ + int ok = 0; + EC_KEY *ret = NULL; + EC_PRIVATEKEY *priv_key = NULL; + + if ((priv_key = d2i_EC_PRIVATEKEY(NULL, in, len)) == NULL) { + ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); + return NULL; + } + + if (a == NULL || *a == NULL) { + if ((ret = EC_KEY_new()) == NULL) { + ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); + goto err; + } + } else + ret = *a; + + if (priv_key->parameters) { + if (ret->group) + EC_GROUP_clear_free(ret->group); + ret->group = ec_asn1_pkparameters2group(priv_key->parameters); + } + + if (ret->group == NULL) { + ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); + goto err; + } + + ret->version = priv_key->version; + + if (priv_key->privateKey) { + ret->priv_key = BN_bin2bn(M_ASN1_STRING_data(priv_key->privateKey), + M_ASN1_STRING_length(priv_key->privateKey), + ret->priv_key); + if (ret->priv_key == NULL) { + ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_BN_LIB); + goto err; + } + } else { + ECerr(EC_F_D2I_ECPRIVATEKEY, EC_R_MISSING_PRIVATE_KEY); + goto err; + } + + if (ret->pub_key) + EC_POINT_clear_free(ret->pub_key); + ret->pub_key = EC_POINT_new(ret->group); + if (ret->pub_key == NULL) { + ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); + goto err; + } + + if (priv_key->publicKey) { + const unsigned char *pub_oct; + int pub_oct_len; + + pub_oct = M_ASN1_STRING_data(priv_key->publicKey); + pub_oct_len = M_ASN1_STRING_length(priv_key->publicKey); + /* + * The first byte - point conversion form - must be present. + */ + if (pub_oct_len <= 0) { + ECerr(EC_F_D2I_ECPRIVATEKEY, EC_R_BUFFER_TOO_SMALL); + goto err; + } + /* Save the point conversion form. */ + ret->conv_form = (point_conversion_form_t) (pub_oct[0] & ~0x01); + if (!EC_POINT_oct2point(ret->group, ret->pub_key, + pub_oct, (size_t)(pub_oct_len), NULL)) { + ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); + goto err; + } + } else { + if (!EC_POINT_mul + (ret->group, ret->pub_key, ret->priv_key, NULL, NULL, NULL)) { + ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB); + goto err; + } + /* Remember the original private-key-only encoding. */ + ret->enc_flag |= EC_PKEY_NO_PUBKEY; + } + + if (a) + *a = ret; + ok = 1; + err: + if (!ok) { + if (ret && (a == NULL || *a != ret)) + EC_KEY_free(ret); + ret = NULL; + } + + if (priv_key) + EC_PRIVATEKEY_free(priv_key); + + return (ret); +} + +int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out) +{ + int ret = 0, ok = 0; + unsigned char *buffer = NULL; + size_t buf_len = 0, tmp_len; + EC_PRIVATEKEY *priv_key = NULL; + + if (a == NULL || a->group == NULL || a->priv_key == NULL || + (!(a->enc_flag & EC_PKEY_NO_PUBKEY) && a->pub_key == NULL)) { + ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER); + goto err; + } + + if ((priv_key = EC_PRIVATEKEY_new()) == NULL) { + ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); + goto err; + } + + priv_key->version = a->version; + + buf_len = (size_t)BN_num_bytes(a->priv_key); + buffer = OPENSSL_malloc(buf_len); + if (buffer == NULL) { + ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!BN_bn2bin(a->priv_key, buffer)) { + ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_BN_LIB); + goto err; + } + + if (!M_ASN1_OCTET_STRING_set(priv_key->privateKey, buffer, buf_len)) { + ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB); + goto err; + } + + if (!(a->enc_flag & EC_PKEY_NO_PARAMETERS)) { + if ((priv_key->parameters = + ec_asn1_group2pkparameters(a->group, + priv_key->parameters)) == NULL) { + ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); + goto err; + } + } + + if (!(a->enc_flag & EC_PKEY_NO_PUBKEY)) { + priv_key->publicKey = M_ASN1_BIT_STRING_new(); + if (priv_key->publicKey == NULL) { + ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); + goto err; + } + + tmp_len = EC_POINT_point2oct(a->group, a->pub_key, + a->conv_form, NULL, 0, NULL); + + if (tmp_len > buf_len) { + unsigned char *tmp_buffer = OPENSSL_realloc(buffer, tmp_len); + if (!tmp_buffer) { + ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); + goto err; + } + buffer = tmp_buffer; + buf_len = tmp_len; + } + + if (!EC_POINT_point2oct(a->group, a->pub_key, + a->conv_form, buffer, buf_len, NULL)) { + ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); + goto err; + } + + priv_key->publicKey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + priv_key->publicKey->flags |= ASN1_STRING_FLAG_BITS_LEFT; + if (!M_ASN1_BIT_STRING_set(priv_key->publicKey, buffer, buf_len)) { + ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB); + goto err; + } + } + + if ((ret = i2d_EC_PRIVATEKEY(priv_key, out)) == 0) { + ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB); + goto err; + } + ok = 1; + err: + if (buffer) + OPENSSL_free(buffer); + if (priv_key) + EC_PRIVATEKEY_free(priv_key); + return (ok ? ret : 0); +} int i2d_ECParameters(EC_KEY *a, unsigned char **out) - { - if (a == NULL) - { - ECerr(EC_F_I2D_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - return i2d_ECPKParameters(a->group, out); - } +{ + if (a == NULL) { + ECerr(EC_F_I2D_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + return i2d_ECPKParameters(a->group, out); +} EC_KEY *d2i_ECParameters(EC_KEY **a, const unsigned char **in, long len) - { - EC_KEY *ret; - - if (in == NULL || *in == NULL) - { - ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER); - return NULL; - } - - if (a == NULL || *a == NULL) - { - if ((ret = EC_KEY_new()) == NULL) - { - ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_MALLOC_FAILURE); - return NULL; - } - if (a) - *a = ret; - } - else - ret = *a; - - if (!d2i_ECPKParameters(&ret->group, in, len)) - { - ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_EC_LIB); - return NULL; - } - - return ret; - } +{ + EC_KEY *ret; + + if (in == NULL || *in == NULL) { + ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + if (a == NULL || *a == NULL) { + if ((ret = EC_KEY_new()) == NULL) { + ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_MALLOC_FAILURE); + return NULL; + } + } else + ret = *a; + + if (!d2i_ECPKParameters(&ret->group, in, len)) { + ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_EC_LIB); + if (a == NULL || *a != ret) + EC_KEY_free(ret); + return NULL; + } + + if (a) + *a = ret; + + return ret; +} EC_KEY *o2i_ECPublicKey(EC_KEY **a, const unsigned char **in, long len) - { - EC_KEY *ret=NULL; - - if (a == NULL || (*a) == NULL || (*a)->group == NULL) - { - /* sorry, but a EC_GROUP-structur is necessary - * to set the public key */ - ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - ret = *a; - if (ret->pub_key == NULL && - (ret->pub_key = EC_POINT_new(ret->group)) == NULL) - { - ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_MALLOC_FAILURE); - return 0; - } - if (!EC_POINT_oct2point(ret->group, ret->pub_key, *in, len, NULL)) - { - ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_EC_LIB); - return 0; - } - /* save the point conversion form */ - ret->conv_form = (point_conversion_form_t)(*in[0] & ~0x01); - *in += len; - return ret; - } +{ + EC_KEY *ret = NULL; + + if (a == NULL || (*a) == NULL || (*a)->group == NULL) { + /* + * sorry, but a EC_GROUP-structur is necessary to set the public key + */ + ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + ret = *a; + if (ret->pub_key == NULL && + (ret->pub_key = EC_POINT_new(ret->group)) == NULL) { + ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_MALLOC_FAILURE); + return 0; + } + if (!EC_POINT_oct2point(ret->group, ret->pub_key, *in, len, NULL)) { + ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_EC_LIB); + return 0; + } + /* save the point conversion form */ + ret->conv_form = (point_conversion_form_t) (*in[0] & ~0x01); + *in += len; + return ret; +} int i2o_ECPublicKey(EC_KEY *a, unsigned char **out) - { - size_t buf_len=0; - int new_buffer = 0; - - if (a == NULL) - { - ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - - buf_len = EC_POINT_point2oct(a->group, a->pub_key, - a->conv_form, NULL, 0, NULL); - - if (out == NULL || buf_len == 0) - /* out == NULL => just return the length of the octet string */ - return buf_len; - - if (*out == NULL) - { - if ((*out = OPENSSL_malloc(buf_len)) == NULL) - { - ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_MALLOC_FAILURE); - return 0; - } - new_buffer = 1; - } - if (!EC_POINT_point2oct(a->group, a->pub_key, a->conv_form, - *out, buf_len, NULL)) - { - ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_EC_LIB); - if (new_buffer) - { - OPENSSL_free(*out); - *out = NULL; - } - return 0; - } - if (!new_buffer) - *out += buf_len; - return buf_len; - } +{ + size_t buf_len = 0; + int new_buffer = 0; + + if (a == NULL) { + ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + buf_len = EC_POINT_point2oct(a->group, a->pub_key, + a->conv_form, NULL, 0, NULL); + + if (out == NULL || buf_len == 0) + /* out == NULL => just return the length of the octet string */ + return buf_len; + + if (*out == NULL) { + if ((*out = OPENSSL_malloc(buf_len)) == NULL) { + ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_MALLOC_FAILURE); + return 0; + } + new_buffer = 1; + } + if (!EC_POINT_point2oct(a->group, a->pub_key, a->conv_form, + *out, buf_len, NULL)) { + ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_EC_LIB); + if (new_buffer) { + OPENSSL_free(*out); + *out = NULL; + } + return 0; + } + if (!new_buffer) + *out += buf_len; + return buf_len; +} diff --git a/openssl/crypto/ec/ec_check.c b/openssl/crypto/ec/ec_check.c index 0e316b4b3..d3f534999 100644 --- a/openssl/crypto/ec/ec_check.c +++ b/openssl/crypto/ec/ec_check.c @@ -7,7 +7,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -57,67 +57,64 @@ #include <openssl/err.h> int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx) - { - int ret = 0; - BIGNUM *order; - BN_CTX *new_ctx = NULL; - EC_POINT *point = NULL; +{ + int ret = 0; + BIGNUM *order; + 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_GROUP_CHECK, ERR_R_MALLOC_FAILURE); - goto err; - } - } - BN_CTX_start(ctx); - if ((order = BN_CTX_get(ctx)) == NULL) goto err; + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + ECerr(EC_F_EC_GROUP_CHECK, ERR_R_MALLOC_FAILURE); + goto err; + } + } + BN_CTX_start(ctx); + if ((order = BN_CTX_get(ctx)) == NULL) + goto err; - /* check the discriminant */ - if (!EC_GROUP_check_discriminant(group, ctx)) - { - ECerr(EC_F_EC_GROUP_CHECK, EC_R_DISCRIMINANT_IS_ZERO); - goto err; - } + /* check the discriminant */ + if (!EC_GROUP_check_discriminant(group, ctx)) { + ECerr(EC_F_EC_GROUP_CHECK, EC_R_DISCRIMINANT_IS_ZERO); + goto err; + } - /* check the generator */ - if (group->generator == NULL) - { - ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_GENERATOR); - goto err; - } - if (!EC_POINT_is_on_curve(group, group->generator, ctx)) - { - ECerr(EC_F_EC_GROUP_CHECK, EC_R_POINT_IS_NOT_ON_CURVE); - goto err; - } + /* check the generator */ + if (group->generator == NULL) { + ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_GENERATOR); + goto err; + } + if (!EC_POINT_is_on_curve(group, group->generator, ctx)) { + ECerr(EC_F_EC_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_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_GROUP_CHECK, EC_R_INVALID_GROUP_ORDER); - 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_GROUP_CHECK, EC_R_UNDEFINED_ORDER); + goto err; + } - ret = 1; + if (!EC_POINT_mul(group, point, order, NULL, NULL, ctx)) + goto err; + if (!EC_POINT_is_at_infinity(group, point)) { + ECerr(EC_F_EC_GROUP_CHECK, EC_R_INVALID_GROUP_ORDER); + goto err; + } -err: - if (ctx != NULL) - BN_CTX_end(ctx); - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - if (point) - EC_POINT_free(point); - return ret; - } + ret = 1; + + err: + if (ctx != NULL) + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + if (point) + EC_POINT_free(point); + return ret; +} diff --git a/openssl/crypto/ec/ec_curve.c b/openssl/crypto/ec/ec_curve.c index c72fb2697..e4bcb5dd8 100644 --- a/openssl/crypto/ec/ec_curve.c +++ b/openssl/crypto/ec/ec_curve.c @@ -10,7 +10,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -58,13 +58,13 @@ /* ==================================================================== * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. * - * Portions of the attached software ("Contribution") are developed by + * Portions of the attached software ("Contribution") are developed by * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. * * The Contribution is licensed pursuant to the OpenSSL open source * license provided above. * - * The elliptic curve binary polynomial software is originally written by + * The elliptic curve binary polynomial software is originally written by * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories. * */ @@ -75,2026 +75,2541 @@ #include <openssl/opensslconf.h> typedef struct { - int field_type, /* either NID_X9_62_prime_field or - * NID_X9_62_characteristic_two_field */ - seed_len, - param_len; - unsigned int cofactor; /* promoted to BN_ULONG */ + int field_type, /* either NID_X9_62_prime_field or + * NID_X9_62_characteristic_two_field */ + seed_len, param_len; + unsigned int cofactor; /* promoted to BN_ULONG */ } EC_CURVE_DATA; /* the nist prime curves */ -static const struct { EC_CURVE_DATA h; unsigned char data[20+24*6]; } - _EC_NIST_PRIME_192 = { - { NID_X9_62_prime_field,20,24,1 }, - { 0x30,0x45,0xAE,0x6F,0xC8,0x42,0x2F,0x64,0xED,0x57, /* seed */ - 0x95,0x28,0xD3,0x81,0x20,0xEA,0xE1,0x21,0x96,0xD5, - - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFC, - 0x64,0x21,0x05,0x19,0xE5,0x9C,0x80,0xE7,0x0F,0xA7, /* b */ - 0xE9,0xAB,0x72,0x24,0x30,0x49,0xFE,0xB8,0xDE,0xEC, - 0xC1,0x46,0xB9,0xB1, - 0x18,0x8D,0xA8,0x0E,0xB0,0x30,0x90,0xF6,0x7C,0xBF, /* x */ - 0x20,0xEB,0x43,0xA1,0x88,0x00,0xF4,0xFF,0x0A,0xFD, - 0x82,0xFF,0x10,0x12, - 0x07,0x19,0x2b,0x95,0xff,0xc8,0xda,0x78,0x63,0x10, /* y */ - 0x11,0xed,0x6b,0x24,0xcd,0xd5,0x73,0xf9,0x77,0xa1, - 0x1e,0x79,0x48,0x11, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */ - 0xFF,0xFF,0x99,0xDE,0xF8,0x36,0x14,0x6B,0xC9,0xB1, - 0xB4,0xD2,0x28,0x31 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+28*6]; } - _EC_NIST_PRIME_224 = { - { NID_X9_62_prime_field,20,28,1 }, - { 0xBD,0x71,0x34,0x47,0x99,0xD5,0xC7,0xFC,0xDC,0x45, /* seed */ - 0xB5,0x9F,0xA3,0xB9,0xAB,0x8F,0x6A,0x94,0x8B,0xC5, - - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, - 0xB4,0x05,0x0A,0x85,0x0C,0x04,0xB3,0xAB,0xF5,0x41, /* b */ - 0x32,0x56,0x50,0x44,0xB0,0xB7,0xD7,0xBF,0xD8,0xBA, - 0x27,0x0B,0x39,0x43,0x23,0x55,0xFF,0xB4, - 0xB7,0x0E,0x0C,0xBD,0x6B,0xB4,0xBF,0x7F,0x32,0x13, /* x */ - 0x90,0xB9,0x4A,0x03,0xC1,0xD3,0x56,0xC2,0x11,0x22, - 0x34,0x32,0x80,0xD6,0x11,0x5C,0x1D,0x21, - 0xbd,0x37,0x63,0x88,0xb5,0xf7,0x23,0xfb,0x4c,0x22, /* y */ - 0xdf,0xe6,0xcd,0x43,0x75,0xa0,0x5a,0x07,0x47,0x64, - 0x44,0xd5,0x81,0x99,0x85,0x00,0x7e,0x34, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */ - 0xFF,0xFF,0xFF,0xFF,0x16,0xA2,0xE0,0xB8,0xF0,0x3E, - 0x13,0xDD,0x29,0x45,0x5C,0x5C,0x2A,0x3D } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+48*6]; } - _EC_NIST_PRIME_384 = { - { NID_X9_62_prime_field,20,48,1 }, - { 0xA3,0x35,0x92,0x6A,0xA3,0x19,0xA2,0x7A,0x1D,0x00, /* seed */ - 0x89,0x6A,0x67,0x73,0xA4,0x82,0x7A,0xCD,0xAC,0x73, - - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFC, - 0xB3,0x31,0x2F,0xA7,0xE2,0x3E,0xE7,0xE4,0x98,0x8E, /* b */ - 0x05,0x6B,0xE3,0xF8,0x2D,0x19,0x18,0x1D,0x9C,0x6E, - 0xFE,0x81,0x41,0x12,0x03,0x14,0x08,0x8F,0x50,0x13, - 0x87,0x5A,0xC6,0x56,0x39,0x8D,0x8A,0x2E,0xD1,0x9D, - 0x2A,0x85,0xC8,0xED,0xD3,0xEC,0x2A,0xEF, - 0xAA,0x87,0xCA,0x22,0xBE,0x8B,0x05,0x37,0x8E,0xB1, /* x */ - 0xC7,0x1E,0xF3,0x20,0xAD,0x74,0x6E,0x1D,0x3B,0x62, - 0x8B,0xA7,0x9B,0x98,0x59,0xF7,0x41,0xE0,0x82,0x54, - 0x2A,0x38,0x55,0x02,0xF2,0x5D,0xBF,0x55,0x29,0x6C, - 0x3A,0x54,0x5E,0x38,0x72,0x76,0x0A,0xB7, - 0x36,0x17,0xde,0x4a,0x96,0x26,0x2c,0x6f,0x5d,0x9e, /* y */ - 0x98,0xbf,0x92,0x92,0xdc,0x29,0xf8,0xf4,0x1d,0xbd, - 0x28,0x9a,0x14,0x7c,0xe9,0xda,0x31,0x13,0xb5,0xf0, - 0xb8,0xc0,0x0a,0x60,0xb1,0xce,0x1d,0x7e,0x81,0x9d, - 0x7a,0x43,0x1d,0x7c,0x90,0xea,0x0e,0x5f, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xC7,0x63,0x4D,0x81,0xF4,0x37, - 0x2D,0xDF,0x58,0x1A,0x0D,0xB2,0x48,0xB0,0xA7,0x7A, - 0xEC,0xEC,0x19,0x6A,0xCC,0xC5,0x29,0x73 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+66*6]; } - _EC_NIST_PRIME_521 = { - { NID_X9_62_prime_field,20,66,1 }, - { 0xD0,0x9E,0x88,0x00,0x29,0x1C,0xB8,0x53,0x96,0xCC, /* seed */ - 0x67,0x17,0x39,0x32,0x84,0xAA,0xA0,0xDA,0x64,0xBA, - - 0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFC, - 0x00,0x51,0x95,0x3E,0xB9,0x61,0x8E,0x1C,0x9A,0x1F, /* b */ - 0x92,0x9A,0x21,0xA0,0xB6,0x85,0x40,0xEE,0xA2,0xDA, - 0x72,0x5B,0x99,0xB3,0x15,0xF3,0xB8,0xB4,0x89,0x91, - 0x8E,0xF1,0x09,0xE1,0x56,0x19,0x39,0x51,0xEC,0x7E, - 0x93,0x7B,0x16,0x52,0xC0,0xBD,0x3B,0xB1,0xBF,0x07, - 0x35,0x73,0xDF,0x88,0x3D,0x2C,0x34,0xF1,0xEF,0x45, - 0x1F,0xD4,0x6B,0x50,0x3F,0x00, - 0x00,0xC6,0x85,0x8E,0x06,0xB7,0x04,0x04,0xE9,0xCD, /* x */ - 0x9E,0x3E,0xCB,0x66,0x23,0x95,0xB4,0x42,0x9C,0x64, - 0x81,0x39,0x05,0x3F,0xB5,0x21,0xF8,0x28,0xAF,0x60, - 0x6B,0x4D,0x3D,0xBA,0xA1,0x4B,0x5E,0x77,0xEF,0xE7, - 0x59,0x28,0xFE,0x1D,0xC1,0x27,0xA2,0xFF,0xA8,0xDE, - 0x33,0x48,0xB3,0xC1,0x85,0x6A,0x42,0x9B,0xF9,0x7E, - 0x7E,0x31,0xC2,0xE5,0xBD,0x66, - 0x01,0x18,0x39,0x29,0x6a,0x78,0x9a,0x3b,0xc0,0x04, /* y */ - 0x5c,0x8a,0x5f,0xb4,0x2c,0x7d,0x1b,0xd9,0x98,0xf5, - 0x44,0x49,0x57,0x9b,0x44,0x68,0x17,0xaf,0xbd,0x17, - 0x27,0x3e,0x66,0x2c,0x97,0xee,0x72,0x99,0x5e,0xf4, - 0x26,0x40,0xc5,0x50,0xb9,0x01,0x3f,0xad,0x07,0x61, - 0x35,0x3c,0x70,0x86,0xa2,0x72,0xc2,0x40,0x88,0xbe, - 0x94,0x76,0x9f,0xd1,0x66,0x50, - 0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFA,0x51,0x86,0x87,0x83,0xBF,0x2F, - 0x96,0x6B,0x7F,0xCC,0x01,0x48,0xF7,0x09,0xA5,0xD0, - 0x3B,0xB5,0xC9,0xB8,0x89,0x9C,0x47,0xAE,0xBB,0x6F, - 0xB7,0x1E,0x91,0x38,0x64,0x09 } - }; +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 24 * 6]; +} _EC_NIST_PRIME_192 = { + { + NID_X9_62_prime_field, 20, 24, 1 + }, + { + /* seed */ + 0x30, 0x45, 0xAE, 0x6F, 0xC8, 0x42, 0x2F, 0x64, 0xED, 0x57, 0x95, 0x28, + 0xD3, 0x81, 0x20, 0xEA, 0xE1, 0x21, 0x96, 0xD5, + /* p */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* a */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + /* b */ + 0x64, 0x21, 0x05, 0x19, 0xE5, 0x9C, 0x80, 0xE7, 0x0F, 0xA7, 0xE9, 0xAB, + 0x72, 0x24, 0x30, 0x49, 0xFE, 0xB8, 0xDE, 0xEC, 0xC1, 0x46, 0xB9, 0xB1, + /* x */ + 0x18, 0x8D, 0xA8, 0x0E, 0xB0, 0x30, 0x90, 0xF6, 0x7C, 0xBF, 0x20, 0xEB, + 0x43, 0xA1, 0x88, 0x00, 0xF4, 0xFF, 0x0A, 0xFD, 0x82, 0xFF, 0x10, 0x12, + /* y */ + 0x07, 0x19, 0x2b, 0x95, 0xff, 0xc8, 0xda, 0x78, 0x63, 0x10, 0x11, 0xed, + 0x6b, 0x24, 0xcd, 0xd5, 0x73, 0xf9, 0x77, 0xa1, 0x1e, 0x79, 0x48, 0x11, + /* order */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x99, 0xDE, 0xF8, 0x36, 0x14, 0x6B, 0xC9, 0xB1, 0xB4, 0xD2, 0x28, 0x31 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 28 * 6]; +} _EC_NIST_PRIME_224 = { + { + NID_X9_62_prime_field, 20, 28, 1 + }, + { + /* seed */ + 0xBD, 0x71, 0x34, 0x47, 0x99, 0xD5, 0xC7, 0xFC, 0xDC, 0x45, 0xB5, 0x9F, + 0xA3, 0xB9, 0xAB, 0x8F, 0x6A, 0x94, 0x8B, 0xC5, + /* p */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + /* a */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, + /* b */ + 0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56, + 0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39, 0x43, + 0x23, 0x55, 0xFF, 0xB4, + /* x */ + 0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9, + 0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6, + 0x11, 0x5C, 0x1D, 0x21, + /* y */ + 0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6, + 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, 0x44, 0xd5, 0x81, 0x99, + 0x85, 0x00, 0x7e, 0x34, + /* order */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45, + 0x5C, 0x5C, 0x2A, 0x3D + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 48 * 6]; +} _EC_NIST_PRIME_384 = { + { + NID_X9_62_prime_field, 20, 48, 1 + }, + { + /* seed */ + 0xA3, 0x35, 0x92, 0x6A, 0xA3, 0x19, 0xA2, 0x7A, 0x1D, 0x00, 0x89, 0x6A, + 0x67, 0x73, 0xA4, 0x82, 0x7A, 0xCD, 0xAC, 0x73, + /* p */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + /* a */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC, + /* b */ + 0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B, + 0xE3, 0xF8, 0x2D, 0x19, 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12, + 0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, 0xC6, 0x56, 0x39, 0x8D, + 0x8A, 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF, + /* x */ + 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E, + 0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98, + 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D, + 0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7, + /* y */ + 0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e, 0x98, 0xbf, + 0x92, 0x92, 0xdc, 0x29, 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c, + 0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, 0x0a, 0x60, 0xb1, 0xce, + 0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f, + /* order */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, 0x58, 0x1A, 0x0D, 0xB2, + 0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 66 * 6]; +} _EC_NIST_PRIME_521 = { + { + NID_X9_62_prime_field, 20, 66, 1 + }, + { + /* seed */ + 0xD0, 0x9E, 0x88, 0x00, 0x29, 0x1C, 0xB8, 0x53, 0x96, 0xCC, 0x67, 0x17, + 0x39, 0x32, 0x84, 0xAA, 0xA0, 0xDA, 0x64, 0xBA, + /* p */ + 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* a */ + 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + /* b */ + 0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A, + 0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3, + 0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1, 0x56, 0x19, + 0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1, + 0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45, + 0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00, + /* x */ + 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E, + 0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F, + 0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B, + 0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF, + 0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E, + 0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66, + /* y */ + 0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a, + 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, + 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee, + 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, + 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe, + 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50, + /* order */ + 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x51, 0x86, + 0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09, + 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F, + 0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09 + } +}; /* the x9.62 prime curves (minus the nist prime curves) */ -static const struct { EC_CURVE_DATA h; unsigned char data[20+24*6]; } - _EC_X9_62_PRIME_192V2 = { - { NID_X9_62_prime_field,20,24,1 }, - { 0x31,0xA9,0x2E,0xE2,0x02,0x9F,0xD1,0x0D,0x90,0x1B, /* seed */ - 0x11,0x3E,0x99,0x07,0x10,0xF0,0xD2,0x1A,0xC6,0xB6, - - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFC, - 0xCC,0x22,0xD6,0xDF,0xB9,0x5C,0x6B,0x25,0xE4,0x9C, /* b */ - 0x0D,0x63,0x64,0xA4,0xE5,0x98,0x0C,0x39,0x3A,0xA2, - 0x16,0x68,0xD9,0x53, - 0xEE,0xA2,0xBA,0xE7,0xE1,0x49,0x78,0x42,0xF2,0xDE, /* x */ - 0x77,0x69,0xCF,0xE9,0xC9,0x89,0xC0,0x72,0xAD,0x69, - 0x6F,0x48,0x03,0x4A, - 0x65,0x74,0xd1,0x1d,0x69,0xb6,0xec,0x7a,0x67,0x2b, /* y */ - 0xb8,0x2a,0x08,0x3d,0xf2,0xf2,0xb0,0x84,0x7d,0xe9, - 0x70,0xb2,0xde,0x15, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */ - 0xFF,0xFE,0x5F,0xB1,0xA7,0x24,0xDC,0x80,0x41,0x86, - 0x48,0xD8,0xDD,0x31 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+24*6]; } - _EC_X9_62_PRIME_192V3 = { - { NID_X9_62_prime_field,20,24,1 }, - { 0xC4,0x69,0x68,0x44,0x35,0xDE,0xB3,0x78,0xC4,0xB6, /* seed */ - 0x5C,0xA9,0x59,0x1E,0x2A,0x57,0x63,0x05,0x9A,0x2E, - - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFC, - 0x22,0x12,0x3D,0xC2,0x39,0x5A,0x05,0xCA,0xA7,0x42, /* b */ - 0x3D,0xAE,0xCC,0xC9,0x47,0x60,0xA7,0xD4,0x62,0x25, - 0x6B,0xD5,0x69,0x16, - 0x7D,0x29,0x77,0x81,0x00,0xC6,0x5A,0x1D,0xA1,0x78, /* x */ - 0x37,0x16,0x58,0x8D,0xCE,0x2B,0x8B,0x4A,0xEE,0x8E, - 0x22,0x8F,0x18,0x96, - 0x38,0xa9,0x0f,0x22,0x63,0x73,0x37,0x33,0x4b,0x49, /* y */ - 0xdc,0xb6,0x6a,0x6d,0xc8,0xf9,0x97,0x8a,0xca,0x76, - 0x48,0xa9,0x43,0xb0, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */ - 0xFF,0xFF,0x7A,0x62,0xD0,0x31,0xC8,0x3F,0x42,0x94, - 0xF6,0x40,0xEC,0x13 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+30*6]; } - _EC_X9_62_PRIME_239V1 = { - { NID_X9_62_prime_field,20,30,1 }, - { 0xE4,0x3B,0xB4,0x60,0xF0,0xB8,0x0C,0xC0,0xC0,0xB0, /* seed */ - 0x75,0x79,0x8E,0x94,0x80,0x60,0xF8,0x32,0x1B,0x7D, - - 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */ - 0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00, - 0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF, - - 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */ - 0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00, - 0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFC, - - 0x6B,0x01,0x6C,0x3B,0xDC,0xF1,0x89,0x41,0xD0,0xD6, /* b */ - 0x54,0x92,0x14,0x75,0xCA,0x71,0xA9,0xDB,0x2F,0xB2, - 0x7D,0x1D,0x37,0x79,0x61,0x85,0xC2,0x94,0x2C,0x0A, - - 0x0F,0xFA,0x96,0x3C,0xDC,0xA8,0x81,0x6C,0xCC,0x33, /* x */ - 0xB8,0x64,0x2B,0xED,0xF9,0x05,0xC3,0xD3,0x58,0x57, - 0x3D,0x3F,0x27,0xFB,0xBD,0x3B,0x3C,0xB9,0xAA,0xAF, - - 0x7d,0xeb,0xe8,0xe4,0xe9,0x0a,0x5d,0xae,0x6e,0x40, /* y */ - 0x54,0xca,0x53,0x0b,0xa0,0x46,0x54,0xb3,0x68,0x18, - 0xce,0x22,0x6b,0x39,0xfc,0xcb,0x7b,0x02,0xf1,0xae, - - 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */ - 0xFF,0xFF,0x7F,0xFF,0xFF,0x9E,0x5E,0x9A,0x9F,0x5D, - 0x90,0x71,0xFB,0xD1,0x52,0x26,0x88,0x90,0x9D,0x0B } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+30*6]; } - _EC_X9_62_PRIME_239V2 = { - { NID_X9_62_prime_field,20,30,1 }, - { 0xE8,0xB4,0x01,0x16,0x04,0x09,0x53,0x03,0xCA,0x3B, /* seed */ - 0x80,0x99,0x98,0x2B,0xE0,0x9F,0xCB,0x9A,0xE6,0x16, - - 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */ - 0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00, - 0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF, - - 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */ - 0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00, - 0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFC, - - 0x61,0x7F,0xAB,0x68,0x32,0x57,0x6C,0xBB,0xFE,0xD5, /* b */ - 0x0D,0x99,0xF0,0x24,0x9C,0x3F,0xEE,0x58,0xB9,0x4B, - 0xA0,0x03,0x8C,0x7A,0xE8,0x4C,0x8C,0x83,0x2F,0x2C, - - 0x38,0xAF,0x09,0xD9,0x87,0x27,0x70,0x51,0x20,0xC9, /* x */ - 0x21,0xBB,0x5E,0x9E,0x26,0x29,0x6A,0x3C,0xDC,0xF2, - 0xF3,0x57,0x57,0xA0,0xEA,0xFD,0x87,0xB8,0x30,0xE7, - - 0x5b,0x01,0x25,0xe4,0xdb,0xea,0x0e,0xc7,0x20,0x6d, /* y */ - 0xa0,0xfc,0x01,0xd9,0xb0,0x81,0x32,0x9f,0xb5,0x55, - 0xde,0x6e,0xf4,0x60,0x23,0x7d,0xff,0x8b,0xe4,0xba, - - 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */ - 0xFF,0xFF,0x80,0x00,0x00,0xCF,0xA7,0xE8,0x59,0x43, - 0x77,0xD4,0x14,0xC0,0x38,0x21,0xBC,0x58,0x20,0x63 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+30*6]; } - _EC_X9_62_PRIME_239V3 = { - { NID_X9_62_prime_field,20,30,1 }, - { 0x7D,0x73,0x74,0x16,0x8F,0xFE,0x34,0x71,0xB6,0x0A, /* seed */ - 0x85,0x76,0x86,0xA1,0x94,0x75,0xD3,0xBF,0xA2,0xFF, - - 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */ - 0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00, - 0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF, - - 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */ - 0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00, - 0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFC, - - 0x25,0x57,0x05,0xFA,0x2A,0x30,0x66,0x54,0xB1,0xF4, /* b */ - 0xCB,0x03,0xD6,0xA7,0x50,0xA3,0x0C,0x25,0x01,0x02, - 0xD4,0x98,0x87,0x17,0xD9,0xBA,0x15,0xAB,0x6D,0x3E, - - 0x67,0x68,0xAE,0x8E,0x18,0xBB,0x92,0xCF,0xCF,0x00, /* x */ - 0x5C,0x94,0x9A,0xA2,0xC6,0xD9,0x48,0x53,0xD0,0xE6, - 0x60,0xBB,0xF8,0x54,0xB1,0xC9,0x50,0x5F,0xE9,0x5A, - - 0x16,0x07,0xe6,0x89,0x8f,0x39,0x0c,0x06,0xbc,0x1d, /* y */ - 0x55,0x2b,0xad,0x22,0x6f,0x3b,0x6f,0xcf,0xe4,0x8b, - 0x6e,0x81,0x84,0x99,0xaf,0x18,0xe3,0xed,0x6c,0xf3, - - 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */ - 0xFF,0xFF,0x7F,0xFF,0xFF,0x97,0x5D,0xEB,0x41,0xB3, - 0xA6,0x05,0x7C,0x3C,0x43,0x21,0x46,0x52,0x65,0x51 } - }; - - -static const struct { EC_CURVE_DATA h; unsigned char data[20+32*6]; } - _EC_X9_62_PRIME_256V1 = { - { NID_X9_62_prime_field,20,32,1 }, - { 0xC4,0x9D,0x36,0x08,0x86,0xE7,0x04,0x93,0x6A,0x66, /* seed */ - 0x78,0xE1,0x13,0x9D,0x26,0xB7,0x81,0x9F,0x7E,0x90, - - 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,0x00,0x00, /* a */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFC, - 0x5A,0xC6,0x35,0xD8,0xAA,0x3A,0x93,0xE7,0xB3,0xEB, /* b */ - 0xBD,0x55,0x76,0x98,0x86,0xBC,0x65,0x1D,0x06,0xB0, - 0xCC,0x53,0xB0,0xF6,0x3B,0xCE,0x3C,0x3E,0x27,0xD2, - 0x60,0x4B, - 0x6B,0x17,0xD1,0xF2,0xE1,0x2C,0x42,0x47,0xF8,0xBC, /* x */ - 0xE6,0xE5,0x63,0xA4,0x40,0xF2,0x77,0x03,0x7D,0x81, - 0x2D,0xEB,0x33,0xA0,0xF4,0xA1,0x39,0x45,0xD8,0x98, - 0xC2,0x96, - 0x4f,0xe3,0x42,0xe2,0xfe,0x1a,0x7f,0x9b,0x8e,0xe7, /* y */ - 0xeb,0x4a,0x7c,0x0f,0x9e,0x16,0x2b,0xce,0x33,0x57, - 0x6b,0x31,0x5e,0xce,0xcb,0xb6,0x40,0x68,0x37,0xbf, - 0x51,0xf5, - 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFF, /* order */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBC,0xE6,0xFA,0xAD, - 0xA7,0x17,0x9E,0x84,0xF3,0xB9,0xCA,0xC2,0xFC,0x63, - 0x25,0x51 } - }; +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 24 * 6]; +} _EC_X9_62_PRIME_192V2 = { + { + NID_X9_62_prime_field, 20, 24, 1 + }, + { + /* seed */ + 0x31, 0xA9, 0x2E, 0xE2, 0x02, 0x9F, 0xD1, 0x0D, 0x90, 0x1B, 0x11, 0x3E, + 0x99, 0x07, 0x10, 0xF0, 0xD2, 0x1A, 0xC6, 0xB6, + /* p */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* a */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + /* b */ + 0xCC, 0x22, 0xD6, 0xDF, 0xB9, 0x5C, 0x6B, 0x25, 0xE4, 0x9C, 0x0D, 0x63, + 0x64, 0xA4, 0xE5, 0x98, 0x0C, 0x39, 0x3A, 0xA2, 0x16, 0x68, 0xD9, 0x53, + /* x */ + 0xEE, 0xA2, 0xBA, 0xE7, 0xE1, 0x49, 0x78, 0x42, 0xF2, 0xDE, 0x77, 0x69, + 0xCF, 0xE9, 0xC9, 0x89, 0xC0, 0x72, 0xAD, 0x69, 0x6F, 0x48, 0x03, 0x4A, + /* y */ + 0x65, 0x74, 0xd1, 0x1d, 0x69, 0xb6, 0xec, 0x7a, 0x67, 0x2b, 0xb8, 0x2a, + 0x08, 0x3d, 0xf2, 0xf2, 0xb0, 0x84, 0x7d, 0xe9, 0x70, 0xb2, 0xde, 0x15, + /* order */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0x5F, 0xB1, 0xA7, 0x24, 0xDC, 0x80, 0x41, 0x86, 0x48, 0xD8, 0xDD, 0x31 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 24 * 6]; +} _EC_X9_62_PRIME_192V3 = { + { + NID_X9_62_prime_field, 20, 24, 1 + }, + { + /* seed */ + 0xC4, 0x69, 0x68, 0x44, 0x35, 0xDE, 0xB3, 0x78, 0xC4, 0xB6, 0x5C, 0xA9, + 0x59, 0x1E, 0x2A, 0x57, 0x63, 0x05, 0x9A, 0x2E, + /* p */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* a */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + /* b */ + 0x22, 0x12, 0x3D, 0xC2, 0x39, 0x5A, 0x05, 0xCA, 0xA7, 0x42, 0x3D, 0xAE, + 0xCC, 0xC9, 0x47, 0x60, 0xA7, 0xD4, 0x62, 0x25, 0x6B, 0xD5, 0x69, 0x16, + /* x */ + 0x7D, 0x29, 0x77, 0x81, 0x00, 0xC6, 0x5A, 0x1D, 0xA1, 0x78, 0x37, 0x16, + 0x58, 0x8D, 0xCE, 0x2B, 0x8B, 0x4A, 0xEE, 0x8E, 0x22, 0x8F, 0x18, 0x96, + /* y */ + 0x38, 0xa9, 0x0f, 0x22, 0x63, 0x73, 0x37, 0x33, 0x4b, 0x49, 0xdc, 0xb6, + 0x6a, 0x6d, 0xc8, 0xf9, 0x97, 0x8a, 0xca, 0x76, 0x48, 0xa9, 0x43, 0xb0, + /* order */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x7A, 0x62, 0xD0, 0x31, 0xC8, 0x3F, 0x42, 0x94, 0xF6, 0x40, 0xEC, 0x13 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 30 * 6]; +} _EC_X9_62_PRIME_239V1 = { + { + NID_X9_62_prime_field, 20, 30, 1 + }, + { + /* seed */ + 0xE4, 0x3B, 0xB4, 0x60, 0xF0, 0xB8, 0x0C, 0xC0, 0xC0, 0xB0, 0x75, 0x79, + 0x8E, 0x94, 0x80, 0x60, 0xF8, 0x32, 0x1B, 0x7D, + /* p */ + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* a */ + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + /* b */ + 0x6B, 0x01, 0x6C, 0x3B, 0xDC, 0xF1, 0x89, 0x41, 0xD0, 0xD6, 0x54, 0x92, + 0x14, 0x75, 0xCA, 0x71, 0xA9, 0xDB, 0x2F, 0xB2, 0x7D, 0x1D, 0x37, 0x79, + 0x61, 0x85, 0xC2, 0x94, 0x2C, 0x0A, + /* x */ + 0x0F, 0xFA, 0x96, 0x3C, 0xDC, 0xA8, 0x81, 0x6C, 0xCC, 0x33, 0xB8, 0x64, + 0x2B, 0xED, 0xF9, 0x05, 0xC3, 0xD3, 0x58, 0x57, 0x3D, 0x3F, 0x27, 0xFB, + 0xBD, 0x3B, 0x3C, 0xB9, 0xAA, 0xAF, + /* y */ + 0x7d, 0xeb, 0xe8, 0xe4, 0xe9, 0x0a, 0x5d, 0xae, 0x6e, 0x40, 0x54, 0xca, + 0x53, 0x0b, 0xa0, 0x46, 0x54, 0xb3, 0x68, 0x18, 0xce, 0x22, 0x6b, 0x39, + 0xfc, 0xcb, 0x7b, 0x02, 0xf1, 0xae, + /* order */ + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x7F, 0xFF, 0xFF, 0x9E, 0x5E, 0x9A, 0x9F, 0x5D, 0x90, 0x71, 0xFB, 0xD1, + 0x52, 0x26, 0x88, 0x90, 0x9D, 0x0B + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 30 * 6]; +} _EC_X9_62_PRIME_239V2 = { + { + NID_X9_62_prime_field, 20, 30, 1 + }, + { + /* seed */ + 0xE8, 0xB4, 0x01, 0x16, 0x04, 0x09, 0x53, 0x03, 0xCA, 0x3B, 0x80, 0x99, + 0x98, 0x2B, 0xE0, 0x9F, 0xCB, 0x9A, 0xE6, 0x16, + /* p */ + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* a */ + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + /* b */ + 0x61, 0x7F, 0xAB, 0x68, 0x32, 0x57, 0x6C, 0xBB, 0xFE, 0xD5, 0x0D, 0x99, + 0xF0, 0x24, 0x9C, 0x3F, 0xEE, 0x58, 0xB9, 0x4B, 0xA0, 0x03, 0x8C, 0x7A, + 0xE8, 0x4C, 0x8C, 0x83, 0x2F, 0x2C, + /* x */ + 0x38, 0xAF, 0x09, 0xD9, 0x87, 0x27, 0x70, 0x51, 0x20, 0xC9, 0x21, 0xBB, + 0x5E, 0x9E, 0x26, 0x29, 0x6A, 0x3C, 0xDC, 0xF2, 0xF3, 0x57, 0x57, 0xA0, + 0xEA, 0xFD, 0x87, 0xB8, 0x30, 0xE7, + /* y */ + 0x5b, 0x01, 0x25, 0xe4, 0xdb, 0xea, 0x0e, 0xc7, 0x20, 0x6d, 0xa0, 0xfc, + 0x01, 0xd9, 0xb0, 0x81, 0x32, 0x9f, 0xb5, 0x55, 0xde, 0x6e, 0xf4, 0x60, + 0x23, 0x7d, 0xff, 0x8b, 0xe4, 0xba, + /* order */ + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x80, 0x00, 0x00, 0xCF, 0xA7, 0xE8, 0x59, 0x43, 0x77, 0xD4, 0x14, 0xC0, + 0x38, 0x21, 0xBC, 0x58, 0x20, 0x63 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 30 * 6]; +} _EC_X9_62_PRIME_239V3 = { + { + NID_X9_62_prime_field, 20, 30, 1 + }, + { + /* seed */ + 0x7D, 0x73, 0x74, 0x16, 0x8F, 0xFE, 0x34, 0x71, 0xB6, 0x0A, 0x85, 0x76, + 0x86, 0xA1, 0x94, 0x75, 0xD3, 0xBF, 0xA2, 0xFF, + /* p */ + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* a */ + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + /* b */ + 0x25, 0x57, 0x05, 0xFA, 0x2A, 0x30, 0x66, 0x54, 0xB1, 0xF4, 0xCB, 0x03, + 0xD6, 0xA7, 0x50, 0xA3, 0x0C, 0x25, 0x01, 0x02, 0xD4, 0x98, 0x87, 0x17, + 0xD9, 0xBA, 0x15, 0xAB, 0x6D, 0x3E, + /* x */ + 0x67, 0x68, 0xAE, 0x8E, 0x18, 0xBB, 0x92, 0xCF, 0xCF, 0x00, 0x5C, 0x94, + 0x9A, 0xA2, 0xC6, 0xD9, 0x48, 0x53, 0xD0, 0xE6, 0x60, 0xBB, 0xF8, 0x54, + 0xB1, 0xC9, 0x50, 0x5F, 0xE9, 0x5A, + /* y */ + 0x16, 0x07, 0xe6, 0x89, 0x8f, 0x39, 0x0c, 0x06, 0xbc, 0x1d, 0x55, 0x2b, + 0xad, 0x22, 0x6f, 0x3b, 0x6f, 0xcf, 0xe4, 0x8b, 0x6e, 0x81, 0x84, 0x99, + 0xaf, 0x18, 0xe3, 0xed, 0x6c, 0xf3, + /* order */ + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x7F, 0xFF, 0xFF, 0x97, 0x5D, 0xEB, 0x41, 0xB3, 0xA6, 0x05, 0x7C, 0x3C, + 0x43, 0x21, 0x46, 0x52, 0x65, 0x51 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 32 * 6]; +} _EC_X9_62_PRIME_256V1 = { + { + NID_X9_62_prime_field, 20, 32, 1 + }, + { + /* seed */ + 0xC4, 0x9D, 0x36, 0x08, 0x86, 0xE7, 0x04, 0x93, 0x6A, 0x66, 0x78, 0xE1, + 0x13, 0x9D, 0x26, 0xB7, 0x81, 0x9F, 0x7E, 0x90, + /* p */ + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* a */ + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + /* b */ + 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55, + 0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6, + 0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B, + /* x */ + 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5, + 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0, + 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96, + /* y */ + 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, + 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, + 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5, + /* order */ + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84, + 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51 + } +}; /* the secg prime curves (minus the nist and x9.62 prime curves) */ -static const struct { EC_CURVE_DATA h; unsigned char data[20+14*6]; } - _EC_SECG_PRIME_112R1 = { - { NID_X9_62_prime_field,20,14,1 }, - { 0x00,0xF5,0x0B,0x02,0x8E,0x4D,0x69,0x6E,0x67,0x68, /* seed */ - 0x75,0x61,0x51,0x75,0x29,0x04,0x72,0x78,0x3F,0xB1, - - 0xDB,0x7C,0x2A,0xBF,0x62,0xE3,0x5E,0x66,0x80,0x76, /* p */ - 0xBE,0xAD,0x20,0x8B, - 0xDB,0x7C,0x2A,0xBF,0x62,0xE3,0x5E,0x66,0x80,0x76, /* a */ - 0xBE,0xAD,0x20,0x88, - 0x65,0x9E,0xF8,0xBA,0x04,0x39,0x16,0xEE,0xDE,0x89, /* b */ - 0x11,0x70,0x2B,0x22, - 0x09,0x48,0x72,0x39,0x99,0x5A,0x5E,0xE7,0x6B,0x55, /* x */ - 0xF9,0xC2,0xF0,0x98, - 0xa8,0x9c,0xe5,0xaf,0x87,0x24,0xc0,0xa2,0x3e,0x0e, /* y */ - 0x0f,0xf7,0x75,0x00, - 0xDB,0x7C,0x2A,0xBF,0x62,0xE3,0x5E,0x76,0x28,0xDF, /* order */ - 0xAC,0x65,0x61,0xC5 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+14*6]; } - _EC_SECG_PRIME_112R2 = { - { NID_X9_62_prime_field,20,14,4 }, - { 0x00,0x27,0x57,0xA1,0x11,0x4D,0x69,0x6E,0x67,0x68, /* seed */ - 0x75,0x61,0x51,0x75,0x53,0x16,0xC0,0x5E,0x0B,0xD4, - - 0xDB,0x7C,0x2A,0xBF,0x62,0xE3,0x5E,0x66,0x80,0x76, /* p */ - 0xBE,0xAD,0x20,0x8B, - 0x61,0x27,0xC2,0x4C,0x05,0xF3,0x8A,0x0A,0xAA,0xF6, /* a */ - 0x5C,0x0E,0xF0,0x2C, - 0x51,0xDE,0xF1,0x81,0x5D,0xB5,0xED,0x74,0xFC,0xC3, /* b */ - 0x4C,0x85,0xD7,0x09, - 0x4B,0xA3,0x0A,0xB5,0xE8,0x92,0xB4,0xE1,0x64,0x9D, /* x */ - 0xD0,0x92,0x86,0x43, - 0xad,0xcd,0x46,0xf5,0x88,0x2e,0x37,0x47,0xde,0xf3, /* y */ - 0x6e,0x95,0x6e,0x97, - 0x36,0xDF,0x0A,0xAF,0xD8,0xB8,0xD7,0x59,0x7C,0xA1, /* order */ - 0x05,0x20,0xD0,0x4B } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+16*6]; } - _EC_SECG_PRIME_128R1 = { - { NID_X9_62_prime_field,20,16,1 }, - { 0x00,0x0E,0x0D,0x4D,0x69,0x6E,0x67,0x68,0x75,0x61, /* seed */ - 0x51,0x75,0x0C,0xC0,0x3A,0x44,0x73,0xD0,0x36,0x79, - - 0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFC, - 0xE8,0x75,0x79,0xC1,0x10,0x79,0xF4,0x3D,0xD8,0x24, /* b */ - 0x99,0x3C,0x2C,0xEE,0x5E,0xD3, - 0x16,0x1F,0xF7,0x52,0x8B,0x89,0x9B,0x2D,0x0C,0x28, /* x */ - 0x60,0x7C,0xA5,0x2C,0x5B,0x86, - 0xcf,0x5a,0xc8,0x39,0x5b,0xaf,0xeb,0x13,0xc0,0x2d, /* y */ - 0xa2,0x92,0xdd,0xed,0x7a,0x83, - 0xFF,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x75,0xA3, /* order */ - 0x0D,0x1B,0x90,0x38,0xA1,0x15 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+16*6]; } - _EC_SECG_PRIME_128R2 = { - { NID_X9_62_prime_field,20,16,4 }, - { 0x00,0x4D,0x69,0x6E,0x67,0x68,0x75,0x61,0x51,0x75, /* seed */ - 0x12,0xD8,0xF0,0x34,0x31,0xFC,0xE6,0x3B,0x88,0xF4, - - 0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xD6,0x03,0x19,0x98,0xD1,0xB3,0xBB,0xFE,0xBF,0x59, /* a */ - 0xCC,0x9B,0xBF,0xF9,0xAE,0xE1, - 0x5E,0xEE,0xFC,0xA3,0x80,0xD0,0x29,0x19,0xDC,0x2C, /* b */ - 0x65,0x58,0xBB,0x6D,0x8A,0x5D, - 0x7B,0x6A,0xA5,0xD8,0x5E,0x57,0x29,0x83,0xE6,0xFB, /* x */ - 0x32,0xA7,0xCD,0xEB,0xC1,0x40, - 0x27,0xb6,0x91,0x6a,0x89,0x4d,0x3a,0xee,0x71,0x06, /* y */ - 0xfe,0x80,0x5f,0xc3,0x4b,0x44, - 0x3F,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xBE,0x00, /* order */ - 0x24,0x72,0x06,0x13,0xB5,0xA3 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[0+21*6]; } - _EC_SECG_PRIME_160K1 = { - { NID_X9_62_prime_field,0,21,1 }, - { /* no seed */ - 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xAC, - 0x73, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x07, - 0x00,0x3B,0x4C,0x38,0x2C,0xE3,0x7A,0xA1,0x92,0xA4, /* x */ - 0x01,0x9E,0x76,0x30,0x36,0xF4,0xF5,0xDD,0x4D,0x7E, - 0xBB, - 0x00,0x93,0x8c,0xf9,0x35,0x31,0x8f,0xdc,0xed,0x6b, /* y */ - 0xc2,0x82,0x86,0x53,0x17,0x33,0xc3,0xf0,0x3c,0x4f, - 0xee, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */ - 0x01,0xB8,0xFA,0x16,0xDF,0xAB,0x9A,0xCA,0x16,0xB6, - 0xB3 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+21*6]; } - _EC_SECG_PRIME_160R1 = { - { NID_X9_62_prime_field,20,21,1 }, - { 0x10,0x53,0xCD,0xE4,0x2C,0x14,0xD6,0x96,0xE6,0x76, /* seed */ - 0x87,0x56,0x15,0x17,0x53,0x3B,0xF3,0xF8,0x33,0x45, - - 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF, - 0xFF, - 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF, - 0xFC, - 0x00,0x1C,0x97,0xBE,0xFC,0x54,0xBD,0x7A,0x8B,0x65, /* b */ - 0xAC,0xF8,0x9F,0x81,0xD4,0xD4,0xAD,0xC5,0x65,0xFA, - 0x45, - 0x00,0x4A,0x96,0xB5,0x68,0x8E,0xF5,0x73,0x28,0x46, /* x */ - 0x64,0x69,0x89,0x68,0xC3,0x8B,0xB9,0x13,0xCB,0xFC, - 0x82, - 0x00,0x23,0xa6,0x28,0x55,0x31,0x68,0x94,0x7d,0x59, /* y */ - 0xdc,0xc9,0x12,0x04,0x23,0x51,0x37,0x7a,0xc5,0xfb, - 0x32, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */ - 0x01,0xF4,0xC8,0xF9,0x27,0xAE,0xD3,0xCA,0x75,0x22, - 0x57 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+21*6]; } - _EC_SECG_PRIME_160R2 = { - { NID_X9_62_prime_field,20,21,1 }, - { 0xB9,0x9B,0x99,0xB0,0x99,0xB3,0x23,0xE0,0x27,0x09, /* seed */ - 0xA4,0xD6,0x96,0xE6,0x76,0x87,0x56,0x15,0x17,0x51, - - 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xAC, - 0x73, - 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xAC, - 0x70, - 0x00,0xB4,0xE1,0x34,0xD3,0xFB,0x59,0xEB,0x8B,0xAB, /* b */ - 0x57,0x27,0x49,0x04,0x66,0x4D,0x5A,0xF5,0x03,0x88, - 0xBA, - 0x00,0x52,0xDC,0xB0,0x34,0x29,0x3A,0x11,0x7E,0x1F, /* x */ - 0x4F,0xF1,0x1B,0x30,0xF7,0x19,0x9D,0x31,0x44,0xCE, - 0x6D, - 0x00,0xfe,0xaf,0xfe,0xf2,0xe3,0x31,0xf2,0x96,0xe0, /* y */ - 0x71,0xfa,0x0d,0xf9,0x98,0x2c,0xfe,0xa7,0xd4,0x3f, - 0x2e, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */ - 0x00,0x35,0x1E,0xE7,0x86,0xA8,0x18,0xF3,0xA1,0xA1, - 0x6B } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[0+24*6]; } - _EC_SECG_PRIME_192K1 = { - { NID_X9_62_prime_field,0,24,1 }, - { /* no seed */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, - 0xFF,0xFF,0xEE,0x37, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x03, - 0xDB,0x4F,0xF1,0x0E,0xC0,0x57,0xE9,0xAE,0x26,0xB0, /* x */ - 0x7D,0x02,0x80,0xB7,0xF4,0x34,0x1D,0xA5,0xD1,0xB1, - 0xEA,0xE0,0x6C,0x7D, - 0x9b,0x2f,0x2f,0x6d,0x9c,0x56,0x28,0xa7,0x84,0x41, /* y */ - 0x63,0xd0,0x15,0xbe,0x86,0x34,0x40,0x82,0xaa,0x88, - 0xd9,0x5e,0x2f,0x9d, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */ - 0xFF,0xFE,0x26,0xF2,0xFC,0x17,0x0F,0x69,0x46,0x6A, - 0x74,0xDE,0xFD,0x8D } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[0+29*6]; } - _EC_SECG_PRIME_224K1 = { - { NID_X9_62_prime_field,0,29,1 }, - { /* no seed */ - 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xE5,0x6D, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05, - 0x00,0xA1,0x45,0x5B,0x33,0x4D,0xF0,0x99,0xDF,0x30, /* x */ - 0xFC,0x28,0xA1,0x69,0xA4,0x67,0xE9,0xE4,0x70,0x75, - 0xA9,0x0F,0x7E,0x65,0x0E,0xB6,0xB7,0xA4,0x5C, - 0x00,0x7e,0x08,0x9f,0xed,0x7f,0xba,0x34,0x42,0x82, /* y */ - 0xca,0xfb,0xd6,0xf7,0xe3,0x19,0xf7,0xc0,0xb0,0xbd, - 0x59,0xe2,0xca,0x4b,0xdb,0x55,0x6d,0x61,0xa5, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */ - 0x00,0x00,0x00,0x00,0x01,0xDC,0xE8,0xD2,0xEC,0x61, - 0x84,0xCA,0xF0,0xA9,0x71,0x76,0x9F,0xB1,0xF7 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[0+32*6]; } - _EC_SECG_PRIME_256K1 = { - { NID_X9_62_prime_field,0,32,1 }, - { /* no seed */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF, - 0xFC,0x2F, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x07, - 0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0, /* x */ - 0x62,0x95,0xCE,0x87,0x0B,0x07,0x02,0x9B,0xFC,0xDB, - 0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8, - 0x17,0x98, - 0x48,0x3a,0xda,0x77,0x26,0xa3,0xc4,0x65,0x5d,0xa4, /* y */ - 0xfb,0xfc,0x0e,0x11,0x08,0xa8,0xfd,0x17,0xb4,0x48, - 0xa6,0x85,0x54,0x19,0x9c,0x47,0xd0,0x8f,0xfb,0x10, - 0xd4,0xb8, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6, - 0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E,0x8C,0xD0,0x36, - 0x41,0x41 } - }; +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 14 * 6]; +} _EC_SECG_PRIME_112R1 = { + { + NID_X9_62_prime_field, 20, 14, 1 + }, + { + /* seed */ + 0x00, 0xF5, 0x0B, 0x02, 0x8E, 0x4D, 0x69, 0x6E, 0x67, 0x68, 0x75, 0x61, + 0x51, 0x75, 0x29, 0x04, 0x72, 0x78, 0x3F, 0xB1, + /* p */ + 0xDB, 0x7C, 0x2A, 0xBF, 0x62, 0xE3, 0x5E, 0x66, 0x80, 0x76, 0xBE, 0xAD, + 0x20, 0x8B, + /* a */ + 0xDB, 0x7C, 0x2A, 0xBF, 0x62, 0xE3, 0x5E, 0x66, 0x80, 0x76, 0xBE, 0xAD, + 0x20, 0x88, + /* b */ + 0x65, 0x9E, 0xF8, 0xBA, 0x04, 0x39, 0x16, 0xEE, 0xDE, 0x89, 0x11, 0x70, + 0x2B, 0x22, + /* x */ + 0x09, 0x48, 0x72, 0x39, 0x99, 0x5A, 0x5E, 0xE7, 0x6B, 0x55, 0xF9, 0xC2, + 0xF0, 0x98, + /* y */ + 0xa8, 0x9c, 0xe5, 0xaf, 0x87, 0x24, 0xc0, 0xa2, 0x3e, 0x0e, 0x0f, 0xf7, + 0x75, 0x00, + /* order */ + 0xDB, 0x7C, 0x2A, 0xBF, 0x62, 0xE3, 0x5E, 0x76, 0x28, 0xDF, 0xAC, 0x65, + 0x61, 0xC5 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 14 * 6]; +} _EC_SECG_PRIME_112R2 = { + { + NID_X9_62_prime_field, 20, 14, 4 + }, + { + /* seed */ + 0x00, 0x27, 0x57, 0xA1, 0x11, 0x4D, 0x69, 0x6E, 0x67, 0x68, 0x75, 0x61, + 0x51, 0x75, 0x53, 0x16, 0xC0, 0x5E, 0x0B, 0xD4, + /* p */ + 0xDB, 0x7C, 0x2A, 0xBF, 0x62, 0xE3, 0x5E, 0x66, 0x80, 0x76, 0xBE, 0xAD, + 0x20, 0x8B, + /* a */ + 0x61, 0x27, 0xC2, 0x4C, 0x05, 0xF3, 0x8A, 0x0A, 0xAA, 0xF6, 0x5C, 0x0E, + 0xF0, 0x2C, + /* b */ + 0x51, 0xDE, 0xF1, 0x81, 0x5D, 0xB5, 0xED, 0x74, 0xFC, 0xC3, 0x4C, 0x85, + 0xD7, 0x09, + /* x */ + 0x4B, 0xA3, 0x0A, 0xB5, 0xE8, 0x92, 0xB4, 0xE1, 0x64, 0x9D, 0xD0, 0x92, + 0x86, 0x43, + /* y */ + 0xad, 0xcd, 0x46, 0xf5, 0x88, 0x2e, 0x37, 0x47, 0xde, 0xf3, 0x6e, 0x95, + 0x6e, 0x97, + /* order */ + 0x36, 0xDF, 0x0A, 0xAF, 0xD8, 0xB8, 0xD7, 0x59, 0x7C, 0xA1, 0x05, 0x20, + 0xD0, 0x4B + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 16 * 6]; +} _EC_SECG_PRIME_128R1 = { + { + NID_X9_62_prime_field, 20, 16, 1 + }, + { + /* seed */ + 0x00, 0x0E, 0x0D, 0x4D, 0x69, 0x6E, 0x67, 0x68, 0x75, 0x61, 0x51, 0x75, + 0x0C, 0xC0, 0x3A, 0x44, 0x73, 0xD0, 0x36, 0x79, + /* p */ + 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + /* a */ + 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFC, + /* b */ + 0xE8, 0x75, 0x79, 0xC1, 0x10, 0x79, 0xF4, 0x3D, 0xD8, 0x24, 0x99, 0x3C, + 0x2C, 0xEE, 0x5E, 0xD3, + /* x */ + 0x16, 0x1F, 0xF7, 0x52, 0x8B, 0x89, 0x9B, 0x2D, 0x0C, 0x28, 0x60, 0x7C, + 0xA5, 0x2C, 0x5B, 0x86, + /* y */ + 0xcf, 0x5a, 0xc8, 0x39, 0x5b, 0xaf, 0xeb, 0x13, 0xc0, 0x2d, 0xa2, 0x92, + 0xdd, 0xed, 0x7a, 0x83, + /* order */ + 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x75, 0xA3, 0x0D, 0x1B, + 0x90, 0x38, 0xA1, 0x15 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 16 * 6]; +} _EC_SECG_PRIME_128R2 = { + { + NID_X9_62_prime_field, 20, 16, 4 + }, + { + /* seed */ + 0x00, 0x4D, 0x69, 0x6E, 0x67, 0x68, 0x75, 0x61, 0x51, 0x75, 0x12, 0xD8, + 0xF0, 0x34, 0x31, 0xFC, 0xE6, 0x3B, 0x88, 0xF4, + /* p */ + 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + /* a */ + 0xD6, 0x03, 0x19, 0x98, 0xD1, 0xB3, 0xBB, 0xFE, 0xBF, 0x59, 0xCC, 0x9B, + 0xBF, 0xF9, 0xAE, 0xE1, + /* b */ + 0x5E, 0xEE, 0xFC, 0xA3, 0x80, 0xD0, 0x29, 0x19, 0xDC, 0x2C, 0x65, 0x58, + 0xBB, 0x6D, 0x8A, 0x5D, + /* x */ + 0x7B, 0x6A, 0xA5, 0xD8, 0x5E, 0x57, 0x29, 0x83, 0xE6, 0xFB, 0x32, 0xA7, + 0xCD, 0xEB, 0xC1, 0x40, + /* y */ + 0x27, 0xb6, 0x91, 0x6a, 0x89, 0x4d, 0x3a, 0xee, 0x71, 0x06, 0xfe, 0x80, + 0x5f, 0xc3, 0x4b, 0x44, + /* order */ + 0x3F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xBE, 0x00, 0x24, 0x72, + 0x06, 0x13, 0xB5, 0xA3 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 21 * 6]; +} _EC_SECG_PRIME_160K1 = { + { + NID_X9_62_prime_field, 0, 21, 1 + }, + { + /* no seed */ + /* p */ + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xAC, 0x73, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + /* x */ + 0x00, 0x3B, 0x4C, 0x38, 0x2C, 0xE3, 0x7A, 0xA1, 0x92, 0xA4, 0x01, 0x9E, + 0x76, 0x30, 0x36, 0xF4, 0xF5, 0xDD, 0x4D, 0x7E, 0xBB, + /* y */ + 0x00, 0x93, 0x8c, 0xf9, 0x35, 0x31, 0x8f, 0xdc, 0xed, 0x6b, 0xc2, 0x82, + 0x86, 0x53, 0x17, 0x33, 0xc3, 0xf0, 0x3c, 0x4f, 0xee, + /* order */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xB8, + 0xFA, 0x16, 0xDF, 0xAB, 0x9A, 0xCA, 0x16, 0xB6, 0xB3 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 21 * 6]; +} _EC_SECG_PRIME_160R1 = { + { + NID_X9_62_prime_field, 20, 21, 1 + }, + { + /* seed */ + 0x10, 0x53, 0xCD, 0xE4, 0x2C, 0x14, 0xD6, 0x96, 0xE6, 0x76, 0x87, 0x56, + 0x15, 0x17, 0x53, 0x3B, 0xF3, 0xF8, 0x33, 0x45, + /* p */ + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, + /* a */ + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFC, + /* b */ + 0x00, 0x1C, 0x97, 0xBE, 0xFC, 0x54, 0xBD, 0x7A, 0x8B, 0x65, 0xAC, 0xF8, + 0x9F, 0x81, 0xD4, 0xD4, 0xAD, 0xC5, 0x65, 0xFA, 0x45, + /* x */ + 0x00, 0x4A, 0x96, 0xB5, 0x68, 0x8E, 0xF5, 0x73, 0x28, 0x46, 0x64, 0x69, + 0x89, 0x68, 0xC3, 0x8B, 0xB9, 0x13, 0xCB, 0xFC, 0x82, + /* y */ + 0x00, 0x23, 0xa6, 0x28, 0x55, 0x31, 0x68, 0x94, 0x7d, 0x59, 0xdc, 0xc9, + 0x12, 0x04, 0x23, 0x51, 0x37, 0x7a, 0xc5, 0xfb, 0x32, + /* order */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF4, + 0xC8, 0xF9, 0x27, 0xAE, 0xD3, 0xCA, 0x75, 0x22, 0x57 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 21 * 6]; +} _EC_SECG_PRIME_160R2 = { + { + NID_X9_62_prime_field, 20, 21, 1 + }, + { + /* seed */ + 0xB9, 0x9B, 0x99, 0xB0, 0x99, 0xB3, 0x23, 0xE0, 0x27, 0x09, 0xA4, 0xD6, + 0x96, 0xE6, 0x76, 0x87, 0x56, 0x15, 0x17, 0x51, + /* p */ + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xAC, 0x73, + /* a */ + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xAC, 0x70, + /* b */ + 0x00, 0xB4, 0xE1, 0x34, 0xD3, 0xFB, 0x59, 0xEB, 0x8B, 0xAB, 0x57, 0x27, + 0x49, 0x04, 0x66, 0x4D, 0x5A, 0xF5, 0x03, 0x88, 0xBA, + /* x */ + 0x00, 0x52, 0xDC, 0xB0, 0x34, 0x29, 0x3A, 0x11, 0x7E, 0x1F, 0x4F, 0xF1, + 0x1B, 0x30, 0xF7, 0x19, 0x9D, 0x31, 0x44, 0xCE, 0x6D, + /* y */ + 0x00, 0xfe, 0xaf, 0xfe, 0xf2, 0xe3, 0x31, 0xf2, 0x96, 0xe0, 0x71, 0xfa, + 0x0d, 0xf9, 0x98, 0x2c, 0xfe, 0xa7, 0xd4, 0x3f, 0x2e, + /* order */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, + 0x1E, 0xE7, 0x86, 0xA8, 0x18, 0xF3, 0xA1, 0xA1, 0x6B + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 24 * 6]; +} _EC_SECG_PRIME_192K1 = { + { + NID_X9_62_prime_field, 0, 24, 1 + }, + { + /* no seed */ + /* p */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xEE, 0x37, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + /* x */ + 0xDB, 0x4F, 0xF1, 0x0E, 0xC0, 0x57, 0xE9, 0xAE, 0x26, 0xB0, 0x7D, 0x02, + 0x80, 0xB7, 0xF4, 0x34, 0x1D, 0xA5, 0xD1, 0xB1, 0xEA, 0xE0, 0x6C, 0x7D, + /* y */ + 0x9b, 0x2f, 0x2f, 0x6d, 0x9c, 0x56, 0x28, 0xa7, 0x84, 0x41, 0x63, 0xd0, + 0x15, 0xbe, 0x86, 0x34, 0x40, 0x82, 0xaa, 0x88, 0xd9, 0x5e, 0x2f, 0x9d, + /* order */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0x26, 0xF2, 0xFC, 0x17, 0x0F, 0x69, 0x46, 0x6A, 0x74, 0xDE, 0xFD, 0x8D + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 29 * 6]; +} _EC_SECG_PRIME_224K1 = { + { + NID_X9_62_prime_field, 0, 29, 1 + }, + { + /* no seed */ + /* p */ + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFE, 0xFF, 0xFF, 0xE5, 0x6D, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, + /* x */ + 0x00, 0xA1, 0x45, 0x5B, 0x33, 0x4D, 0xF0, 0x99, 0xDF, 0x30, 0xFC, 0x28, + 0xA1, 0x69, 0xA4, 0x67, 0xE9, 0xE4, 0x70, 0x75, 0xA9, 0x0F, 0x7E, 0x65, + 0x0E, 0xB6, 0xB7, 0xA4, 0x5C, + /* y */ + 0x00, 0x7e, 0x08, 0x9f, 0xed, 0x7f, 0xba, 0x34, 0x42, 0x82, 0xca, 0xfb, + 0xd6, 0xf7, 0xe3, 0x19, 0xf7, 0xc0, 0xb0, 0xbd, 0x59, 0xe2, 0xca, 0x4b, + 0xdb, 0x55, 0x6d, 0x61, 0xa5, + /* order */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xDC, 0xE8, 0xD2, 0xEC, 0x61, 0x84, 0xCA, 0xF0, 0xA9, + 0x71, 0x76, 0x9F, 0xB1, 0xF7 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 32 * 6]; +} _EC_SECG_PRIME_256K1 = { + { + NID_X9_62_prime_field, 0, 32, 1 + }, + { + /* no seed */ + /* p */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x2F, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + /* x */ + 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, + 0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, + 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98, + /* y */ + 0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, 0xfb, 0xfc, + 0x0e, 0x11, 0x08, 0xa8, 0xfd, 0x17, 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19, + 0x9c, 0x47, 0xd0, 0x8f, 0xfb, 0x10, 0xd4, 0xb8, + /* order */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, + 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41 + } +}; /* some wap/wtls curves */ -static const struct { EC_CURVE_DATA h; unsigned char data[0+15*6]; } - _EC_WTLS_8 = { - { NID_X9_62_prime_field,0,15,1 }, - { /* no seed */ - 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */ - 0xFF,0xFF,0xFF,0xFD,0xE7, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */ - 0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */ - 0x00,0x00,0x00,0x00,0x03, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* x */ - 0x00,0x00,0x00,0x00,0x01, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* y */ - 0x00,0x00,0x00,0x00,0x02, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xEC,0xEA, /* order */ - 0x55,0x1A,0xD8,0x37,0xE9 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[0+21*6]; } - _EC_WTLS_9 = { - { NID_X9_62_prime_field,0,21,1 }, - { /* no seed */ - 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x80, - 0x8F, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x03, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* x */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* y */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x02, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */ - 0x01,0xCD,0xC9,0x8A,0xE0,0xE2,0xDE,0x57,0x4A,0xBF, - 0x33 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[0+28*6]; } - _EC_WTLS_12 = { - { NID_X9_62_prime_field,0,28,1 }, - { /* no seed */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, - 0xB4,0x05,0x0A,0x85,0x0C,0x04,0xB3,0xAB,0xF5,0x41, /* b */ - 0x32,0x56,0x50,0x44,0xB0,0xB7,0xD7,0xBF,0xD8,0xBA, - 0x27,0x0B,0x39,0x43,0x23,0x55,0xFF,0xB4, - 0xB7,0x0E,0x0C,0xBD,0x6B,0xB4,0xBF,0x7F,0x32,0x13, /* x */ - 0x90,0xB9,0x4A,0x03,0xC1,0xD3,0x56,0xC2,0x11,0x22, - 0x34,0x32,0x80,0xD6,0x11,0x5C,0x1D,0x21, - 0xbd,0x37,0x63,0x88,0xb5,0xf7,0x23,0xfb,0x4c,0x22, /* y */ - 0xdf,0xe6,0xcd,0x43,0x75,0xa0,0x5a,0x07,0x47,0x64, - 0x44,0xd5,0x81,0x99,0x85,0x00,0x7e,0x34, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */ - 0xFF,0xFF,0xFF,0xFF,0x16,0xA2,0xE0,0xB8,0xF0,0x3E, - 0x13,0xDD,0x29,0x45,0x5C,0x5C,0x2A,0x3D } - }; +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 15 * 6]; +} _EC_WTLS_8 = { + { + NID_X9_62_prime_field, 0, 15, 1 + }, + { + /* no seed */ + /* p */ + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFD, 0xE7, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, + /* x */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, + /* y */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, + /* order */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xEC, 0xEA, 0x55, 0x1A, + 0xD8, 0x37, 0xE9 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 21 * 6]; +} _EC_WTLS_9 = { + { + NID_X9_62_prime_field, 0, 21, 1 + }, + { + /* no seed */ + /* p */ + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x80, 0x8F, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + /* x */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* y */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + /* order */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xCD, + 0xC9, 0x8A, 0xE0, 0xE2, 0xDE, 0x57, 0x4A, 0xBF, 0x33 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 28 * 6]; +} _EC_WTLS_12 = { + { + NID_X9_62_prime_field, 0, 28, 1 + }, + { + /* no seed */ + /* p */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + /* a */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, + /* b */ + 0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56, + 0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39, 0x43, + 0x23, 0x55, 0xFF, 0xB4, + /* x */ + 0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9, + 0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6, + 0x11, 0x5C, 0x1D, 0x21, + /* y */ + 0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6, + 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, 0x44, 0xd5, 0x81, 0x99, + 0x85, 0x00, 0x7e, 0x34, + /* order */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45, + 0x5C, 0x5C, 0x2A, 0x3D + } +}; #ifndef OPENSSL_NO_EC2M /* characteristic two curves */ -static const struct { EC_CURVE_DATA h; unsigned char data[20+15*6]; } - _EC_SECG_CHAR2_113R1 = { - { NID_X9_62_characteristic_two_field,20,15,2 }, - { 0x10,0xE7,0x23,0xAB,0x14,0xD6,0x96,0xE6,0x76,0x87, /* seed */ - 0x56,0x15,0x17,0x56,0xFE,0xBF,0x8F,0xCB,0x49,0xA9, - - 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x02,0x01, - 0x00,0x30,0x88,0x25,0x0C,0xA6,0xE7,0xC7,0xFE,0x64, /* a */ - 0x9C,0xE8,0x58,0x20,0xF7, - 0x00,0xE8,0xBE,0xE4,0xD3,0xE2,0x26,0x07,0x44,0x18, /* b */ - 0x8B,0xE0,0xE9,0xC7,0x23, - 0x00,0x9D,0x73,0x61,0x6F,0x35,0xF4,0xAB,0x14,0x07, /* x */ - 0xD7,0x35,0x62,0xC1,0x0F, - 0x00,0xA5,0x28,0x30,0x27,0x79,0x58,0xEE,0x84,0xD1, /* y */ - 0x31,0x5E,0xD3,0x18,0x86, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD9,0xCC, /* order */ - 0xEC,0x8A,0x39,0xE5,0x6F } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+15*6]; } - _EC_SECG_CHAR2_113R2 = { - { NID_X9_62_characteristic_two_field,20,15,2 }, - { 0x10,0xC0,0xFB,0x15,0x76,0x08,0x60,0xDE,0xF1,0xEE, /* seed */ - 0xF4,0xD6,0x96,0xE6,0x76,0x87,0x56,0x15,0x17,0x5D, - - 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x02,0x01, - 0x00,0x68,0x99,0x18,0xDB,0xEC,0x7E,0x5A,0x0D,0xD6, /* a */ - 0xDF,0xC0,0xAA,0x55,0xC7, - 0x00,0x95,0xE9,0xA9,0xEC,0x9B,0x29,0x7B,0xD4,0xBF, /* b */ - 0x36,0xE0,0x59,0x18,0x4F, - 0x01,0xA5,0x7A,0x6A,0x7B,0x26,0xCA,0x5E,0xF5,0x2F, /* x */ - 0xCD,0xB8,0x16,0x47,0x97, - 0x00,0xB3,0xAD,0xC9,0x4E,0xD1,0xFE,0x67,0x4C,0x06, /* y */ - 0xE6,0x95,0xBA,0xBA,0x1D, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x08,0x78, /* order */ - 0x9B,0x24,0x96,0xAF,0x93 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+17*6]; } - _EC_SECG_CHAR2_131R1 = { - { NID_X9_62_characteristic_two_field,20,17,2 }, - { 0x4D,0x69,0x6E,0x67,0x68,0x75,0x61,0x51,0x75,0x98, /* seed */ - 0x5B,0xD3,0xAD,0xBA,0xDA,0x21,0xB4,0x3A,0x97,0xE2, - - 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x01,0x0D, - 0x07,0xA1,0x1B,0x09,0xA7,0x6B,0x56,0x21,0x44,0x41, /* a */ - 0x8F,0xF3,0xFF,0x8C,0x25,0x70,0xB8, - 0x02,0x17,0xC0,0x56,0x10,0x88,0x4B,0x63,0xB9,0xC6, /* b */ - 0xC7,0x29,0x16,0x78,0xF9,0xD3,0x41, - 0x00,0x81,0xBA,0xF9,0x1F,0xDF,0x98,0x33,0xC4,0x0F, /* x */ - 0x9C,0x18,0x13,0x43,0x63,0x83,0x99, - 0x07,0x8C,0x6E,0x7E,0xA3,0x8C,0x00,0x1F,0x73,0xC8, /* y */ - 0x13,0x4B,0x1B,0x4E,0xF9,0xE1,0x50, - 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x31, /* order */ - 0x23,0x95,0x3A,0x94,0x64,0xB5,0x4D } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+17*6]; } - _EC_SECG_CHAR2_131R2 = { - { NID_X9_62_characteristic_two_field,20,17,2 }, - { 0x98,0x5B,0xD3,0xAD,0xBA,0xD4,0xD6,0x96,0xE6,0x76, /* seed */ - 0x87,0x56,0x15,0x17,0x5A,0x21,0xB4,0x3A,0x97,0xE3, - - 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x01,0x0D, - 0x03,0xE5,0xA8,0x89,0x19,0xD7,0xCA,0xFC,0xBF,0x41, /* a */ - 0x5F,0x07,0xC2,0x17,0x65,0x73,0xB2, - 0x04,0xB8,0x26,0x6A,0x46,0xC5,0x56,0x57,0xAC,0x73, /* b */ - 0x4C,0xE3,0x8F,0x01,0x8F,0x21,0x92, - 0x03,0x56,0xDC,0xD8,0xF2,0xF9,0x50,0x31,0xAD,0x65, /* x */ - 0x2D,0x23,0x95,0x1B,0xB3,0x66,0xA8, - 0x06,0x48,0xF0,0x6D,0x86,0x79,0x40,0xA5,0x36,0x6D, /* y */ - 0x9E,0x26,0x5D,0xE9,0xEB,0x24,0x0F, - 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x69, /* order */ - 0x54,0xA2,0x33,0x04,0x9B,0xA9,0x8F } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[0+21*6]; } - _EC_NIST_CHAR2_163K = { - { NID_X9_62_characteristic_two_field,0,21,2 }, - { /* no seed */ - 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xC9, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01, - 0x02,0xFE,0x13,0xC0,0x53,0x7B,0xBC,0x11,0xAC,0xAA, /* x */ - 0x07,0xD7,0x93,0xDE,0x4E,0x6D,0x5E,0x5C,0x94,0xEE, - 0xE8, - 0x02,0x89,0x07,0x0F,0xB0,0x5D,0x38,0xFF,0x58,0x32, /* y */ - 0x1F,0x2E,0x80,0x05,0x36,0xD5,0x38,0xCC,0xDA,0xA3, - 0xD9, - 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */ - 0x02,0x01,0x08,0xA2,0xE0,0xCC,0x0D,0x99,0xF8,0xA5, - 0xEF } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[0+21*6]; } - _EC_SECG_CHAR2_163R1 = { - { NID_X9_62_characteristic_two_field,0,21,2 }, - { /* no seed */ -#if 0 -/* The algorithm used to derive the curve parameters from - * the seed used here is slightly different than the - * algorithm described in X9.62 . */ - 0x24,0xB7,0xB1,0x37,0xC8,0xA1,0x4D,0x69,0x6E,0x67, - 0x68,0x75,0x61,0x51,0x75,0x6F,0xD0,0xDA,0x2E,0x5C, -#endif - 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xC9, - 0x07,0xB6,0x88,0x2C,0xAA,0xEF,0xA8,0x4F,0x95,0x54, /* a */ - 0xFF,0x84,0x28,0xBD,0x88,0xE2,0x46,0xD2,0x78,0x2A, - 0xE2, - 0x07,0x13,0x61,0x2D,0xCD,0xDC,0xB4,0x0A,0xAB,0x94, /* b */ - 0x6B,0xDA,0x29,0xCA,0x91,0xF7,0x3A,0xF9,0x58,0xAF, - 0xD9, - 0x03,0x69,0x97,0x96,0x97,0xAB,0x43,0x89,0x77,0x89, /* x */ - 0x56,0x67,0x89,0x56,0x7F,0x78,0x7A,0x78,0x76,0xA6, - 0x54, - 0x00,0x43,0x5E,0xDB,0x42,0xEF,0xAF,0xB2,0x98,0x9D, /* y */ - 0x51,0xFE,0xFC,0xE3,0xC8,0x09,0x88,0xF4,0x1F,0xF8, - 0x83, - 0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */ - 0xFF,0x48,0xAA,0xB6,0x89,0xC2,0x9C,0xA7,0x10,0x27, - 0x9B } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[0+21*6]; } - _EC_NIST_CHAR2_163B = { - { NID_X9_62_characteristic_two_field,0,21,2 }, - { /* no seed */ -#if 0 -/* The seed here was used to created the curve parameters in normal - * basis representation (and not the polynomial representation used here) */ - 0x85,0xE2,0x5B,0xFE,0x5C,0x86,0x22,0x6C,0xDB,0x12, - 0x01,0x6F,0x75,0x53,0xF9,0xD0,0xE6,0x93,0xA2,0x68, -#endif - 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xC9, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01, - 0x02,0x0A,0x60,0x19,0x07,0xB8,0xC9,0x53,0xCA,0x14, /* b */ - 0x81,0xEB,0x10,0x51,0x2F,0x78,0x74,0x4A,0x32,0x05, - 0xFD, - 0x03,0xF0,0xEB,0xA1,0x62,0x86,0xA2,0xD5,0x7E,0xA0, /* x */ - 0x99,0x11,0x68,0xD4,0x99,0x46,0x37,0xE8,0x34,0x3E, - 0x36, - 0x00,0xD5,0x1F,0xBC,0x6C,0x71,0xA0,0x09,0x4F,0xA2, /* y */ - 0xCD,0xD5,0x45,0xB1,0x1C,0x5C,0x0C,0x79,0x73,0x24, - 0xF1, - 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */ - 0x02,0x92,0xFE,0x77,0xE7,0x0C,0x12,0xA4,0x23,0x4C, - 0x33 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+25*6]; } - _EC_SECG_CHAR2_193R1 = { - { NID_X9_62_characteristic_two_field,20,25,2 }, - { 0x10,0x3F,0xAE,0xC7,0x4D,0x69,0x6E,0x67,0x68,0x75, /* seed */ - 0x61,0x51,0x75,0x77,0x7F,0xC5,0xB1,0x91,0xEF,0x30, - - 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x80,0x01, - 0x00,0x17,0x85,0x8F,0xEB,0x7A,0x98,0x97,0x51,0x69, /* a */ - 0xE1,0x71,0xF7,0x7B,0x40,0x87,0xDE,0x09,0x8A,0xC8, - 0xA9,0x11,0xDF,0x7B,0x01, - 0x00,0xFD,0xFB,0x49,0xBF,0xE6,0xC3,0xA8,0x9F,0xAC, /* b */ - 0xAD,0xAA,0x7A,0x1E,0x5B,0xBC,0x7C,0xC1,0xC2,0xE5, - 0xD8,0x31,0x47,0x88,0x14, - 0x01,0xF4,0x81,0xBC,0x5F,0x0F,0xF8,0x4A,0x74,0xAD, /* x */ - 0x6C,0xDF,0x6F,0xDE,0xF4,0xBF,0x61,0x79,0x62,0x53, - 0x72,0xD8,0xC0,0xC5,0xE1, - 0x00,0x25,0xE3,0x99,0xF2,0x90,0x37,0x12,0xCC,0xF3, /* y */ - 0xEA,0x9E,0x3A,0x1A,0xD1,0x7F,0xB0,0xB3,0x20,0x1B, - 0x6A,0xF7,0xCE,0x1B,0x05, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */ - 0x00,0x00,0x00,0xC7,0xF3,0x4A,0x77,0x8F,0x44,0x3A, - 0xCC,0x92,0x0E,0xBA,0x49 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+25*6]; } - _EC_SECG_CHAR2_193R2 = { - { NID_X9_62_characteristic_two_field,20,25,2 }, - { 0x10,0xB7,0xB4,0xD6,0x96,0xE6,0x76,0x87,0x56,0x15, /* seed */ - 0x17,0x51,0x37,0xC8,0xA1,0x6F,0xD0,0xDA,0x22,0x11, - - 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x80,0x01, - 0x01,0x63,0xF3,0x5A,0x51,0x37,0xC2,0xCE,0x3E,0xA6, /* a */ - 0xED,0x86,0x67,0x19,0x0B,0x0B,0xC4,0x3E,0xCD,0x69, - 0x97,0x77,0x02,0x70,0x9B, - 0x00,0xC9,0xBB,0x9E,0x89,0x27,0xD4,0xD6,0x4C,0x37, /* b */ - 0x7E,0x2A,0xB2,0x85,0x6A,0x5B,0x16,0xE3,0xEF,0xB7, - 0xF6,0x1D,0x43,0x16,0xAE, - 0x00,0xD9,0xB6,0x7D,0x19,0x2E,0x03,0x67,0xC8,0x03, /* x */ - 0xF3,0x9E,0x1A,0x7E,0x82,0xCA,0x14,0xA6,0x51,0x35, - 0x0A,0xAE,0x61,0x7E,0x8F, - 0x01,0xCE,0x94,0x33,0x56,0x07,0xC3,0x04,0xAC,0x29, /* y */ - 0xE7,0xDE,0xFB,0xD9,0xCA,0x01,0xF5,0x96,0xF9,0x27, - 0x22,0x4C,0xDE,0xCF,0x6C, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */ - 0x00,0x00,0x01,0x5A,0xAB,0x56,0x1B,0x00,0x54,0x13, - 0xCC,0xD4,0xEE,0x99,0xD5 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[0+30*6]; } - _EC_NIST_CHAR2_233K = { - { NID_X9_62_characteristic_two_field,0,30,4 }, - { /* no seed */ - 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, - - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, - - 0x01,0x72,0x32,0xBA,0x85,0x3A,0x7E,0x73,0x1A,0xF1, /* x */ - 0x29,0xF2,0x2F,0xF4,0x14,0x95,0x63,0xA4,0x19,0xC2, - 0x6B,0xF5,0x0A,0x4C,0x9D,0x6E,0xEF,0xAD,0x61,0x26, - - 0x01,0xDB,0x53,0x7D,0xEC,0xE8,0x19,0xB7,0xF7,0x0F, /* y */ - 0x55,0x5A,0x67,0xC4,0x27,0xA8,0xCD,0x9B,0xF1,0x8A, - 0xEB,0x9B,0x56,0xE0,0xC1,0x10,0x56,0xFA,0xE6,0xA3, - - 0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */ - 0x00,0x00,0x00,0x00,0x00,0x06,0x9D,0x5B,0xB9,0x15, - 0xBC,0xD4,0x6E,0xFB,0x1A,0xD5,0xF1,0x73,0xAB,0xDF } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+30*6]; } - _EC_NIST_CHAR2_233B = { - { NID_X9_62_characteristic_two_field,20,30,2 }, - { 0x74,0xD5,0x9F,0xF0,0x7F,0x6B,0x41,0x3D,0x0E,0xA1, /* seed */ - 0x4B,0x34,0x4B,0x20,0xA2,0xDB,0x04,0x9B,0x50,0xC3, - - 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, - - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, - - 0x00,0x66,0x64,0x7E,0xDE,0x6C,0x33,0x2C,0x7F,0x8C, /* b */ - 0x09,0x23,0xBB,0x58,0x21,0x3B,0x33,0x3B,0x20,0xE9, - 0xCE,0x42,0x81,0xFE,0x11,0x5F,0x7D,0x8F,0x90,0xAD, - - 0x00,0xFA,0xC9,0xDF,0xCB,0xAC,0x83,0x13,0xBB,0x21, /* x */ - 0x39,0xF1,0xBB,0x75,0x5F,0xEF,0x65,0xBC,0x39,0x1F, - 0x8B,0x36,0xF8,0xF8,0xEB,0x73,0x71,0xFD,0x55,0x8B, - - 0x01,0x00,0x6A,0x08,0xA4,0x19,0x03,0x35,0x06,0x78, /* y */ - 0xE5,0x85,0x28,0xBE,0xBF,0x8A,0x0B,0xEF,0xF8,0x67, - 0xA7,0xCA,0x36,0x71,0x6F,0x7E,0x01,0xF8,0x10,0x52, - - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */ - 0x00,0x00,0x00,0x00,0x00,0x13,0xE9,0x74,0xE7,0x2F, - 0x8A,0x69,0x22,0x03,0x1D,0x26,0x03,0xCF,0xE0,0xD7 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[0+30*6]; } - _EC_SECG_CHAR2_239K1 = { - { NID_X9_62_characteristic_two_field,0,30,4 }, - { /* no seed */ - 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, - - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, - - 0x29,0xA0,0xB6,0xA8,0x87,0xA9,0x83,0xE9,0x73,0x09, /* x */ - 0x88,0xA6,0x87,0x27,0xA8,0xB2,0xD1,0x26,0xC4,0x4C, - 0xC2,0xCC,0x7B,0x2A,0x65,0x55,0x19,0x30,0x35,0xDC, - - 0x76,0x31,0x08,0x04,0xF1,0x2E,0x54,0x9B,0xDB,0x01, /* y */ - 0x1C,0x10,0x30,0x89,0xE7,0x35,0x10,0xAC,0xB2,0x75, - 0xFC,0x31,0x2A,0x5D,0xC6,0xB7,0x65,0x53,0xF0,0xCA, - - 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */ - 0x00,0x00,0x00,0x00,0x00,0x5A,0x79,0xFE,0xC6,0x7C, - 0xB6,0xE9,0x1F,0x1C,0x1D,0xA8,0x00,0xE4,0x78,0xA5 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[0+36*6]; } - _EC_NIST_CHAR2_283K = { - { NID_X9_62_characteristic_two_field,0,36,4 }, - { /* no seed */ - 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x10,0xA1, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x01, - 0x05,0x03,0x21,0x3F,0x78,0xCA,0x44,0x88,0x3F,0x1A, /* x */ - 0x3B,0x81,0x62,0xF1,0x88,0xE5,0x53,0xCD,0x26,0x5F, - 0x23,0xC1,0x56,0x7A,0x16,0x87,0x69,0x13,0xB0,0xC2, - 0xAC,0x24,0x58,0x49,0x28,0x36, - 0x01,0xCC,0xDA,0x38,0x0F,0x1C,0x9E,0x31,0x8D,0x90, /* y */ - 0xF9,0x5D,0x07,0xE5,0x42,0x6F,0xE8,0x7E,0x45,0xC0, - 0xE8,0x18,0x46,0x98,0xE4,0x59,0x62,0x36,0x4E,0x34, - 0x11,0x61,0x77,0xDD,0x22,0x59, - 0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE9,0xAE, - 0x2E,0xD0,0x75,0x77,0x26,0x5D,0xFF,0x7F,0x94,0x45, - 0x1E,0x06,0x1E,0x16,0x3C,0x61 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+36*6]; } - _EC_NIST_CHAR2_283B = { - { NID_X9_62_characteristic_two_field,20,36,2 }, - { 0x77,0xE2,0xB0,0x73,0x70,0xEB,0x0F,0x83,0x2A,0x6D, /* no seed */ - 0xD5,0xB6,0x2D,0xFC,0x88,0xCD,0x06,0xBB,0x84,0xBE, - - 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x10,0xA1, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x01, - 0x02,0x7B,0x68,0x0A,0xC8,0xB8,0x59,0x6D,0xA5,0xA4, /* b */ - 0xAF,0x8A,0x19,0xA0,0x30,0x3F,0xCA,0x97,0xFD,0x76, - 0x45,0x30,0x9F,0xA2,0xA5,0x81,0x48,0x5A,0xF6,0x26, - 0x3E,0x31,0x3B,0x79,0xA2,0xF5, - 0x05,0xF9,0x39,0x25,0x8D,0xB7,0xDD,0x90,0xE1,0x93, /* x */ - 0x4F,0x8C,0x70,0xB0,0xDF,0xEC,0x2E,0xED,0x25,0xB8, - 0x55,0x7E,0xAC,0x9C,0x80,0xE2,0xE1,0x98,0xF8,0xCD, - 0xBE,0xCD,0x86,0xB1,0x20,0x53, - 0x03,0x67,0x68,0x54,0xFE,0x24,0x14,0x1C,0xB9,0x8F, /* y */ - 0xE6,0xD4,0xB2,0x0D,0x02,0xB4,0x51,0x6F,0xF7,0x02, - 0x35,0x0E,0xDD,0xB0,0x82,0x67,0x79,0xC8,0x13,0xF0, - 0xDF,0x45,0xBE,0x81,0x12,0xF4, - 0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0x90, - 0x39,0x96,0x60,0xFC,0x93,0x8A,0x90,0x16,0x5B,0x04, - 0x2A,0x7C,0xEF,0xAD,0xB3,0x07 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[0+52*6]; } - _EC_NIST_CHAR2_409K = { - { NID_X9_62_characteristic_two_field,0,52,4 }, - { /* no seed */ - 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x01, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x01, - 0x00,0x60,0xF0,0x5F,0x65,0x8F,0x49,0xC1,0xAD,0x3A, /* x */ - 0xB1,0x89,0x0F,0x71,0x84,0x21,0x0E,0xFD,0x09,0x87, - 0xE3,0x07,0xC8,0x4C,0x27,0xAC,0xCF,0xB8,0xF9,0xF6, - 0x7C,0xC2,0xC4,0x60,0x18,0x9E,0xB5,0xAA,0xAA,0x62, - 0xEE,0x22,0x2E,0xB1,0xB3,0x55,0x40,0xCF,0xE9,0x02, - 0x37,0x46, - 0x01,0xE3,0x69,0x05,0x0B,0x7C,0x4E,0x42,0xAC,0xBA, /* y */ - 0x1D,0xAC,0xBF,0x04,0x29,0x9C,0x34,0x60,0x78,0x2F, - 0x91,0x8E,0xA4,0x27,0xE6,0x32,0x51,0x65,0xE9,0xEA, - 0x10,0xE3,0xDA,0x5F,0x6C,0x42,0xE9,0xC5,0x52,0x15, - 0xAA,0x9C,0xA2,0x7A,0x58,0x63,0xEC,0x48,0xD8,0xE0, - 0x28,0x6B, - 0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x5F,0x83,0xB2, - 0xD4,0xEA,0x20,0x40,0x0E,0xC4,0x55,0x7D,0x5E,0xD3, - 0xE3,0xE7,0xCA,0x5B,0x4B,0x5C,0x83,0xB8,0xE0,0x1E, - 0x5F,0xCF } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+52*6]; } - _EC_NIST_CHAR2_409B = { - { NID_X9_62_characteristic_two_field,20,52,2 }, - { 0x40,0x99,0xB5,0xA4,0x57,0xF9,0xD6,0x9F,0x79,0x21, /* seed */ - 0x3D,0x09,0x4C,0x4B,0xCD,0x4D,0x42,0x62,0x21,0x0B, - - 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x01, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x01, - 0x00,0x21,0xA5,0xC2,0xC8,0xEE,0x9F,0xEB,0x5C,0x4B, /* b */ - 0x9A,0x75,0x3B,0x7B,0x47,0x6B,0x7F,0xD6,0x42,0x2E, - 0xF1,0xF3,0xDD,0x67,0x47,0x61,0xFA,0x99,0xD6,0xAC, - 0x27,0xC8,0xA9,0xA1,0x97,0xB2,0x72,0x82,0x2F,0x6C, - 0xD5,0x7A,0x55,0xAA,0x4F,0x50,0xAE,0x31,0x7B,0x13, - 0x54,0x5F, - 0x01,0x5D,0x48,0x60,0xD0,0x88,0xDD,0xB3,0x49,0x6B, /* x */ - 0x0C,0x60,0x64,0x75,0x62,0x60,0x44,0x1C,0xDE,0x4A, - 0xF1,0x77,0x1D,0x4D,0xB0,0x1F,0xFE,0x5B,0x34,0xE5, - 0x97,0x03,0xDC,0x25,0x5A,0x86,0x8A,0x11,0x80,0x51, - 0x56,0x03,0xAE,0xAB,0x60,0x79,0x4E,0x54,0xBB,0x79, - 0x96,0xA7, - 0x00,0x61,0xB1,0xCF,0xAB,0x6B,0xE5,0xF3,0x2B,0xBF, /* y */ - 0xA7,0x83,0x24,0xED,0x10,0x6A,0x76,0x36,0xB9,0xC5, - 0xA7,0xBD,0x19,0x8D,0x01,0x58,0xAA,0x4F,0x54,0x88, - 0xD0,0x8F,0x38,0x51,0x4F,0x1F,0xDF,0x4B,0x4F,0x40, - 0xD2,0x18,0x1B,0x36,0x81,0xC3,0x64,0xBA,0x02,0x73, - 0xC7,0x06, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xE2,0xAA,0xD6, - 0xA6,0x12,0xF3,0x33,0x07,0xBE,0x5F,0xA4,0x7C,0x3C, - 0x9E,0x05,0x2F,0x83,0x81,0x64,0xCD,0x37,0xD9,0xA2, - 0x11,0x73 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[0+72*6]; } - _EC_NIST_CHAR2_571K = { - { NID_X9_62_characteristic_two_field,0,72,4 }, - { /* no seed */ - 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x04,0x25, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x01, - 0x02,0x6E,0xB7,0xA8,0x59,0x92,0x3F,0xBC,0x82,0x18, /* x */ - 0x96,0x31,0xF8,0x10,0x3F,0xE4,0xAC,0x9C,0xA2,0x97, - 0x00,0x12,0xD5,0xD4,0x60,0x24,0x80,0x48,0x01,0x84, - 0x1C,0xA4,0x43,0x70,0x95,0x84,0x93,0xB2,0x05,0xE6, - 0x47,0xDA,0x30,0x4D,0xB4,0xCE,0xB0,0x8C,0xBB,0xD1, - 0xBA,0x39,0x49,0x47,0x76,0xFB,0x98,0x8B,0x47,0x17, - 0x4D,0xCA,0x88,0xC7,0xE2,0x94,0x52,0x83,0xA0,0x1C, - 0x89,0x72, - 0x03,0x49,0xDC,0x80,0x7F,0x4F,0xBF,0x37,0x4F,0x4A, /* y */ - 0xEA,0xDE,0x3B,0xCA,0x95,0x31,0x4D,0xD5,0x8C,0xEC, - 0x9F,0x30,0x7A,0x54,0xFF,0xC6,0x1E,0xFC,0x00,0x6D, - 0x8A,0x2C,0x9D,0x49,0x79,0xC0,0xAC,0x44,0xAE,0xA7, - 0x4F,0xBE,0xBB,0xB9,0xF7,0x72,0xAE,0xDC,0xB6,0x20, - 0xB0,0x1A,0x7B,0xA7,0xAF,0x1B,0x32,0x04,0x30,0xC8, - 0x59,0x19,0x84,0xF6,0x01,0xCD,0x4C,0x14,0x3E,0xF1, - 0xC7,0xA3, - 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x18,0x50,0xE1, - 0xF1,0x9A,0x63,0xE4,0xB3,0x91,0xA8,0xDB,0x91,0x7F, - 0x41,0x38,0xB6,0x30,0xD8,0x4B,0xE5,0xD6,0x39,0x38, - 0x1E,0x91,0xDE,0xB4,0x5C,0xFE,0x77,0x8F,0x63,0x7C, - 0x10,0x01 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+72*6]; } - _EC_NIST_CHAR2_571B = { - { NID_X9_62_characteristic_two_field,20,72,2 }, - { 0x2A,0xA0,0x58,0xF7,0x3A,0x0E,0x33,0xAB,0x48,0x6B, /* seed */ - 0x0F,0x61,0x04,0x10,0xC5,0x3A,0x7F,0x13,0x23,0x10, - - 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x04,0x25, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x01, - 0x02,0xF4,0x0E,0x7E,0x22,0x21,0xF2,0x95,0xDE,0x29, /* b */ - 0x71,0x17,0xB7,0xF3,0xD6,0x2F,0x5C,0x6A,0x97,0xFF, - 0xCB,0x8C,0xEF,0xF1,0xCD,0x6B,0xA8,0xCE,0x4A,0x9A, - 0x18,0xAD,0x84,0xFF,0xAB,0xBD,0x8E,0xFA,0x59,0x33, - 0x2B,0xE7,0xAD,0x67,0x56,0xA6,0x6E,0x29,0x4A,0xFD, - 0x18,0x5A,0x78,0xFF,0x12,0xAA,0x52,0x0E,0x4D,0xE7, - 0x39,0xBA,0xCA,0x0C,0x7F,0xFE,0xFF,0x7F,0x29,0x55, - 0x72,0x7A, - 0x03,0x03,0x00,0x1D,0x34,0xB8,0x56,0x29,0x6C,0x16, /* x */ - 0xC0,0xD4,0x0D,0x3C,0xD7,0x75,0x0A,0x93,0xD1,0xD2, - 0x95,0x5F,0xA8,0x0A,0xA5,0xF4,0x0F,0xC8,0xDB,0x7B, - 0x2A,0xBD,0xBD,0xE5,0x39,0x50,0xF4,0xC0,0xD2,0x93, - 0xCD,0xD7,0x11,0xA3,0x5B,0x67,0xFB,0x14,0x99,0xAE, - 0x60,0x03,0x86,0x14,0xF1,0x39,0x4A,0xBF,0xA3,0xB4, - 0xC8,0x50,0xD9,0x27,0xE1,0xE7,0x76,0x9C,0x8E,0xEC, - 0x2D,0x19, - 0x03,0x7B,0xF2,0x73,0x42,0xDA,0x63,0x9B,0x6D,0xCC, /* y */ - 0xFF,0xFE,0xB7,0x3D,0x69,0xD7,0x8C,0x6C,0x27,0xA6, - 0x00,0x9C,0xBB,0xCA,0x19,0x80,0xF8,0x53,0x39,0x21, - 0xE8,0xA6,0x84,0x42,0x3E,0x43,0xBA,0xB0,0x8A,0x57, - 0x62,0x91,0xAF,0x8F,0x46,0x1B,0xB2,0xA8,0xB3,0x53, - 0x1D,0x2F,0x04,0x85,0xC1,0x9B,0x16,0xE2,0xF1,0x51, - 0x6E,0x23,0xDD,0x3C,0x1A,0x48,0x27,0xAF,0x1B,0x8A, - 0xC1,0x5B, - 0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x61,0xCE,0x18, - 0xFF,0x55,0x98,0x73,0x08,0x05,0x9B,0x18,0x68,0x23, - 0x85,0x1E,0xC7,0xDD,0x9C,0xA1,0x16,0x1D,0xE9,0x3D, - 0x51,0x74,0xD6,0x6E,0x83,0x82,0xE9,0xBB,0x2F,0xE8, - 0x4E,0x47 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+21*6]; } - _EC_X9_62_CHAR2_163V1 = { - { NID_X9_62_characteristic_two_field,20,21,2 }, - { 0xD2,0xC0,0xFB,0x15,0x76,0x08,0x60,0xDE,0xF1,0xEE, - 0xF4,0xD6,0x96,0xE6,0x76,0x87,0x56,0x15,0x17,0x54, /* seed */ - - 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, - 0x07, - 0x07,0x25,0x46,0xB5,0x43,0x52,0x34,0xA4,0x22,0xE0, /* a */ - 0x78,0x96,0x75,0xF4,0x32,0xC8,0x94,0x35,0xDE,0x52, - 0x42, - 0x00,0xC9,0x51,0x7D,0x06,0xD5,0x24,0x0D,0x3C,0xFF, /* b */ - 0x38,0xC7,0x4B,0x20,0xB6,0xCD,0x4D,0x6F,0x9D,0xD4, - 0xD9, - 0x07,0xAF,0x69,0x98,0x95,0x46,0x10,0x3D,0x79,0x32, /* x */ - 0x9F,0xCC,0x3D,0x74,0x88,0x0F,0x33,0xBB,0xE8,0x03, - 0xCB, - 0x01,0xEC,0x23,0x21,0x1B,0x59,0x66,0xAD,0xEA,0x1D, /* y */ - 0x3F,0x87,0xF7,0xEA,0x58,0x48,0xAE,0xF0,0xB7,0xCA, - 0x9F, - 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */ - 0x01,0xE6,0x0F,0xC8,0x82,0x1C,0xC7,0x4D,0xAE,0xAF, - 0xC1 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+21*6]; } - _EC_X9_62_CHAR2_163V2 = { - { NID_X9_62_characteristic_two_field,20,21,2 }, - { 0x53,0x81,0x4C,0x05,0x0D,0x44,0xD6,0x96,0xE6,0x76, /* seed */ - 0x87,0x56,0x15,0x17,0x58,0x0C,0xA4,0xE2,0x9F,0xFD, - - 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, - 0x07, - 0x01,0x08,0xB3,0x9E,0x77,0xC4,0xB1,0x08,0xBE,0xD9, /* a */ - 0x81,0xED,0x0E,0x89,0x0E,0x11,0x7C,0x51,0x1C,0xF0, - 0x72, - 0x06,0x67,0xAC,0xEB,0x38,0xAF,0x4E,0x48,0x8C,0x40, /* b */ - 0x74,0x33,0xFF,0xAE,0x4F,0x1C,0x81,0x16,0x38,0xDF, - 0x20, - 0x00,0x24,0x26,0x6E,0x4E,0xB5,0x10,0x6D,0x0A,0x96, /* x */ - 0x4D,0x92,0xC4,0x86,0x0E,0x26,0x71,0xDB,0x9B,0x6C, - 0xC5, - 0x07,0x9F,0x68,0x4D,0xDF,0x66,0x84,0xC5,0xCD,0x25, /* y */ - 0x8B,0x38,0x90,0x02,0x1B,0x23,0x86,0xDF,0xD1,0x9F, - 0xC5, - 0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */ - 0xFD,0xF6,0x4D,0xE1,0x15,0x1A,0xDB,0xB7,0x8F,0x10, - 0xA7 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+21*6]; } - _EC_X9_62_CHAR2_163V3 = { - { NID_X9_62_characteristic_two_field,20,21,2 }, - { 0x50,0xCB,0xF1,0xD9,0x5C,0xA9,0x4D,0x69,0x6E,0x67, /* seed */ - 0x68,0x75,0x61,0x51,0x75,0xF1,0x6A,0x36,0xA3,0xB8, - - 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, - 0x07, - 0x07,0xA5,0x26,0xC6,0x3D,0x3E,0x25,0xA2,0x56,0xA0, /* a */ - 0x07,0x69,0x9F,0x54,0x47,0xE3,0x2A,0xE4,0x56,0xB5, - 0x0E, - 0x03,0xF7,0x06,0x17,0x98,0xEB,0x99,0xE2,0x38,0xFD, /* b */ - 0x6F,0x1B,0xF9,0x5B,0x48,0xFE,0xEB,0x48,0x54,0x25, - 0x2B, - 0x02,0xF9,0xF8,0x7B,0x7C,0x57,0x4D,0x0B,0xDE,0xCF, /* x */ - 0x8A,0x22,0xE6,0x52,0x47,0x75,0xF9,0x8C,0xDE,0xBD, - 0xCB, - 0x05,0xB9,0x35,0x59,0x0C,0x15,0x5E,0x17,0xEA,0x48, /* y */ - 0xEB,0x3F,0xF3,0x71,0x8B,0x89,0x3D,0xF5,0x9A,0x05, - 0xD0, - 0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */ - 0xFE,0x1A,0xEE,0x14,0x0F,0x11,0x0A,0xFF,0x96,0x13, - 0x09 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[0+23*6]; } - _EC_X9_62_CHAR2_176V1 = { - { NID_X9_62_characteristic_two_field,0,23,0xFF6E }, - { /* no seed */ - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00, - 0x00,0x00,0x07, - 0x00,0xE4,0xE6,0xDB,0x29,0x95,0x06,0x5C,0x40,0x7D, /* a */ - 0x9D,0x39,0xB8,0xD0,0x96,0x7B,0x96,0x70,0x4B,0xA8, - 0xE9,0xC9,0x0B, - 0x00,0x5D,0xDA,0x47,0x0A,0xBE,0x64,0x14,0xDE,0x8E, /* b */ - 0xC1,0x33,0xAE,0x28,0xE9,0xBB,0xD7,0xFC,0xEC,0x0A, - 0xE0,0xFF,0xF2, - 0x00,0x8D,0x16,0xC2,0x86,0x67,0x98,0xB6,0x00,0xF9, /* x */ - 0xF0,0x8B,0xB4,0xA8,0xE8,0x60,0xF3,0x29,0x8C,0xE0, - 0x4A,0x57,0x98, - 0x00,0x6F,0xA4,0x53,0x9C,0x2D,0xAD,0xDD,0xD6,0xBA, /* y */ - 0xB5,0x16,0x7D,0x61,0xB4,0x36,0xE1,0xD9,0x2B,0xB1, - 0x6A,0x56,0x2C, - 0x00,0x00,0x01,0x00,0x92,0x53,0x73,0x97,0xEC,0xA4, /* order */ - 0xF6,0x14,0x57,0x99,0xD6,0x2B,0x0A,0x19,0xCE,0x06, - 0xFE,0x26,0xAD } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+24*6]; } - _EC_X9_62_CHAR2_191V1 = { - { NID_X9_62_characteristic_two_field,20,24,2 }, - { 0x4E,0x13,0xCA,0x54,0x27,0x44,0xD6,0x96,0xE6,0x76, /* seed */ - 0x87,0x56,0x15,0x17,0x55,0x2F,0x27,0x9A,0x8C,0x84, - - 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x02,0x01, - 0x28,0x66,0x53,0x7B,0x67,0x67,0x52,0x63,0x6A,0x68, /* a */ - 0xF5,0x65,0x54,0xE1,0x26,0x40,0x27,0x6B,0x64,0x9E, - 0xF7,0x52,0x62,0x67, - 0x2E,0x45,0xEF,0x57,0x1F,0x00,0x78,0x6F,0x67,0xB0, /* b */ - 0x08,0x1B,0x94,0x95,0xA3,0xD9,0x54,0x62,0xF5,0xDE, - 0x0A,0xA1,0x85,0xEC, - 0x36,0xB3,0xDA,0xF8,0xA2,0x32,0x06,0xF9,0xC4,0xF2, /* x */ - 0x99,0xD7,0xB2,0x1A,0x9C,0x36,0x91,0x37,0xF2,0xC8, - 0x4A,0xE1,0xAA,0x0D, - 0x76,0x5B,0xE7,0x34,0x33,0xB3,0xF9,0x5E,0x33,0x29, /* y */ - 0x32,0xE7,0x0E,0xA2,0x45,0xCA,0x24,0x18,0xEA,0x0E, - 0xF9,0x80,0x18,0xFB, - 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */ - 0x00,0x00,0x04,0xA2,0x0E,0x90,0xC3,0x90,0x67,0xC8, - 0x93,0xBB,0xB9,0xA5 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+24*6]; } - _EC_X9_62_CHAR2_191V2 = { - { NID_X9_62_characteristic_two_field,20,24,4 }, - { 0x08,0x71,0xEF,0x2F,0xEF,0x24,0xD6,0x96,0xE6,0x76, /* seed */ - 0x87,0x56,0x15,0x17,0x58,0xBE,0xE0,0xD9,0x5C,0x15, - - 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x02,0x01, - 0x40,0x10,0x28,0x77,0x4D,0x77,0x77,0xC7,0xB7,0x66, /* a */ - 0x6D,0x13,0x66,0xEA,0x43,0x20,0x71,0x27,0x4F,0x89, - 0xFF,0x01,0xE7,0x18, - 0x06,0x20,0x04,0x8D,0x28,0xBC,0xBD,0x03,0xB6,0x24, /* b */ - 0x9C,0x99,0x18,0x2B,0x7C,0x8C,0xD1,0x97,0x00,0xC3, - 0x62,0xC4,0x6A,0x01, - 0x38,0x09,0xB2,0xB7,0xCC,0x1B,0x28,0xCC,0x5A,0x87, /* x */ - 0x92,0x6A,0xAD,0x83,0xFD,0x28,0x78,0x9E,0x81,0xE2, - 0xC9,0xE3,0xBF,0x10, - 0x17,0x43,0x43,0x86,0x62,0x6D,0x14,0xF3,0xDB,0xF0, /* y */ - 0x17,0x60,0xD9,0x21,0x3A,0x3E,0x1C,0xF3,0x7A,0xEC, - 0x43,0x7D,0x66,0x8A, - 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */ - 0x00,0x00,0x50,0x50,0x8C,0xB8,0x9F,0x65,0x28,0x24, - 0xE0,0x6B,0x81,0x73 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+24*6]; } - _EC_X9_62_CHAR2_191V3 = { - { NID_X9_62_characteristic_two_field,20,24,6 }, - { 0xE0,0x53,0x51,0x2D,0xC6,0x84,0xD6,0x96,0xE6,0x76, /* seed */ - 0x87,0x56,0x15,0x17,0x50,0x67,0xAE,0x78,0x6D,0x1F, - - 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x02,0x01, - 0x6C,0x01,0x07,0x47,0x56,0x09,0x91,0x22,0x22,0x10, /* a */ - 0x56,0x91,0x1C,0x77,0xD7,0x7E,0x77,0xA7,0x77,0xE7, - 0xE7,0xE7,0x7F,0xCB, - 0x71,0xFE,0x1A,0xF9,0x26,0xCF,0x84,0x79,0x89,0xEF, /* b */ - 0xEF,0x8D,0xB4,0x59,0xF6,0x63,0x94,0xD9,0x0F,0x32, - 0xAD,0x3F,0x15,0xE8, - 0x37,0x5D,0x4C,0xE2,0x4F,0xDE,0x43,0x44,0x89,0xDE, /* x */ - 0x87,0x46,0xE7,0x17,0x86,0x01,0x50,0x09,0xE6,0x6E, - 0x38,0xA9,0x26,0xDD, - 0x54,0x5A,0x39,0x17,0x61,0x96,0x57,0x5D,0x98,0x59, /* y */ - 0x99,0x36,0x6E,0x6A,0xD3,0x4C,0xE0,0xA7,0x7C,0xD7, - 0x12,0x7B,0x06,0xBE, - 0x15,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, /* order */ - 0x55,0x55,0x61,0x0C,0x0B,0x19,0x68,0x12,0xBF,0xB6, - 0x28,0x8A,0x3E,0xA3 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[0+27*6]; } - _EC_X9_62_CHAR2_208W1 = { - { NID_X9_62_characteristic_two_field,0,27,0xFE48 }, - { /* no seed */ - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x07, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0xC8,0x61,0x9E,0xD4,0x5A,0x62,0xE6,0x21,0x2E, /* b */ - 0x11,0x60,0x34,0x9E,0x2B,0xFA,0x84,0x44,0x39,0xFA, - 0xFC,0x2A,0x3F,0xD1,0x63,0x8F,0x9E, - 0x00,0x89,0xFD,0xFB,0xE4,0xAB,0xE1,0x93,0xDF,0x95, /* x */ - 0x59,0xEC,0xF0,0x7A,0xC0,0xCE,0x78,0x55,0x4E,0x27, - 0x84,0xEB,0x8C,0x1E,0xD1,0xA5,0x7A, - 0x00,0x0F,0x55,0xB5,0x1A,0x06,0xE7,0x8E,0x9A,0xC3, /* y */ - 0x8A,0x03,0x5F,0xF5,0x20,0xD8,0xB0,0x17,0x81,0xBE, - 0xB1,0xA6,0xBB,0x08,0x61,0x7D,0xE3, - 0x00,0x00,0x01,0x01,0xBA,0xF9,0x5C,0x97,0x23,0xC5, /* order */ - 0x7B,0x6C,0x21,0xDA,0x2E,0xFF,0x2D,0x5E,0xD5,0x88, - 0xBD,0xD5,0x71,0x7E,0x21,0x2F,0x9D } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+30*6]; } - _EC_X9_62_CHAR2_239V1 = { - { NID_X9_62_characteristic_two_field,20,30,4 }, - { 0xD3,0x4B,0x9A,0x4D,0x69,0x6E,0x67,0x68,0x75,0x61, /* seed */ - 0x51,0x75,0xCA,0x71,0xB9,0x20,0xBF,0xEF,0xB0,0x5D, - - 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01, - - 0x32,0x01,0x08,0x57,0x07,0x7C,0x54,0x31,0x12,0x3A, /* a */ - 0x46,0xB8,0x08,0x90,0x67,0x56,0xF5,0x43,0x42,0x3E, - 0x8D,0x27,0x87,0x75,0x78,0x12,0x57,0x78,0xAC,0x76, - - 0x79,0x04,0x08,0xF2,0xEE,0xDA,0xF3,0x92,0xB0,0x12, /* b */ - 0xED,0xEF,0xB3,0x39,0x2F,0x30,0xF4,0x32,0x7C,0x0C, - 0xA3,0xF3,0x1F,0xC3,0x83,0xC4,0x22,0xAA,0x8C,0x16, - - 0x57,0x92,0x70,0x98,0xFA,0x93,0x2E,0x7C,0x0A,0x96, /* x */ - 0xD3,0xFD,0x5B,0x70,0x6E,0xF7,0xE5,0xF5,0xC1,0x56, - 0xE1,0x6B,0x7E,0x7C,0x86,0x03,0x85,0x52,0xE9,0x1D, - - 0x61,0xD8,0xEE,0x50,0x77,0xC3,0x3F,0xEC,0xF6,0xF1, /* y */ - 0xA1,0x6B,0x26,0x8D,0xE4,0x69,0xC3,0xC7,0x74,0x4E, - 0xA9,0xA9,0x71,0x64,0x9F,0xC7,0xA9,0x61,0x63,0x05, - - 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */ - 0x00,0x00,0x00,0x00,0x00,0x0F,0x4D,0x42,0xFF,0xE1, - 0x49,0x2A,0x49,0x93,0xF1,0xCA,0xD6,0x66,0xE4,0x47 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+30*6]; } - _EC_X9_62_CHAR2_239V2 = { - { NID_X9_62_characteristic_two_field,20,30,6 }, - { 0x2A,0xA6,0x98,0x2F,0xDF,0xA4,0xD6,0x96,0xE6,0x76, /* seed */ - 0x87,0x56,0x15,0x17,0x5D,0x26,0x67,0x27,0x27,0x7D, - - 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01, - - 0x42,0x30,0x01,0x77,0x57,0xA7,0x67,0xFA,0xE4,0x23, /* a */ - 0x98,0x56,0x9B,0x74,0x63,0x25,0xD4,0x53,0x13,0xAF, - 0x07,0x66,0x26,0x64,0x79,0xB7,0x56,0x54,0xE6,0x5F, - - 0x50,0x37,0xEA,0x65,0x41,0x96,0xCF,0xF0,0xCD,0x82, /* b */ - 0xB2,0xC1,0x4A,0x2F,0xCF,0x2E,0x3F,0xF8,0x77,0x52, - 0x85,0xB5,0x45,0x72,0x2F,0x03,0xEA,0xCD,0xB7,0x4B, - - 0x28,0xF9,0xD0,0x4E,0x90,0x00,0x69,0xC8,0xDC,0x47, /* x */ - 0xA0,0x85,0x34,0xFE,0x76,0xD2,0xB9,0x00,0xB7,0xD7, - 0xEF,0x31,0xF5,0x70,0x9F,0x20,0x0C,0x4C,0xA2,0x05, - - 0x56,0x67,0x33,0x4C,0x45,0xAF,0xF3,0xB5,0xA0,0x3B, /* y */ - 0xAD,0x9D,0xD7,0x5E,0x2C,0x71,0xA9,0x93,0x62,0x56, - 0x7D,0x54,0x53,0xF7,0xFA,0x6E,0x22,0x7E,0xC8,0x33, - - 0x15,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, /* order */ - 0x55,0x55,0x55,0x55,0x55,0x3C,0x6F,0x28,0x85,0x25, - 0x9C,0x31,0xE3,0xFC,0xDF,0x15,0x46,0x24,0x52,0x2D } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+30*6]; } - _EC_X9_62_CHAR2_239V3 = { - { NID_X9_62_characteristic_two_field,20,30,0xA }, - { 0x9E,0x07,0x6F,0x4D,0x69,0x6E,0x67,0x68,0x75,0x61, /* seed */ - 0x51,0x75,0xE1,0x1E,0x9F,0xDD,0x77,0xF9,0x20,0x41, - - 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01, - - 0x01,0x23,0x87,0x74,0x66,0x6A,0x67,0x76,0x6D,0x66, /* a */ - 0x76,0xF7,0x78,0xE6,0x76,0xB6,0x69,0x99,0x17,0x66, - 0x66,0xE6,0x87,0x66,0x6D,0x87,0x66,0xC6,0x6A,0x9F, - - 0x6A,0x94,0x19,0x77,0xBA,0x9F,0x6A,0x43,0x51,0x99, /* b */ - 0xAC,0xFC,0x51,0x06,0x7E,0xD5,0x87,0xF5,0x19,0xC5, - 0xEC,0xB5,0x41,0xB8,0xE4,0x41,0x11,0xDE,0x1D,0x40, - - 0x70,0xF6,0xE9,0xD0,0x4D,0x28,0x9C,0x4E,0x89,0x91, /* x */ - 0x3C,0xE3,0x53,0x0B,0xFD,0xE9,0x03,0x97,0x7D,0x42, - 0xB1,0x46,0xD5,0x39,0xBF,0x1B,0xDE,0x4E,0x9C,0x92, - - 0x2E,0x5A,0x0E,0xAF,0x6E,0x5E,0x13,0x05,0xB9,0x00, /* y */ - 0x4D,0xCE,0x5C,0x0E,0xD7,0xFE,0x59,0xA3,0x56,0x08, - 0xF3,0x38,0x37,0xC8,0x16,0xD8,0x0B,0x79,0xF4,0x61, - - 0x0C,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC, /* order */ - 0xCC,0xCC,0xCC,0xCC,0xCC,0xAC,0x49,0x12,0xD2,0xD9, - 0xDF,0x90,0x3E,0xF9,0x88,0x8B,0x8A,0x0E,0x4C,0xFF } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[0+35*6]; } - _EC_X9_62_CHAR2_272W1 = { - { NID_X9_62_characteristic_two_field,0,35,0xFF06 }, - { /* no seed */ - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, - 0x00,0x00,0x00,0x00,0x0B, - 0x00,0x91,0xA0,0x91,0xF0,0x3B,0x5F,0xBA,0x4A,0xB2, /* a */ - 0xCC,0xF4,0x9C,0x4E,0xDD,0x22,0x0F,0xB0,0x28,0x71, - 0x2D,0x42,0xBE,0x75,0x2B,0x2C,0x40,0x09,0x4D,0xBA, - 0xCD,0xB5,0x86,0xFB,0x20, - 0x00,0x71,0x67,0xEF,0xC9,0x2B,0xB2,0xE3,0xCE,0x7C, /* b */ - 0x8A,0xAA,0xFF,0x34,0xE1,0x2A,0x9C,0x55,0x70,0x03, - 0xD7,0xC7,0x3A,0x6F,0xAF,0x00,0x3F,0x99,0xF6,0xCC, - 0x84,0x82,0xE5,0x40,0xF7, - 0x00,0x61,0x08,0xBA,0xBB,0x2C,0xEE,0xBC,0xF7,0x87, /* x */ - 0x05,0x8A,0x05,0x6C,0xBE,0x0C,0xFE,0x62,0x2D,0x77, - 0x23,0xA2,0x89,0xE0,0x8A,0x07,0xAE,0x13,0xEF,0x0D, - 0x10,0xD1,0x71,0xDD,0x8D, - 0x00,0x10,0xC7,0x69,0x57,0x16,0x85,0x1E,0xEF,0x6B, /* y */ - 0xA7,0xF6,0x87,0x2E,0x61,0x42,0xFB,0xD2,0x41,0xB8, - 0x30,0xFF,0x5E,0xFC,0xAC,0xEC,0xCA,0xB0,0x5E,0x02, - 0x00,0x5D,0xDE,0x9D,0x23, - 0x00,0x00,0x01,0x00,0xFA,0xF5,0x13,0x54,0xE0,0xE3, /* order */ - 0x9E,0x48,0x92,0xDF,0x6E,0x31,0x9C,0x72,0xC8,0x16, - 0x16,0x03,0xFA,0x45,0xAA,0x7B,0x99,0x8A,0x16,0x7B, - 0x8F,0x1E,0x62,0x95,0x21 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[0+39*6]; } - _EC_X9_62_CHAR2_304W1 = { - { NID_X9_62_characteristic_two_field,0,39,0xFE2E }, - { /* no seed */ - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x07, - 0x00,0xFD,0x0D,0x69,0x31,0x49,0xA1,0x18,0xF6,0x51, /* a */ - 0xE6,0xDC,0xE6,0x80,0x20,0x85,0x37,0x7E,0x5F,0x88, - 0x2D,0x1B,0x51,0x0B,0x44,0x16,0x00,0x74,0xC1,0x28, - 0x80,0x78,0x36,0x5A,0x03,0x96,0xC8,0xE6,0x81, - 0x00,0xBD,0xDB,0x97,0xE5,0x55,0xA5,0x0A,0x90,0x8E, /* b */ - 0x43,0xB0,0x1C,0x79,0x8E,0xA5,0xDA,0xA6,0x78,0x8F, - 0x1E,0xA2,0x79,0x4E,0xFC,0xF5,0x71,0x66,0xB8,0xC1, - 0x40,0x39,0x60,0x1E,0x55,0x82,0x73,0x40,0xBE, - 0x00,0x19,0x7B,0x07,0x84,0x5E,0x9B,0xE2,0xD9,0x6A, /* x */ - 0xDB,0x0F,0x5F,0x3C,0x7F,0x2C,0xFF,0xBD,0x7A,0x3E, - 0xB8,0xB6,0xFE,0xC3,0x5C,0x7F,0xD6,0x7F,0x26,0xDD, - 0xF6,0x28,0x5A,0x64,0x4F,0x74,0x0A,0x26,0x14, - 0x00,0xE1,0x9F,0xBE,0xB7,0x6E,0x0D,0xA1,0x71,0x51, /* y */ - 0x7E,0xCF,0x40,0x1B,0x50,0x28,0x9B,0xF0,0x14,0x10, - 0x32,0x88,0x52,0x7A,0x9B,0x41,0x6A,0x10,0x5E,0x80, - 0x26,0x0B,0x54,0x9F,0xDC,0x1B,0x92,0xC0,0x3B, - 0x00,0x00,0x01,0x01,0xD5,0x56,0x57,0x2A,0xAB,0xAC, /* order */ - 0x80,0x01,0x01,0xD5,0x56,0x57,0x2A,0xAB,0xAC,0x80, - 0x01,0x02,0x2D,0x5C,0x91,0xDD,0x17,0x3F,0x8F,0xB5, - 0x61,0xDA,0x68,0x99,0x16,0x44,0x43,0x05,0x1D } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[20+45*6]; } - _EC_X9_62_CHAR2_359V1 = { - { NID_X9_62_characteristic_two_field,20,45,0x4C }, - { 0x2B,0x35,0x49,0x20,0xB7,0x24,0xD6,0x96,0xE6,0x76, /* seed */ - 0x87,0x56,0x15,0x17,0x58,0x5B,0xA1,0x33,0x2D,0xC6, - - 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x01, - 0x56,0x67,0x67,0x6A,0x65,0x4B,0x20,0x75,0x4F,0x35, /* a */ - 0x6E,0xA9,0x20,0x17,0xD9,0x46,0x56,0x7C,0x46,0x67, - 0x55,0x56,0xF1,0x95,0x56,0xA0,0x46,0x16,0xB5,0x67, - 0xD2,0x23,0xA5,0xE0,0x56,0x56,0xFB,0x54,0x90,0x16, - 0xA9,0x66,0x56,0xA5,0x57, - 0x24,0x72,0xE2,0xD0,0x19,0x7C,0x49,0x36,0x3F,0x1F, /* b */ - 0xE7,0xF5,0xB6,0xDB,0x07,0x5D,0x52,0xB6,0x94,0x7D, - 0x13,0x5D,0x8C,0xA4,0x45,0x80,0x5D,0x39,0xBC,0x34, - 0x56,0x26,0x08,0x96,0x87,0x74,0x2B,0x63,0x29,0xE7, - 0x06,0x80,0x23,0x19,0x88, - 0x3C,0x25,0x8E,0xF3,0x04,0x77,0x67,0xE7,0xED,0xE0, /* x */ - 0xF1,0xFD,0xAA,0x79,0xDA,0xEE,0x38,0x41,0x36,0x6A, - 0x13,0x2E,0x16,0x3A,0xCE,0xD4,0xED,0x24,0x01,0xDF, - 0x9C,0x6B,0xDC,0xDE,0x98,0xE8,0xE7,0x07,0xC0,0x7A, - 0x22,0x39,0xB1,0xB0,0x97, - 0x53,0xD7,0xE0,0x85,0x29,0x54,0x70,0x48,0x12,0x1E, /* y */ - 0x9C,0x95,0xF3,0x79,0x1D,0xD8,0x04,0x96,0x39,0x48, - 0xF3,0x4F,0xAE,0x7B,0xF4,0x4E,0xA8,0x23,0x65,0xDC, - 0x78,0x68,0xFE,0x57,0xE4,0xAE,0x2D,0xE2,0x11,0x30, - 0x5A,0x40,0x71,0x04,0xBD, - 0x01,0xAF,0x28,0x6B,0xCA,0x1A,0xF2,0x86,0xBC,0xA1, /* order */ - 0xAF,0x28,0x6B,0xCA,0x1A,0xF2,0x86,0xBC,0xA1,0xAF, - 0x28,0x6B,0xC9,0xFB,0x8F,0x6B,0x85,0xC5,0x56,0x89, - 0x2C,0x20,0xA7,0xEB,0x96,0x4F,0xE7,0x71,0x9E,0x74, - 0xF4,0x90,0x75,0x8D,0x3B } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[0+47*6]; } - _EC_X9_62_CHAR2_368W1 = { - { NID_X9_62_characteristic_two_field,0,47,0xFF70 }, - { /* no seed */ - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x07, - 0x00,0xE0,0xD2,0xEE,0x25,0x09,0x52,0x06,0xF5,0xE2, /* a */ - 0xA4,0xF9,0xED,0x22,0x9F,0x1F,0x25,0x6E,0x79,0xA0, - 0xE2,0xB4,0x55,0x97,0x0D,0x8D,0x0D,0x86,0x5B,0xD9, - 0x47,0x78,0xC5,0x76,0xD6,0x2F,0x0A,0xB7,0x51,0x9C, - 0xCD,0x2A,0x1A,0x90,0x6A,0xE3,0x0D, - 0x00,0xFC,0x12,0x17,0xD4,0x32,0x0A,0x90,0x45,0x2C, /* b */ - 0x76,0x0A,0x58,0xED,0xCD,0x30,0xC8,0xDD,0x06,0x9B, - 0x3C,0x34,0x45,0x38,0x37,0xA3,0x4E,0xD5,0x0C,0xB5, - 0x49,0x17,0xE1,0xC2,0x11,0x2D,0x84,0xD1,0x64,0xF4, - 0x44,0xF8,0xF7,0x47,0x86,0x04,0x6A, - 0x00,0x10,0x85,0xE2,0x75,0x53,0x81,0xDC,0xCC,0xE3, /* x */ - 0xC1,0x55,0x7A,0xFA,0x10,0xC2,0xF0,0xC0,0xC2,0x82, - 0x56,0x46,0xC5,0xB3,0x4A,0x39,0x4C,0xBC,0xFA,0x8B, - 0xC1,0x6B,0x22,0xE7,0xE7,0x89,0xE9,0x27,0xBE,0x21, - 0x6F,0x02,0xE1,0xFB,0x13,0x6A,0x5F, - 0x00,0x7B,0x3E,0xB1,0xBD,0xDC,0xBA,0x62,0xD5,0xD8, /* y */ - 0xB2,0x05,0x9B,0x52,0x57,0x97,0xFC,0x73,0x82,0x2C, - 0x59,0x05,0x9C,0x62,0x3A,0x45,0xFF,0x38,0x43,0xCE, - 0xE8,0xF8,0x7C,0xD1,0x85,0x5A,0xDA,0xA8,0x1E,0x2A, - 0x07,0x50,0xB8,0x0F,0xDA,0x23,0x10, - 0x00,0x00,0x01,0x00,0x90,0x51,0x2D,0xA9,0xAF,0x72, /* order */ - 0xB0,0x83,0x49,0xD9,0x8A,0x5D,0xD4,0xC7,0xB0,0x53, - 0x2E,0xCA,0x51,0xCE,0x03,0xE2,0xD1,0x0F,0x3B,0x7A, - 0xC5,0x79,0xBD,0x87,0xE9,0x09,0xAE,0x40,0xA6,0xF1, - 0x31,0xE9,0xCF,0xCE,0x5B,0xD9,0x67 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[0+54*6]; } - _EC_X9_62_CHAR2_431R1 = { - { NID_X9_62_characteristic_two_field,0,54,0x2760 }, - { /* no seed */ - 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x01, - 0x1A,0x82,0x7E,0xF0,0x0D,0xD6,0xFC,0x0E,0x23,0x4C, /* a */ - 0xAF,0x04,0x6C,0x6A,0x5D,0x8A,0x85,0x39,0x5B,0x23, - 0x6C,0xC4,0xAD,0x2C,0xF3,0x2A,0x0C,0xAD,0xBD,0xC9, - 0xDD,0xF6,0x20,0xB0,0xEB,0x99,0x06,0xD0,0x95,0x7F, - 0x6C,0x6F,0xEA,0xCD,0x61,0x54,0x68,0xDF,0x10,0x4D, - 0xE2,0x96,0xCD,0x8F, - 0x10,0xD9,0xB4,0xA3,0xD9,0x04,0x7D,0x8B,0x15,0x43, /* b */ - 0x59,0xAB,0xFB,0x1B,0x7F,0x54,0x85,0xB0,0x4C,0xEB, - 0x86,0x82,0x37,0xDD,0xC9,0xDE,0xDA,0x98,0x2A,0x67, - 0x9A,0x5A,0x91,0x9B,0x62,0x6D,0x4E,0x50,0xA8,0xDD, - 0x73,0x1B,0x10,0x7A,0x99,0x62,0x38,0x1F,0xB5,0xD8, - 0x07,0xBF,0x26,0x18, - 0x12,0x0F,0xC0,0x5D,0x3C,0x67,0xA9,0x9D,0xE1,0x61, /* x */ - 0xD2,0xF4,0x09,0x26,0x22,0xFE,0xCA,0x70,0x1B,0xE4, - 0xF5,0x0F,0x47,0x58,0x71,0x4E,0x8A,0x87,0xBB,0xF2, - 0xA6,0x58,0xEF,0x8C,0x21,0xE7,0xC5,0xEF,0xE9,0x65, - 0x36,0x1F,0x6C,0x29,0x99,0xC0,0xC2,0x47,0xB0,0xDB, - 0xD7,0x0C,0xE6,0xB7, - 0x20,0xD0,0xAF,0x89,0x03,0xA9,0x6F,0x8D,0x5F,0xA2, /* y */ - 0xC2,0x55,0x74,0x5D,0x3C,0x45,0x1B,0x30,0x2C,0x93, - 0x46,0xD9,0xB7,0xE4,0x85,0xE7,0xBC,0xE4,0x1F,0x6B, - 0x59,0x1F,0x3E,0x8F,0x6A,0xDD,0xCB,0xB0,0xBC,0x4C, - 0x2F,0x94,0x7A,0x7D,0xE1,0xA8,0x9B,0x62,0x5D,0x6A, - 0x59,0x8B,0x37,0x60, - 0x00,0x03,0x40,0x34,0x03,0x40,0x34,0x03,0x40,0x34, /* order */ - 0x03,0x40,0x34,0x03,0x40,0x34,0x03,0x40,0x34,0x03, - 0x40,0x34,0x03,0x40,0x34,0x03,0x40,0x34,0x03,0x23, - 0xC3,0x13,0xFA,0xB5,0x05,0x89,0x70,0x3B,0x5E,0xC6, - 0x8D,0x35,0x87,0xFE,0xC6,0x0D,0x16,0x1C,0xC1,0x49, - 0xC1,0xAD,0x4A,0x91 } - }; - -static const struct { EC_CURVE_DATA h; unsigned char data[0+15*6]; } - _EC_WTLS_1 = { - { NID_X9_62_characteristic_two_field,0,15,2 }, - { /* no seed */ - 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x02,0x01, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */ - 0x00,0x00,0x00,0x00,0x01, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */ - 0x00,0x00,0x00,0x00,0x01, - 0x01,0x66,0x79,0x79,0xA4,0x0B,0xA4,0x97,0xE5,0xD5, /* x */ - 0xC2,0x70,0x78,0x06,0x17, - 0x00,0xF4,0x4B,0x4A,0xF1,0xEC,0xC2,0x63,0x0E,0x08, /* y */ - 0x78,0x5C,0xEB,0xCC,0x15, - 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xBF, /* order */ - 0x91,0xAF,0x6D,0xEA,0x73 } - }; +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 15 * 6]; +} _EC_SECG_CHAR2_113R1 = { + { + NID_X9_62_characteristic_two_field, 20, 15, 2 + }, + { + /* seed */ + 0x10, 0xE7, 0x23, 0xAB, 0x14, 0xD6, 0x96, 0xE6, 0x76, 0x87, 0x56, 0x15, + 0x17, 0x56, 0xFE, 0xBF, 0x8F, 0xCB, 0x49, 0xA9, + /* p */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x01, + /* a */ + 0x00, 0x30, 0x88, 0x25, 0x0C, 0xA6, 0xE7, 0xC7, 0xFE, 0x64, 0x9C, 0xE8, + 0x58, 0x20, 0xF7, + /* b */ + 0x00, 0xE8, 0xBE, 0xE4, 0xD3, 0xE2, 0x26, 0x07, 0x44, 0x18, 0x8B, 0xE0, + 0xE9, 0xC7, 0x23, + /* x */ + 0x00, 0x9D, 0x73, 0x61, 0x6F, 0x35, 0xF4, 0xAB, 0x14, 0x07, 0xD7, 0x35, + 0x62, 0xC1, 0x0F, + /* y */ + 0x00, 0xA5, 0x28, 0x30, 0x27, 0x79, 0x58, 0xEE, 0x84, 0xD1, 0x31, 0x5E, + 0xD3, 0x18, 0x86, + /* order */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD9, 0xCC, 0xEC, 0x8A, + 0x39, 0xE5, 0x6F + } +}; -/* IPSec curves */ -/* NOTE: The of curves over a extension field of non prime degree - * is not recommended (Weil-descent). - * As the group order is not a prime this curve is not suitable - * for ECDSA. - */ -static const struct { EC_CURVE_DATA h; unsigned char data[0+20*6]; } - _EC_IPSEC_155_ID3 = { - { NID_X9_62_characteristic_two_field,0,20,3 }, - { /* no seed */ - 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x01, +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 15 * 6]; +} _EC_SECG_CHAR2_113R2 = { + { + NID_X9_62_characteristic_two_field, 20, 15, 2 + }, + { + /* seed */ + 0x10, 0xC0, 0xFB, 0x15, 0x76, 0x08, 0x60, 0xDE, 0xF1, 0xEE, 0xF4, 0xD6, + 0x96, 0xE6, 0x76, 0x87, 0x56, 0x15, 0x17, 0x5D, + /* p */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x01, + /* a */ + 0x00, 0x68, 0x99, 0x18, 0xDB, 0xEC, 0x7E, 0x5A, 0x0D, 0xD6, 0xDF, 0xC0, + 0xAA, 0x55, 0xC7, + /* b */ + 0x00, 0x95, 0xE9, 0xA9, 0xEC, 0x9B, 0x29, 0x7B, 0xD4, 0xBF, 0x36, 0xE0, + 0x59, 0x18, 0x4F, + /* x */ + 0x01, 0xA5, 0x7A, 0x6A, 0x7B, 0x26, 0xCA, 0x5E, 0xF5, 0x2F, 0xCD, 0xB8, + 0x16, 0x47, 0x97, + /* y */ + 0x00, 0xB3, 0xAD, 0xC9, 0x4E, 0xD1, 0xFE, 0x67, 0x4C, 0x06, 0xE6, 0x95, + 0xBA, 0xBA, 0x1D, + /* order */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x78, 0x9B, 0x24, + 0x96, 0xAF, 0x93 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 17 * 6]; +} _EC_SECG_CHAR2_131R1 = { + { + NID_X9_62_characteristic_two_field, 20, 17, 2 + }, + { + /* seed */ + 0x4D, 0x69, 0x6E, 0x67, 0x68, 0x75, 0x61, 0x51, 0x75, 0x98, 0x5B, 0xD3, + 0xAD, 0xBA, 0xDA, 0x21, 0xB4, 0x3A, 0x97, 0xE2, + /* p */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x0D, + /* a */ + 0x07, 0xA1, 0x1B, 0x09, 0xA7, 0x6B, 0x56, 0x21, 0x44, 0x41, 0x8F, 0xF3, + 0xFF, 0x8C, 0x25, 0x70, 0xB8, + /* b */ + 0x02, 0x17, 0xC0, 0x56, 0x10, 0x88, 0x4B, 0x63, 0xB9, 0xC6, 0xC7, 0x29, + 0x16, 0x78, 0xF9, 0xD3, 0x41, + /* x */ + 0x00, 0x81, 0xBA, 0xF9, 0x1F, 0xDF, 0x98, 0x33, 0xC4, 0x0F, 0x9C, 0x18, + 0x13, 0x43, 0x63, 0x83, 0x99, + /* y */ + 0x07, 0x8C, 0x6E, 0x7E, 0xA3, 0x8C, 0x00, 0x1F, 0x73, 0xC8, 0x13, 0x4B, + 0x1B, 0x4E, 0xF9, 0xE1, 0x50, + /* order */ + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31, 0x23, 0x95, + 0x3A, 0x94, 0x64, 0xB5, 0x4D + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 17 * 6]; +} _EC_SECG_CHAR2_131R2 = { + { + NID_X9_62_characteristic_two_field, 20, 17, 2 + }, + { + /* seed */ + 0x98, 0x5B, 0xD3, 0xAD, 0xBA, 0xD4, 0xD6, 0x96, 0xE6, 0x76, 0x87, 0x56, + 0x15, 0x17, 0x5A, 0x21, 0xB4, 0x3A, 0x97, 0xE3, + /* p */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x0D, + /* a */ + 0x03, 0xE5, 0xA8, 0x89, 0x19, 0xD7, 0xCA, 0xFC, 0xBF, 0x41, 0x5F, 0x07, + 0xC2, 0x17, 0x65, 0x73, 0xB2, + /* b */ + 0x04, 0xB8, 0x26, 0x6A, 0x46, 0xC5, 0x56, 0x57, 0xAC, 0x73, 0x4C, 0xE3, + 0x8F, 0x01, 0x8F, 0x21, 0x92, + /* x */ + 0x03, 0x56, 0xDC, 0xD8, 0xF2, 0xF9, 0x50, 0x31, 0xAD, 0x65, 0x2D, 0x23, + 0x95, 0x1B, 0xB3, 0x66, 0xA8, + /* y */ + 0x06, 0x48, 0xF0, 0x6D, 0x86, 0x79, 0x40, 0xA5, 0x36, 0x6D, 0x9E, 0x26, + 0x5D, 0xE9, 0xEB, 0x24, 0x0F, + /* order */ + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x69, 0x54, 0xA2, + 0x33, 0x04, 0x9B, 0xA9, 0x8F + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 21 * 6]; +} _EC_NIST_CHAR2_163K = { + { + NID_X9_62_characteristic_two_field, 0, 21, 2 + }, + { + /* no seed */ + /* p */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC9, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* x */ + 0x02, 0xFE, 0x13, 0xC0, 0x53, 0x7B, 0xBC, 0x11, 0xAC, 0xAA, 0x07, 0xD7, + 0x93, 0xDE, 0x4E, 0x6D, 0x5E, 0x5C, 0x94, 0xEE, 0xE8, + /* y */ + 0x02, 0x89, 0x07, 0x0F, 0xB0, 0x5D, 0x38, 0xFF, 0x58, 0x32, 0x1F, 0x2E, + 0x80, 0x05, 0x36, 0xD5, 0x38, 0xCC, 0xDA, 0xA3, 0xD9, + /* order */ + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, + 0x08, 0xA2, 0xE0, 0xCC, 0x0D, 0x99, 0xF8, 0xA5, 0xEF + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 21 * 6]; +} _EC_SECG_CHAR2_163R1 = { + { + NID_X9_62_characteristic_two_field, 0, 21, 2 + }, + { + /* no seed */ +# if 0 + /* + * The algorithm used to derive the curve parameters from the seed + * used here is slightly different than the algorithm described in + * X9.62 . + */ + 0x24, 0xB7, 0xB1, 0x37, 0xC8, 0xA1, 0x4D, 0x69, 0x6E, 0x67, 0x68, 0x75, + 0x61, 0x51, 0x75, 0x6F, 0xD0, 0xDA, 0x2E, 0x5C, +# endif + /* p */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC9, + /* a */ + 0x07, 0xB6, 0x88, 0x2C, 0xAA, 0xEF, 0xA8, 0x4F, 0x95, 0x54, 0xFF, 0x84, + 0x28, 0xBD, 0x88, 0xE2, 0x46, 0xD2, 0x78, 0x2A, 0xE2, + /* b */ + 0x07, 0x13, 0x61, 0x2D, 0xCD, 0xDC, 0xB4, 0x0A, 0xAB, 0x94, 0x6B, 0xDA, + 0x29, 0xCA, 0x91, 0xF7, 0x3A, 0xF9, 0x58, 0xAF, 0xD9, + /* x */ + 0x03, 0x69, 0x97, 0x96, 0x97, 0xAB, 0x43, 0x89, 0x77, 0x89, 0x56, 0x67, + 0x89, 0x56, 0x7F, 0x78, 0x7A, 0x78, 0x76, 0xA6, 0x54, + /* y */ + 0x00, 0x43, 0x5E, 0xDB, 0x42, 0xEF, 0xAF, 0xB2, 0x98, 0x9D, 0x51, 0xFE, + 0xFC, 0xE3, 0xC8, 0x09, 0x88, 0xF4, 0x1F, 0xF8, 0x83, + /* order */ + 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x48, + 0xAA, 0xB6, 0x89, 0xC2, 0x9C, 0xA7, 0x10, 0x27, 0x9B + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 21 * 6]; +} _EC_NIST_CHAR2_163B = { + { + NID_X9_62_characteristic_two_field, 0, 21, 2 + }, + { + /* no seed */ +# if 0 + /* + * The seed here was used to created the curve parameters in normal + * basis representation (and not the polynomial representation used + * here) + */ + 0x85, 0xE2, 0x5B, 0xFE, 0x5C, 0x86, 0x22, 0x6C, 0xDB, 0x12, 0x01, 0x6F, + 0x75, 0x53, 0xF9, 0xD0, 0xE6, 0x93, 0xA2, 0x68, +# endif + /* p */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC9, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* b */ + 0x02, 0x0A, 0x60, 0x19, 0x07, 0xB8, 0xC9, 0x53, 0xCA, 0x14, 0x81, 0xEB, + 0x10, 0x51, 0x2F, 0x78, 0x74, 0x4A, 0x32, 0x05, 0xFD, + /* x */ + 0x03, 0xF0, 0xEB, 0xA1, 0x62, 0x86, 0xA2, 0xD5, 0x7E, 0xA0, 0x99, 0x11, + 0x68, 0xD4, 0x99, 0x46, 0x37, 0xE8, 0x34, 0x3E, 0x36, + /* y */ + 0x00, 0xD5, 0x1F, 0xBC, 0x6C, 0x71, 0xA0, 0x09, 0x4F, 0xA2, 0xCD, 0xD5, + 0x45, 0xB1, 0x1C, 0x5C, 0x0C, 0x79, 0x73, 0x24, 0xF1, + /* order */ + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x92, + 0xFE, 0x77, 0xE7, 0x0C, 0x12, 0xA4, 0x23, 0x4C, 0x33 + } +}; - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 25 * 6]; +} _EC_SECG_CHAR2_193R1 = { + { + NID_X9_62_characteristic_two_field, 20, 25, 2 + }, + { + /* seed */ + 0x10, 0x3F, 0xAE, 0xC7, 0x4D, 0x69, 0x6E, 0x67, 0x68, 0x75, 0x61, 0x51, + 0x75, 0x77, 0x7F, 0xC5, 0xB1, 0x91, 0xEF, 0x30, + /* p */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x01, + /* a */ + 0x00, 0x17, 0x85, 0x8F, 0xEB, 0x7A, 0x98, 0x97, 0x51, 0x69, 0xE1, 0x71, + 0xF7, 0x7B, 0x40, 0x87, 0xDE, 0x09, 0x8A, 0xC8, 0xA9, 0x11, 0xDF, 0x7B, + 0x01, + /* b */ + 0x00, 0xFD, 0xFB, 0x49, 0xBF, 0xE6, 0xC3, 0xA8, 0x9F, 0xAC, 0xAD, 0xAA, + 0x7A, 0x1E, 0x5B, 0xBC, 0x7C, 0xC1, 0xC2, 0xE5, 0xD8, 0x31, 0x47, 0x88, + 0x14, + /* x */ + 0x01, 0xF4, 0x81, 0xBC, 0x5F, 0x0F, 0xF8, 0x4A, 0x74, 0xAD, 0x6C, 0xDF, + 0x6F, 0xDE, 0xF4, 0xBF, 0x61, 0x79, 0x62, 0x53, 0x72, 0xD8, 0xC0, 0xC5, + 0xE1, + /* y */ + 0x00, 0x25, 0xE3, 0x99, 0xF2, 0x90, 0x37, 0x12, 0xCC, 0xF3, 0xEA, 0x9E, + 0x3A, 0x1A, 0xD1, 0x7F, 0xB0, 0xB3, 0x20, 0x1B, 0x6A, 0xF7, 0xCE, 0x1B, + 0x05, + /* order */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xC7, 0xF3, 0x4A, 0x77, 0x8F, 0x44, 0x3A, 0xCC, 0x92, 0x0E, 0xBA, + 0x49 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 25 * 6]; +} _EC_SECG_CHAR2_193R2 = { + { + NID_X9_62_characteristic_two_field, 20, 25, 2 + }, + { + /* seed */ + 0x10, 0xB7, 0xB4, 0xD6, 0x96, 0xE6, 0x76, 0x87, 0x56, 0x15, 0x17, 0x51, + 0x37, 0xC8, 0xA1, 0x6F, 0xD0, 0xDA, 0x22, 0x11, + /* p */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x01, + /* a */ + 0x01, 0x63, 0xF3, 0x5A, 0x51, 0x37, 0xC2, 0xCE, 0x3E, 0xA6, 0xED, 0x86, + 0x67, 0x19, 0x0B, 0x0B, 0xC4, 0x3E, 0xCD, 0x69, 0x97, 0x77, 0x02, 0x70, + 0x9B, + /* b */ + 0x00, 0xC9, 0xBB, 0x9E, 0x89, 0x27, 0xD4, 0xD6, 0x4C, 0x37, 0x7E, 0x2A, + 0xB2, 0x85, 0x6A, 0x5B, 0x16, 0xE3, 0xEF, 0xB7, 0xF6, 0x1D, 0x43, 0x16, + 0xAE, + /* x */ + 0x00, 0xD9, 0xB6, 0x7D, 0x19, 0x2E, 0x03, 0x67, 0xC8, 0x03, 0xF3, 0x9E, + 0x1A, 0x7E, 0x82, 0xCA, 0x14, 0xA6, 0x51, 0x35, 0x0A, 0xAE, 0x61, 0x7E, + 0x8F, + /* y */ + 0x01, 0xCE, 0x94, 0x33, 0x56, 0x07, 0xC3, 0x04, 0xAC, 0x29, 0xE7, 0xDE, + 0xFB, 0xD9, 0xCA, 0x01, 0xF5, 0x96, 0xF9, 0x27, 0x22, 0x4C, 0xDE, 0xCF, + 0x6C, + /* order */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x5A, 0xAB, 0x56, 0x1B, 0x00, 0x54, 0x13, 0xCC, 0xD4, 0xEE, 0x99, + 0xD5 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 30 * 6]; +} _EC_NIST_CHAR2_233K = { + { + NID_X9_62_characteristic_two_field, 0, 30, 4 + }, + { + /* no seed */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* x */ + 0x01, 0x72, 0x32, 0xBA, 0x85, 0x3A, 0x7E, 0x73, 0x1A, 0xF1, 0x29, 0xF2, + 0x2F, 0xF4, 0x14, 0x95, 0x63, 0xA4, 0x19, 0xC2, 0x6B, 0xF5, 0x0A, 0x4C, + 0x9D, 0x6E, 0xEF, 0xAD, 0x61, 0x26, + /* y */ + 0x01, 0xDB, 0x53, 0x7D, 0xEC, 0xE8, 0x19, 0xB7, 0xF7, 0x0F, 0x55, 0x5A, + 0x67, 0xC4, 0x27, 0xA8, 0xCD, 0x9B, 0xF1, 0x8A, 0xEB, 0x9B, 0x56, 0xE0, + 0xC1, 0x10, 0x56, 0xFA, 0xE6, 0xA3, + /* order */ + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x9D, 0x5B, 0xB9, 0x15, 0xBC, 0xD4, 0x6E, 0xFB, + 0x1A, 0xD5, 0xF1, 0x73, 0xAB, 0xDF + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 30 * 6]; +} _EC_NIST_CHAR2_233B = { + { + NID_X9_62_characteristic_two_field, 20, 30, 2 + }, + { + /* seed */ + 0x74, 0xD5, 0x9F, 0xF0, 0x7F, 0x6B, 0x41, 0x3D, 0x0E, 0xA1, 0x4B, 0x34, + 0x4B, 0x20, 0xA2, 0xDB, 0x04, 0x9B, 0x50, 0xC3, + /* p */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* b */ + 0x00, 0x66, 0x64, 0x7E, 0xDE, 0x6C, 0x33, 0x2C, 0x7F, 0x8C, 0x09, 0x23, + 0xBB, 0x58, 0x21, 0x3B, 0x33, 0x3B, 0x20, 0xE9, 0xCE, 0x42, 0x81, 0xFE, + 0x11, 0x5F, 0x7D, 0x8F, 0x90, 0xAD, + /* x */ + 0x00, 0xFA, 0xC9, 0xDF, 0xCB, 0xAC, 0x83, 0x13, 0xBB, 0x21, 0x39, 0xF1, + 0xBB, 0x75, 0x5F, 0xEF, 0x65, 0xBC, 0x39, 0x1F, 0x8B, 0x36, 0xF8, 0xF8, + 0xEB, 0x73, 0x71, 0xFD, 0x55, 0x8B, + /* y */ + 0x01, 0x00, 0x6A, 0x08, 0xA4, 0x19, 0x03, 0x35, 0x06, 0x78, 0xE5, 0x85, + 0x28, 0xBE, 0xBF, 0x8A, 0x0B, 0xEF, 0xF8, 0x67, 0xA7, 0xCA, 0x36, 0x71, + 0x6F, 0x7E, 0x01, 0xF8, 0x10, 0x52, + /* order */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x13, 0xE9, 0x74, 0xE7, 0x2F, 0x8A, 0x69, 0x22, 0x03, + 0x1D, 0x26, 0x03, 0xCF, 0xE0, 0xD7 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 30 * 6]; +} _EC_SECG_CHAR2_239K1 = { + { + NID_X9_62_characteristic_two_field, 0, 30, 4 + }, + { + /* no seed */ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* x */ + 0x29, 0xA0, 0xB6, 0xA8, 0x87, 0xA9, 0x83, 0xE9, 0x73, 0x09, 0x88, 0xA6, + 0x87, 0x27, 0xA8, 0xB2, 0xD1, 0x26, 0xC4, 0x4C, 0xC2, 0xCC, 0x7B, 0x2A, + 0x65, 0x55, 0x19, 0x30, 0x35, 0xDC, + /* y */ + 0x76, 0x31, 0x08, 0x04, 0xF1, 0x2E, 0x54, 0x9B, 0xDB, 0x01, 0x1C, 0x10, + 0x30, 0x89, 0xE7, 0x35, 0x10, 0xAC, 0xB2, 0x75, 0xFC, 0x31, 0x2A, 0x5D, + 0xC6, 0xB7, 0x65, 0x53, 0xF0, 0xCA, + /* order */ + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x5A, 0x79, 0xFE, 0xC6, 0x7C, 0xB6, 0xE9, 0x1F, 0x1C, + 0x1D, 0xA8, 0x00, 0xE4, 0x78, 0xA5 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 36 * 6]; +} _EC_NIST_CHAR2_283K = { + { + NID_X9_62_characteristic_two_field, 0, 36, 4 + }, + { + /* no seed */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA1, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* x */ + 0x05, 0x03, 0x21, 0x3F, 0x78, 0xCA, 0x44, 0x88, 0x3F, 0x1A, 0x3B, 0x81, + 0x62, 0xF1, 0x88, 0xE5, 0x53, 0xCD, 0x26, 0x5F, 0x23, 0xC1, 0x56, 0x7A, + 0x16, 0x87, 0x69, 0x13, 0xB0, 0xC2, 0xAC, 0x24, 0x58, 0x49, 0x28, 0x36, + /* y */ + 0x01, 0xCC, 0xDA, 0x38, 0x0F, 0x1C, 0x9E, 0x31, 0x8D, 0x90, 0xF9, 0x5D, + 0x07, 0xE5, 0x42, 0x6F, 0xE8, 0x7E, 0x45, 0xC0, 0xE8, 0x18, 0x46, 0x98, + 0xE4, 0x59, 0x62, 0x36, 0x4E, 0x34, 0x11, 0x61, 0x77, 0xDD, 0x22, 0x59, + /* order */ + 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE9, 0xAE, 0x2E, 0xD0, 0x75, 0x77, + 0x26, 0x5D, 0xFF, 0x7F, 0x94, 0x45, 0x1E, 0x06, 0x1E, 0x16, 0x3C, 0x61 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 36 * 6]; +} _EC_NIST_CHAR2_283B = { + { + NID_X9_62_characteristic_two_field, 20, 36, 2 + }, + { + /* no seed */ + 0x77, 0xE2, 0xB0, 0x73, 0x70, 0xEB, 0x0F, 0x83, 0x2A, 0x6D, 0xD5, 0xB6, + 0x2D, 0xFC, 0x88, 0xCD, 0x06, 0xBB, 0x84, 0xBE, + /* p */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA1, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* b */ + 0x02, 0x7B, 0x68, 0x0A, 0xC8, 0xB8, 0x59, 0x6D, 0xA5, 0xA4, 0xAF, 0x8A, + 0x19, 0xA0, 0x30, 0x3F, 0xCA, 0x97, 0xFD, 0x76, 0x45, 0x30, 0x9F, 0xA2, + 0xA5, 0x81, 0x48, 0x5A, 0xF6, 0x26, 0x3E, 0x31, 0x3B, 0x79, 0xA2, 0xF5, + /* x */ + 0x05, 0xF9, 0x39, 0x25, 0x8D, 0xB7, 0xDD, 0x90, 0xE1, 0x93, 0x4F, 0x8C, + 0x70, 0xB0, 0xDF, 0xEC, 0x2E, 0xED, 0x25, 0xB8, 0x55, 0x7E, 0xAC, 0x9C, + 0x80, 0xE2, 0xE1, 0x98, 0xF8, 0xCD, 0xBE, 0xCD, 0x86, 0xB1, 0x20, 0x53, + /* y */ + 0x03, 0x67, 0x68, 0x54, 0xFE, 0x24, 0x14, 0x1C, 0xB9, 0x8F, 0xE6, 0xD4, + 0xB2, 0x0D, 0x02, 0xB4, 0x51, 0x6F, 0xF7, 0x02, 0x35, 0x0E, 0xDD, 0xB0, + 0x82, 0x67, 0x79, 0xC8, 0x13, 0xF0, 0xDF, 0x45, 0xBE, 0x81, 0x12, 0xF4, + /* order */ + 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x90, 0x39, 0x96, 0x60, 0xFC, + 0x93, 0x8A, 0x90, 0x16, 0x5B, 0x04, 0x2A, 0x7C, 0xEF, 0xAD, 0xB3, 0x07 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 52 * 6]; +} _EC_NIST_CHAR2_409K = { + { + NID_X9_62_characteristic_two_field, 0, 52, 4 + }, + { + /* no seed */ + /* p */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + /* x */ + 0x00, 0x60, 0xF0, 0x5F, 0x65, 0x8F, 0x49, 0xC1, 0xAD, 0x3A, 0xB1, 0x89, + 0x0F, 0x71, 0x84, 0x21, 0x0E, 0xFD, 0x09, 0x87, 0xE3, 0x07, 0xC8, 0x4C, + 0x27, 0xAC, 0xCF, 0xB8, 0xF9, 0xF6, 0x7C, 0xC2, 0xC4, 0x60, 0x18, 0x9E, + 0xB5, 0xAA, 0xAA, 0x62, 0xEE, 0x22, 0x2E, 0xB1, 0xB3, 0x55, 0x40, 0xCF, + 0xE9, 0x02, 0x37, 0x46, + /* y */ + 0x01, 0xE3, 0x69, 0x05, 0x0B, 0x7C, 0x4E, 0x42, 0xAC, 0xBA, 0x1D, 0xAC, + 0xBF, 0x04, 0x29, 0x9C, 0x34, 0x60, 0x78, 0x2F, 0x91, 0x8E, 0xA4, 0x27, + 0xE6, 0x32, 0x51, 0x65, 0xE9, 0xEA, 0x10, 0xE3, 0xDA, 0x5F, 0x6C, 0x42, + 0xE9, 0xC5, 0x52, 0x15, 0xAA, 0x9C, 0xA2, 0x7A, 0x58, 0x63, 0xEC, 0x48, + 0xD8, 0xE0, 0x28, 0x6B, + /* order */ + 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFE, 0x5F, 0x83, 0xB2, 0xD4, 0xEA, 0x20, 0x40, 0x0E, 0xC4, + 0x55, 0x7D, 0x5E, 0xD3, 0xE3, 0xE7, 0xCA, 0x5B, 0x4B, 0x5C, 0x83, 0xB8, + 0xE0, 0x1E, 0x5F, 0xCF + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 52 * 6]; +} _EC_NIST_CHAR2_409B = { + { + NID_X9_62_characteristic_two_field, 20, 52, 2 + }, + { + /* seed */ + 0x40, 0x99, 0xB5, 0xA4, 0x57, 0xF9, 0xD6, 0x9F, 0x79, 0x21, 0x3D, 0x09, + 0x4C, 0x4B, 0xCD, 0x4D, 0x42, 0x62, 0x21, 0x0B, + /* p */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + /* b */ + 0x00, 0x21, 0xA5, 0xC2, 0xC8, 0xEE, 0x9F, 0xEB, 0x5C, 0x4B, 0x9A, 0x75, + 0x3B, 0x7B, 0x47, 0x6B, 0x7F, 0xD6, 0x42, 0x2E, 0xF1, 0xF3, 0xDD, 0x67, + 0x47, 0x61, 0xFA, 0x99, 0xD6, 0xAC, 0x27, 0xC8, 0xA9, 0xA1, 0x97, 0xB2, + 0x72, 0x82, 0x2F, 0x6C, 0xD5, 0x7A, 0x55, 0xAA, 0x4F, 0x50, 0xAE, 0x31, + 0x7B, 0x13, 0x54, 0x5F, + /* x */ + 0x01, 0x5D, 0x48, 0x60, 0xD0, 0x88, 0xDD, 0xB3, 0x49, 0x6B, 0x0C, 0x60, + 0x64, 0x75, 0x62, 0x60, 0x44, 0x1C, 0xDE, 0x4A, 0xF1, 0x77, 0x1D, 0x4D, + 0xB0, 0x1F, 0xFE, 0x5B, 0x34, 0xE5, 0x97, 0x03, 0xDC, 0x25, 0x5A, 0x86, + 0x8A, 0x11, 0x80, 0x51, 0x56, 0x03, 0xAE, 0xAB, 0x60, 0x79, 0x4E, 0x54, + 0xBB, 0x79, 0x96, 0xA7, + /* y */ + 0x00, 0x61, 0xB1, 0xCF, 0xAB, 0x6B, 0xE5, 0xF3, 0x2B, 0xBF, 0xA7, 0x83, + 0x24, 0xED, 0x10, 0x6A, 0x76, 0x36, 0xB9, 0xC5, 0xA7, 0xBD, 0x19, 0x8D, + 0x01, 0x58, 0xAA, 0x4F, 0x54, 0x88, 0xD0, 0x8F, 0x38, 0x51, 0x4F, 0x1F, + 0xDF, 0x4B, 0x4F, 0x40, 0xD2, 0x18, 0x1B, 0x36, 0x81, 0xC3, 0x64, 0xBA, + 0x02, 0x73, 0xC7, 0x06, + /* order */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xE2, 0xAA, 0xD6, 0xA6, 0x12, 0xF3, 0x33, 0x07, 0xBE, + 0x5F, 0xA4, 0x7C, 0x3C, 0x9E, 0x05, 0x2F, 0x83, 0x81, 0x64, 0xCD, 0x37, + 0xD9, 0xA2, 0x11, 0x73 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 72 * 6]; +} _EC_NIST_CHAR2_571K = { + { + NID_X9_62_characteristic_two_field, 0, 72, 4 + }, + { + /* no seed */ + /* p */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x25, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* x */ + 0x02, 0x6E, 0xB7, 0xA8, 0x59, 0x92, 0x3F, 0xBC, 0x82, 0x18, 0x96, 0x31, + 0xF8, 0x10, 0x3F, 0xE4, 0xAC, 0x9C, 0xA2, 0x97, 0x00, 0x12, 0xD5, 0xD4, + 0x60, 0x24, 0x80, 0x48, 0x01, 0x84, 0x1C, 0xA4, 0x43, 0x70, 0x95, 0x84, + 0x93, 0xB2, 0x05, 0xE6, 0x47, 0xDA, 0x30, 0x4D, 0xB4, 0xCE, 0xB0, 0x8C, + 0xBB, 0xD1, 0xBA, 0x39, 0x49, 0x47, 0x76, 0xFB, 0x98, 0x8B, 0x47, 0x17, + 0x4D, 0xCA, 0x88, 0xC7, 0xE2, 0x94, 0x52, 0x83, 0xA0, 0x1C, 0x89, 0x72, + /* y */ + 0x03, 0x49, 0xDC, 0x80, 0x7F, 0x4F, 0xBF, 0x37, 0x4F, 0x4A, 0xEA, 0xDE, + 0x3B, 0xCA, 0x95, 0x31, 0x4D, 0xD5, 0x8C, 0xEC, 0x9F, 0x30, 0x7A, 0x54, + 0xFF, 0xC6, 0x1E, 0xFC, 0x00, 0x6D, 0x8A, 0x2C, 0x9D, 0x49, 0x79, 0xC0, + 0xAC, 0x44, 0xAE, 0xA7, 0x4F, 0xBE, 0xBB, 0xB9, 0xF7, 0x72, 0xAE, 0xDC, + 0xB6, 0x20, 0xB0, 0x1A, 0x7B, 0xA7, 0xAF, 0x1B, 0x32, 0x04, 0x30, 0xC8, + 0x59, 0x19, 0x84, 0xF6, 0x01, 0xCD, 0x4C, 0x14, 0x3E, 0xF1, 0xC7, 0xA3, + /* order */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x13, 0x18, 0x50, 0xE1, 0xF1, 0x9A, 0x63, 0xE4, 0xB3, 0x91, 0xA8, 0xDB, + 0x91, 0x7F, 0x41, 0x38, 0xB6, 0x30, 0xD8, 0x4B, 0xE5, 0xD6, 0x39, 0x38, + 0x1E, 0x91, 0xDE, 0xB4, 0x5C, 0xFE, 0x77, 0x8F, 0x63, 0x7C, 0x10, 0x01 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 72 * 6]; +} _EC_NIST_CHAR2_571B = { + { + NID_X9_62_characteristic_two_field, 20, 72, 2 + }, + { + /* seed */ + 0x2A, 0xA0, 0x58, 0xF7, 0x3A, 0x0E, 0x33, 0xAB, 0x48, 0x6B, 0x0F, 0x61, + 0x04, 0x10, 0xC5, 0x3A, 0x7F, 0x13, 0x23, 0x10, + /* p */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x25, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* b */ + 0x02, 0xF4, 0x0E, 0x7E, 0x22, 0x21, 0xF2, 0x95, 0xDE, 0x29, 0x71, 0x17, + 0xB7, 0xF3, 0xD6, 0x2F, 0x5C, 0x6A, 0x97, 0xFF, 0xCB, 0x8C, 0xEF, 0xF1, + 0xCD, 0x6B, 0xA8, 0xCE, 0x4A, 0x9A, 0x18, 0xAD, 0x84, 0xFF, 0xAB, 0xBD, + 0x8E, 0xFA, 0x59, 0x33, 0x2B, 0xE7, 0xAD, 0x67, 0x56, 0xA6, 0x6E, 0x29, + 0x4A, 0xFD, 0x18, 0x5A, 0x78, 0xFF, 0x12, 0xAA, 0x52, 0x0E, 0x4D, 0xE7, + 0x39, 0xBA, 0xCA, 0x0C, 0x7F, 0xFE, 0xFF, 0x7F, 0x29, 0x55, 0x72, 0x7A, + /* x */ + 0x03, 0x03, 0x00, 0x1D, 0x34, 0xB8, 0x56, 0x29, 0x6C, 0x16, 0xC0, 0xD4, + 0x0D, 0x3C, 0xD7, 0x75, 0x0A, 0x93, 0xD1, 0xD2, 0x95, 0x5F, 0xA8, 0x0A, + 0xA5, 0xF4, 0x0F, 0xC8, 0xDB, 0x7B, 0x2A, 0xBD, 0xBD, 0xE5, 0x39, 0x50, + 0xF4, 0xC0, 0xD2, 0x93, 0xCD, 0xD7, 0x11, 0xA3, 0x5B, 0x67, 0xFB, 0x14, + 0x99, 0xAE, 0x60, 0x03, 0x86, 0x14, 0xF1, 0x39, 0x4A, 0xBF, 0xA3, 0xB4, + 0xC8, 0x50, 0xD9, 0x27, 0xE1, 0xE7, 0x76, 0x9C, 0x8E, 0xEC, 0x2D, 0x19, + /* y */ + 0x03, 0x7B, 0xF2, 0x73, 0x42, 0xDA, 0x63, 0x9B, 0x6D, 0xCC, 0xFF, 0xFE, + 0xB7, 0x3D, 0x69, 0xD7, 0x8C, 0x6C, 0x27, 0xA6, 0x00, 0x9C, 0xBB, 0xCA, + 0x19, 0x80, 0xF8, 0x53, 0x39, 0x21, 0xE8, 0xA6, 0x84, 0x42, 0x3E, 0x43, + 0xBA, 0xB0, 0x8A, 0x57, 0x62, 0x91, 0xAF, 0x8F, 0x46, 0x1B, 0xB2, 0xA8, + 0xB3, 0x53, 0x1D, 0x2F, 0x04, 0x85, 0xC1, 0x9B, 0x16, 0xE2, 0xF1, 0x51, + 0x6E, 0x23, 0xDD, 0x3C, 0x1A, 0x48, 0x27, 0xAF, 0x1B, 0x8A, 0xC1, 0x5B, + /* order */ + 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE6, 0x61, 0xCE, 0x18, 0xFF, 0x55, 0x98, 0x73, 0x08, 0x05, 0x9B, 0x18, + 0x68, 0x23, 0x85, 0x1E, 0xC7, 0xDD, 0x9C, 0xA1, 0x16, 0x1D, 0xE9, 0x3D, + 0x51, 0x74, 0xD6, 0x6E, 0x83, 0x82, 0xE9, 0xBB, 0x2F, 0xE8, 0x4E, 0x47 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 21 * 6]; +} _EC_X9_62_CHAR2_163V1 = { + { + NID_X9_62_characteristic_two_field, 20, 21, 2 + }, + { + /* seed */ + 0xD2, 0xC0, 0xFB, 0x15, 0x76, 0x08, 0x60, 0xDE, 0xF1, 0xEE, 0xF4, 0xD6, + 0x96, 0xE6, 0x76, 0x87, 0x56, 0x15, 0x17, 0x54, + /* p */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, + /* a */ + 0x07, 0x25, 0x46, 0xB5, 0x43, 0x52, 0x34, 0xA4, 0x22, 0xE0, 0x78, 0x96, + 0x75, 0xF4, 0x32, 0xC8, 0x94, 0x35, 0xDE, 0x52, 0x42, + /* b */ + 0x00, 0xC9, 0x51, 0x7D, 0x06, 0xD5, 0x24, 0x0D, 0x3C, 0xFF, 0x38, 0xC7, + 0x4B, 0x20, 0xB6, 0xCD, 0x4D, 0x6F, 0x9D, 0xD4, 0xD9, + /* x */ + 0x07, 0xAF, 0x69, 0x98, 0x95, 0x46, 0x10, 0x3D, 0x79, 0x32, 0x9F, 0xCC, + 0x3D, 0x74, 0x88, 0x0F, 0x33, 0xBB, 0xE8, 0x03, 0xCB, + /* y */ + 0x01, 0xEC, 0x23, 0x21, 0x1B, 0x59, 0x66, 0xAD, 0xEA, 0x1D, 0x3F, 0x87, + 0xF7, 0xEA, 0x58, 0x48, 0xAE, 0xF0, 0xB7, 0xCA, 0x9F, + /* order */ + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE6, + 0x0F, 0xC8, 0x82, 0x1C, 0xC7, 0x4D, 0xAE, 0xAF, 0xC1 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 21 * 6]; +} _EC_X9_62_CHAR2_163V2 = { + { + NID_X9_62_characteristic_two_field, 20, 21, 2 + }, + { + /* seed */ + 0x53, 0x81, 0x4C, 0x05, 0x0D, 0x44, 0xD6, 0x96, 0xE6, 0x76, 0x87, 0x56, + 0x15, 0x17, 0x58, 0x0C, 0xA4, 0xE2, 0x9F, 0xFD, + /* p */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, + /* a */ + 0x01, 0x08, 0xB3, 0x9E, 0x77, 0xC4, 0xB1, 0x08, 0xBE, 0xD9, 0x81, 0xED, + 0x0E, 0x89, 0x0E, 0x11, 0x7C, 0x51, 0x1C, 0xF0, 0x72, + /* b */ + 0x06, 0x67, 0xAC, 0xEB, 0x38, 0xAF, 0x4E, 0x48, 0x8C, 0x40, 0x74, 0x33, + 0xFF, 0xAE, 0x4F, 0x1C, 0x81, 0x16, 0x38, 0xDF, 0x20, + /* x */ + 0x00, 0x24, 0x26, 0x6E, 0x4E, 0xB5, 0x10, 0x6D, 0x0A, 0x96, 0x4D, 0x92, + 0xC4, 0x86, 0x0E, 0x26, 0x71, 0xDB, 0x9B, 0x6C, 0xC5, + /* y */ + 0x07, 0x9F, 0x68, 0x4D, 0xDF, 0x66, 0x84, 0xC5, 0xCD, 0x25, 0x8B, 0x38, + 0x90, 0x02, 0x1B, 0x23, 0x86, 0xDF, 0xD1, 0x9F, 0xC5, + /* order */ + 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xF6, + 0x4D, 0xE1, 0x15, 0x1A, 0xDB, 0xB7, 0x8F, 0x10, 0xA7 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 21 * 6]; +} _EC_X9_62_CHAR2_163V3 = { + { + NID_X9_62_characteristic_two_field, 20, 21, 2 + }, + { + /* seed */ + 0x50, 0xCB, 0xF1, 0xD9, 0x5C, 0xA9, 0x4D, 0x69, 0x6E, 0x67, 0x68, 0x75, + 0x61, 0x51, 0x75, 0xF1, 0x6A, 0x36, 0xA3, 0xB8, + /* p */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, + /* a */ + 0x07, 0xA5, 0x26, 0xC6, 0x3D, 0x3E, 0x25, 0xA2, 0x56, 0xA0, 0x07, 0x69, + 0x9F, 0x54, 0x47, 0xE3, 0x2A, 0xE4, 0x56, 0xB5, 0x0E, + /* b */ + 0x03, 0xF7, 0x06, 0x17, 0x98, 0xEB, 0x99, 0xE2, 0x38, 0xFD, 0x6F, 0x1B, + 0xF9, 0x5B, 0x48, 0xFE, 0xEB, 0x48, 0x54, 0x25, 0x2B, + /* x */ + 0x02, 0xF9, 0xF8, 0x7B, 0x7C, 0x57, 0x4D, 0x0B, 0xDE, 0xCF, 0x8A, 0x22, + 0xE6, 0x52, 0x47, 0x75, 0xF9, 0x8C, 0xDE, 0xBD, 0xCB, + /* y */ + 0x05, 0xB9, 0x35, 0x59, 0x0C, 0x15, 0x5E, 0x17, 0xEA, 0x48, 0xEB, 0x3F, + 0xF3, 0x71, 0x8B, 0x89, 0x3D, 0xF5, 0x9A, 0x05, 0xD0, + /* order */ + 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x1A, + 0xEE, 0x14, 0x0F, 0x11, 0x0A, 0xFF, 0x96, 0x13, 0x09 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 23 * 6]; +} _EC_X9_62_CHAR2_176V1 = { + { + NID_X9_62_characteristic_two_field, 0, 23, 0xFF6E + }, + { + /* no seed */ + /* p */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x07, + /* a */ + 0x00, 0xE4, 0xE6, 0xDB, 0x29, 0x95, 0x06, 0x5C, 0x40, 0x7D, 0x9D, 0x39, + 0xB8, 0xD0, 0x96, 0x7B, 0x96, 0x70, 0x4B, 0xA8, 0xE9, 0xC9, 0x0B, + /* b */ + 0x00, 0x5D, 0xDA, 0x47, 0x0A, 0xBE, 0x64, 0x14, 0xDE, 0x8E, 0xC1, 0x33, + 0xAE, 0x28, 0xE9, 0xBB, 0xD7, 0xFC, 0xEC, 0x0A, 0xE0, 0xFF, 0xF2, + /* x */ + 0x00, 0x8D, 0x16, 0xC2, 0x86, 0x67, 0x98, 0xB6, 0x00, 0xF9, 0xF0, 0x8B, + 0xB4, 0xA8, 0xE8, 0x60, 0xF3, 0x29, 0x8C, 0xE0, 0x4A, 0x57, 0x98, + /* y */ + 0x00, 0x6F, 0xA4, 0x53, 0x9C, 0x2D, 0xAD, 0xDD, 0xD6, 0xBA, 0xB5, 0x16, + 0x7D, 0x61, 0xB4, 0x36, 0xE1, 0xD9, 0x2B, 0xB1, 0x6A, 0x56, 0x2C, + /* order */ + 0x00, 0x00, 0x01, 0x00, 0x92, 0x53, 0x73, 0x97, 0xEC, 0xA4, 0xF6, 0x14, + 0x57, 0x99, 0xD6, 0x2B, 0x0A, 0x19, 0xCE, 0x06, 0xFE, 0x26, 0xAD + } +}; - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x33,0x8f, +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 24 * 6]; +} _EC_X9_62_CHAR2_191V1 = { + { + NID_X9_62_characteristic_two_field, 20, 24, 2 + }, + { + /* seed */ + 0x4E, 0x13, 0xCA, 0x54, 0x27, 0x44, 0xD6, 0x96, 0xE6, 0x76, 0x87, 0x56, + 0x15, 0x17, 0x55, 0x2F, 0x27, 0x9A, 0x8C, 0x84, + /* p */ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, + /* a */ + 0x28, 0x66, 0x53, 0x7B, 0x67, 0x67, 0x52, 0x63, 0x6A, 0x68, 0xF5, 0x65, + 0x54, 0xE1, 0x26, 0x40, 0x27, 0x6B, 0x64, 0x9E, 0xF7, 0x52, 0x62, 0x67, + /* b */ + 0x2E, 0x45, 0xEF, 0x57, 0x1F, 0x00, 0x78, 0x6F, 0x67, 0xB0, 0x08, 0x1B, + 0x94, 0x95, 0xA3, 0xD9, 0x54, 0x62, 0xF5, 0xDE, 0x0A, 0xA1, 0x85, 0xEC, + /* x */ + 0x36, 0xB3, 0xDA, 0xF8, 0xA2, 0x32, 0x06, 0xF9, 0xC4, 0xF2, 0x99, 0xD7, + 0xB2, 0x1A, 0x9C, 0x36, 0x91, 0x37, 0xF2, 0xC8, 0x4A, 0xE1, 0xAA, 0x0D, + /* y */ + 0x76, 0x5B, 0xE7, 0x34, 0x33, 0xB3, 0xF9, 0x5E, 0x33, 0x29, 0x32, 0xE7, + 0x0E, 0xA2, 0x45, 0xCA, 0x24, 0x18, 0xEA, 0x0E, 0xF9, 0x80, 0x18, 0xFB, + /* order */ + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0xA2, 0x0E, 0x90, 0xC3, 0x90, 0x67, 0xC8, 0x93, 0xBB, 0xB9, 0xA5 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 24 * 6]; +} _EC_X9_62_CHAR2_191V2 = { + { + NID_X9_62_characteristic_two_field, 20, 24, 4 + }, + { + /* seed */ + 0x08, 0x71, 0xEF, 0x2F, 0xEF, 0x24, 0xD6, 0x96, 0xE6, 0x76, 0x87, 0x56, + 0x15, 0x17, 0x58, 0xBE, 0xE0, 0xD9, 0x5C, 0x15, + /* p */ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, + /* a */ + 0x40, 0x10, 0x28, 0x77, 0x4D, 0x77, 0x77, 0xC7, 0xB7, 0x66, 0x6D, 0x13, + 0x66, 0xEA, 0x43, 0x20, 0x71, 0x27, 0x4F, 0x89, 0xFF, 0x01, 0xE7, 0x18, + /* b */ + 0x06, 0x20, 0x04, 0x8D, 0x28, 0xBC, 0xBD, 0x03, 0xB6, 0x24, 0x9C, 0x99, + 0x18, 0x2B, 0x7C, 0x8C, 0xD1, 0x97, 0x00, 0xC3, 0x62, 0xC4, 0x6A, 0x01, + /* x */ + 0x38, 0x09, 0xB2, 0xB7, 0xCC, 0x1B, 0x28, 0xCC, 0x5A, 0x87, 0x92, 0x6A, + 0xAD, 0x83, 0xFD, 0x28, 0x78, 0x9E, 0x81, 0xE2, 0xC9, 0xE3, 0xBF, 0x10, + /* y */ + 0x17, 0x43, 0x43, 0x86, 0x62, 0x6D, 0x14, 0xF3, 0xDB, 0xF0, 0x17, 0x60, + 0xD9, 0x21, 0x3A, 0x3E, 0x1C, 0xF3, 0x7A, 0xEC, 0x43, 0x7D, 0x66, 0x8A, + /* order */ + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x50, 0x50, 0x8C, 0xB8, 0x9F, 0x65, 0x28, 0x24, 0xE0, 0x6B, 0x81, 0x73 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 24 * 6]; +} _EC_X9_62_CHAR2_191V3 = { + { + NID_X9_62_characteristic_two_field, 20, 24, 6 + }, + { + /* seed */ + 0xE0, 0x53, 0x51, 0x2D, 0xC6, 0x84, 0xD6, 0x96, 0xE6, 0x76, 0x87, 0x56, + 0x15, 0x17, 0x50, 0x67, 0xAE, 0x78, 0x6D, 0x1F, + /* p */ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, + /* a */ + 0x6C, 0x01, 0x07, 0x47, 0x56, 0x09, 0x91, 0x22, 0x22, 0x10, 0x56, 0x91, + 0x1C, 0x77, 0xD7, 0x7E, 0x77, 0xA7, 0x77, 0xE7, 0xE7, 0xE7, 0x7F, 0xCB, + /* b */ + 0x71, 0xFE, 0x1A, 0xF9, 0x26, 0xCF, 0x84, 0x79, 0x89, 0xEF, 0xEF, 0x8D, + 0xB4, 0x59, 0xF6, 0x63, 0x94, 0xD9, 0x0F, 0x32, 0xAD, 0x3F, 0x15, 0xE8, + /* x */ + 0x37, 0x5D, 0x4C, 0xE2, 0x4F, 0xDE, 0x43, 0x44, 0x89, 0xDE, 0x87, 0x46, + 0xE7, 0x17, 0x86, 0x01, 0x50, 0x09, 0xE6, 0x6E, 0x38, 0xA9, 0x26, 0xDD, + /* y */ + 0x54, 0x5A, 0x39, 0x17, 0x61, 0x96, 0x57, 0x5D, 0x98, 0x59, 0x99, 0x36, + 0x6E, 0x6A, 0xD3, 0x4C, 0xE0, 0xA7, 0x7C, 0xD7, 0x12, 0x7B, 0x06, 0xBE, + /* order */ + 0x15, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x61, 0x0C, 0x0B, 0x19, 0x68, 0x12, 0xBF, 0xB6, 0x28, 0x8A, 0x3E, 0xA3 + } +}; - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* x */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7b, +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 27 * 6]; +} _EC_X9_62_CHAR2_208W1 = { + { + NID_X9_62_characteristic_two_field, 0, 27, 0xFE48 + }, + { + /* no seed */ + /* p */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x07, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + /* b */ + 0x00, 0xC8, 0x61, 0x9E, 0xD4, 0x5A, 0x62, 0xE6, 0x21, 0x2E, 0x11, 0x60, + 0x34, 0x9E, 0x2B, 0xFA, 0x84, 0x44, 0x39, 0xFA, 0xFC, 0x2A, 0x3F, 0xD1, + 0x63, 0x8F, 0x9E, + /* x */ + 0x00, 0x89, 0xFD, 0xFB, 0xE4, 0xAB, 0xE1, 0x93, 0xDF, 0x95, 0x59, 0xEC, + 0xF0, 0x7A, 0xC0, 0xCE, 0x78, 0x55, 0x4E, 0x27, 0x84, 0xEB, 0x8C, 0x1E, + 0xD1, 0xA5, 0x7A, + /* y */ + 0x00, 0x0F, 0x55, 0xB5, 0x1A, 0x06, 0xE7, 0x8E, 0x9A, 0xC3, 0x8A, 0x03, + 0x5F, 0xF5, 0x20, 0xD8, 0xB0, 0x17, 0x81, 0xBE, 0xB1, 0xA6, 0xBB, 0x08, + 0x61, 0x7D, 0xE3, + /* order */ + 0x00, 0x00, 0x01, 0x01, 0xBA, 0xF9, 0x5C, 0x97, 0x23, 0xC5, 0x7B, 0x6C, + 0x21, 0xDA, 0x2E, 0xFF, 0x2D, 0x5E, 0xD5, 0x88, 0xBD, 0xD5, 0x71, 0x7E, + 0x21, 0x2F, 0x9D + } +}; - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* y */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xc8, +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 30 * 6]; +} _EC_X9_62_CHAR2_239V1 = { + { + NID_X9_62_characteristic_two_field, 20, 30, 4 + }, + { + /* seed */ + 0xD3, 0x4B, 0x9A, 0x4D, 0x69, 0x6E, 0x67, 0x68, 0x75, 0x61, 0x51, 0x75, + 0xCA, 0x71, 0xB9, 0x20, 0xBF, 0xEF, 0xB0, 0x5D, + /* p */ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, + /* a */ + 0x32, 0x01, 0x08, 0x57, 0x07, 0x7C, 0x54, 0x31, 0x12, 0x3A, 0x46, 0xB8, + 0x08, 0x90, 0x67, 0x56, 0xF5, 0x43, 0x42, 0x3E, 0x8D, 0x27, 0x87, 0x75, + 0x78, 0x12, 0x57, 0x78, 0xAC, 0x76, + /* b */ + 0x79, 0x04, 0x08, 0xF2, 0xEE, 0xDA, 0xF3, 0x92, 0xB0, 0x12, 0xED, 0xEF, + 0xB3, 0x39, 0x2F, 0x30, 0xF4, 0x32, 0x7C, 0x0C, 0xA3, 0xF3, 0x1F, 0xC3, + 0x83, 0xC4, 0x22, 0xAA, 0x8C, 0x16, + /* x */ + 0x57, 0x92, 0x70, 0x98, 0xFA, 0x93, 0x2E, 0x7C, 0x0A, 0x96, 0xD3, 0xFD, + 0x5B, 0x70, 0x6E, 0xF7, 0xE5, 0xF5, 0xC1, 0x56, 0xE1, 0x6B, 0x7E, 0x7C, + 0x86, 0x03, 0x85, 0x52, 0xE9, 0x1D, + /* y */ + 0x61, 0xD8, 0xEE, 0x50, 0x77, 0xC3, 0x3F, 0xEC, 0xF6, 0xF1, 0xA1, 0x6B, + 0x26, 0x8D, 0xE4, 0x69, 0xC3, 0xC7, 0x74, 0x4E, 0xA9, 0xA9, 0x71, 0x64, + 0x9F, 0xC7, 0xA9, 0x61, 0x63, 0x05, + /* order */ + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0F, 0x4D, 0x42, 0xFF, 0xE1, 0x49, 0x2A, 0x49, 0x93, + 0xF1, 0xCA, 0xD6, 0x66, 0xE4, 0x47 + } +}; - 0x02,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA, /* order */ - 0xC7,0xF3,0xC7,0x88,0x1B,0xD0,0x86,0x8F,0xA8,0x6C } - }; +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 30 * 6]; +} _EC_X9_62_CHAR2_239V2 = { + { + NID_X9_62_characteristic_two_field, 20, 30, 6 + }, + { + /* seed */ + 0x2A, 0xA6, 0x98, 0x2F, 0xDF, 0xA4, 0xD6, 0x96, 0xE6, 0x76, 0x87, 0x56, + 0x15, 0x17, 0x5D, 0x26, 0x67, 0x27, 0x27, 0x7D, + /* p */ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, + /* a */ + 0x42, 0x30, 0x01, 0x77, 0x57, 0xA7, 0x67, 0xFA, 0xE4, 0x23, 0x98, 0x56, + 0x9B, 0x74, 0x63, 0x25, 0xD4, 0x53, 0x13, 0xAF, 0x07, 0x66, 0x26, 0x64, + 0x79, 0xB7, 0x56, 0x54, 0xE6, 0x5F, + /* b */ + 0x50, 0x37, 0xEA, 0x65, 0x41, 0x96, 0xCF, 0xF0, 0xCD, 0x82, 0xB2, 0xC1, + 0x4A, 0x2F, 0xCF, 0x2E, 0x3F, 0xF8, 0x77, 0x52, 0x85, 0xB5, 0x45, 0x72, + 0x2F, 0x03, 0xEA, 0xCD, 0xB7, 0x4B, + /* x */ + 0x28, 0xF9, 0xD0, 0x4E, 0x90, 0x00, 0x69, 0xC8, 0xDC, 0x47, 0xA0, 0x85, + 0x34, 0xFE, 0x76, 0xD2, 0xB9, 0x00, 0xB7, 0xD7, 0xEF, 0x31, 0xF5, 0x70, + 0x9F, 0x20, 0x0C, 0x4C, 0xA2, 0x05, + /* y */ + 0x56, 0x67, 0x33, 0x4C, 0x45, 0xAF, 0xF3, 0xB5, 0xA0, 0x3B, 0xAD, 0x9D, + 0xD7, 0x5E, 0x2C, 0x71, 0xA9, 0x93, 0x62, 0x56, 0x7D, 0x54, 0x53, 0xF7, + 0xFA, 0x6E, 0x22, 0x7E, 0xC8, 0x33, + /* order */ + 0x15, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x3C, 0x6F, 0x28, 0x85, 0x25, 0x9C, 0x31, 0xE3, 0xFC, + 0xDF, 0x15, 0x46, 0x24, 0x52, 0x2D + } +}; -/* NOTE: The of curves over a extension field of non prime degree - * is not recommended (Weil-descent). - * As the group order is not a prime this curve is not suitable - * for ECDSA. +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 30 * 6]; +} _EC_X9_62_CHAR2_239V3 = { + { + NID_X9_62_characteristic_two_field, 20, 30, 0xA + }, + { + /* seed */ + 0x9E, 0x07, 0x6F, 0x4D, 0x69, 0x6E, 0x67, 0x68, 0x75, 0x61, 0x51, 0x75, + 0xE1, 0x1E, 0x9F, 0xDD, 0x77, 0xF9, 0x20, 0x41, + /* p */ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, + /* a */ + 0x01, 0x23, 0x87, 0x74, 0x66, 0x6A, 0x67, 0x76, 0x6D, 0x66, 0x76, 0xF7, + 0x78, 0xE6, 0x76, 0xB6, 0x69, 0x99, 0x17, 0x66, 0x66, 0xE6, 0x87, 0x66, + 0x6D, 0x87, 0x66, 0xC6, 0x6A, 0x9F, + /* b */ + 0x6A, 0x94, 0x19, 0x77, 0xBA, 0x9F, 0x6A, 0x43, 0x51, 0x99, 0xAC, 0xFC, + 0x51, 0x06, 0x7E, 0xD5, 0x87, 0xF5, 0x19, 0xC5, 0xEC, 0xB5, 0x41, 0xB8, + 0xE4, 0x41, 0x11, 0xDE, 0x1D, 0x40, + /* x */ + 0x70, 0xF6, 0xE9, 0xD0, 0x4D, 0x28, 0x9C, 0x4E, 0x89, 0x91, 0x3C, 0xE3, + 0x53, 0x0B, 0xFD, 0xE9, 0x03, 0x97, 0x7D, 0x42, 0xB1, 0x46, 0xD5, 0x39, + 0xBF, 0x1B, 0xDE, 0x4E, 0x9C, 0x92, + /* y */ + 0x2E, 0x5A, 0x0E, 0xAF, 0x6E, 0x5E, 0x13, 0x05, 0xB9, 0x00, 0x4D, 0xCE, + 0x5C, 0x0E, 0xD7, 0xFE, 0x59, 0xA3, 0x56, 0x08, 0xF3, 0x38, 0x37, 0xC8, + 0x16, 0xD8, 0x0B, 0x79, 0xF4, 0x61, + /* order */ + 0x0C, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xAC, 0x49, 0x12, 0xD2, 0xD9, 0xDF, 0x90, 0x3E, 0xF9, + 0x88, 0x8B, 0x8A, 0x0E, 0x4C, 0xFF + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 35 * 6]; +} _EC_X9_62_CHAR2_272W1 = { + { + NID_X9_62_characteristic_two_field, 0, 35, 0xFF06 + }, + { + /* no seed */ + /* p */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, + /* a */ + 0x00, 0x91, 0xA0, 0x91, 0xF0, 0x3B, 0x5F, 0xBA, 0x4A, 0xB2, 0xCC, 0xF4, + 0x9C, 0x4E, 0xDD, 0x22, 0x0F, 0xB0, 0x28, 0x71, 0x2D, 0x42, 0xBE, 0x75, + 0x2B, 0x2C, 0x40, 0x09, 0x4D, 0xBA, 0xCD, 0xB5, 0x86, 0xFB, 0x20, + /* b */ + 0x00, 0x71, 0x67, 0xEF, 0xC9, 0x2B, 0xB2, 0xE3, 0xCE, 0x7C, 0x8A, 0xAA, + 0xFF, 0x34, 0xE1, 0x2A, 0x9C, 0x55, 0x70, 0x03, 0xD7, 0xC7, 0x3A, 0x6F, + 0xAF, 0x00, 0x3F, 0x99, 0xF6, 0xCC, 0x84, 0x82, 0xE5, 0x40, 0xF7, + /* x */ + 0x00, 0x61, 0x08, 0xBA, 0xBB, 0x2C, 0xEE, 0xBC, 0xF7, 0x87, 0x05, 0x8A, + 0x05, 0x6C, 0xBE, 0x0C, 0xFE, 0x62, 0x2D, 0x77, 0x23, 0xA2, 0x89, 0xE0, + 0x8A, 0x07, 0xAE, 0x13, 0xEF, 0x0D, 0x10, 0xD1, 0x71, 0xDD, 0x8D, + /* y */ + 0x00, 0x10, 0xC7, 0x69, 0x57, 0x16, 0x85, 0x1E, 0xEF, 0x6B, 0xA7, 0xF6, + 0x87, 0x2E, 0x61, 0x42, 0xFB, 0xD2, 0x41, 0xB8, 0x30, 0xFF, 0x5E, 0xFC, + 0xAC, 0xEC, 0xCA, 0xB0, 0x5E, 0x02, 0x00, 0x5D, 0xDE, 0x9D, 0x23, + /* order */ + 0x00, 0x00, 0x01, 0x00, 0xFA, 0xF5, 0x13, 0x54, 0xE0, 0xE3, 0x9E, 0x48, + 0x92, 0xDF, 0x6E, 0x31, 0x9C, 0x72, 0xC8, 0x16, 0x16, 0x03, 0xFA, 0x45, + 0xAA, 0x7B, 0x99, 0x8A, 0x16, 0x7B, 0x8F, 0x1E, 0x62, 0x95, 0x21 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 39 * 6]; +} _EC_X9_62_CHAR2_304W1 = { + { + NID_X9_62_characteristic_two_field, 0, 39, 0xFE2E + }, + { + /* no seed */ + /* p */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x07, + /* a */ + 0x00, 0xFD, 0x0D, 0x69, 0x31, 0x49, 0xA1, 0x18, 0xF6, 0x51, 0xE6, 0xDC, + 0xE6, 0x80, 0x20, 0x85, 0x37, 0x7E, 0x5F, 0x88, 0x2D, 0x1B, 0x51, 0x0B, + 0x44, 0x16, 0x00, 0x74, 0xC1, 0x28, 0x80, 0x78, 0x36, 0x5A, 0x03, 0x96, + 0xC8, 0xE6, 0x81, + /* b */ + 0x00, 0xBD, 0xDB, 0x97, 0xE5, 0x55, 0xA5, 0x0A, 0x90, 0x8E, 0x43, 0xB0, + 0x1C, 0x79, 0x8E, 0xA5, 0xDA, 0xA6, 0x78, 0x8F, 0x1E, 0xA2, 0x79, 0x4E, + 0xFC, 0xF5, 0x71, 0x66, 0xB8, 0xC1, 0x40, 0x39, 0x60, 0x1E, 0x55, 0x82, + 0x73, 0x40, 0xBE, + /* x */ + 0x00, 0x19, 0x7B, 0x07, 0x84, 0x5E, 0x9B, 0xE2, 0xD9, 0x6A, 0xDB, 0x0F, + 0x5F, 0x3C, 0x7F, 0x2C, 0xFF, 0xBD, 0x7A, 0x3E, 0xB8, 0xB6, 0xFE, 0xC3, + 0x5C, 0x7F, 0xD6, 0x7F, 0x26, 0xDD, 0xF6, 0x28, 0x5A, 0x64, 0x4F, 0x74, + 0x0A, 0x26, 0x14, + /* y */ + 0x00, 0xE1, 0x9F, 0xBE, 0xB7, 0x6E, 0x0D, 0xA1, 0x71, 0x51, 0x7E, 0xCF, + 0x40, 0x1B, 0x50, 0x28, 0x9B, 0xF0, 0x14, 0x10, 0x32, 0x88, 0x52, 0x7A, + 0x9B, 0x41, 0x6A, 0x10, 0x5E, 0x80, 0x26, 0x0B, 0x54, 0x9F, 0xDC, 0x1B, + 0x92, 0xC0, 0x3B, + /* order */ + 0x00, 0x00, 0x01, 0x01, 0xD5, 0x56, 0x57, 0x2A, 0xAB, 0xAC, 0x80, 0x01, + 0x01, 0xD5, 0x56, 0x57, 0x2A, 0xAB, 0xAC, 0x80, 0x01, 0x02, 0x2D, 0x5C, + 0x91, 0xDD, 0x17, 0x3F, 0x8F, 0xB5, 0x61, 0xDA, 0x68, 0x99, 0x16, 0x44, + 0x43, 0x05, 0x1D + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[20 + 45 * 6]; +} _EC_X9_62_CHAR2_359V1 = { + { + NID_X9_62_characteristic_two_field, 20, 45, 0x4C + }, + { + /* seed */ + 0x2B, 0x35, 0x49, 0x20, 0xB7, 0x24, 0xD6, 0x96, 0xE6, 0x76, 0x87, 0x56, + 0x15, 0x17, 0x58, 0x5B, 0xA1, 0x33, 0x2D, 0xC6, + /* p */ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* a */ + 0x56, 0x67, 0x67, 0x6A, 0x65, 0x4B, 0x20, 0x75, 0x4F, 0x35, 0x6E, 0xA9, + 0x20, 0x17, 0xD9, 0x46, 0x56, 0x7C, 0x46, 0x67, 0x55, 0x56, 0xF1, 0x95, + 0x56, 0xA0, 0x46, 0x16, 0xB5, 0x67, 0xD2, 0x23, 0xA5, 0xE0, 0x56, 0x56, + 0xFB, 0x54, 0x90, 0x16, 0xA9, 0x66, 0x56, 0xA5, 0x57, + /* b */ + 0x24, 0x72, 0xE2, 0xD0, 0x19, 0x7C, 0x49, 0x36, 0x3F, 0x1F, 0xE7, 0xF5, + 0xB6, 0xDB, 0x07, 0x5D, 0x52, 0xB6, 0x94, 0x7D, 0x13, 0x5D, 0x8C, 0xA4, + 0x45, 0x80, 0x5D, 0x39, 0xBC, 0x34, 0x56, 0x26, 0x08, 0x96, 0x87, 0x74, + 0x2B, 0x63, 0x29, 0xE7, 0x06, 0x80, 0x23, 0x19, 0x88, + /* x */ + 0x3C, 0x25, 0x8E, 0xF3, 0x04, 0x77, 0x67, 0xE7, 0xED, 0xE0, 0xF1, 0xFD, + 0xAA, 0x79, 0xDA, 0xEE, 0x38, 0x41, 0x36, 0x6A, 0x13, 0x2E, 0x16, 0x3A, + 0xCE, 0xD4, 0xED, 0x24, 0x01, 0xDF, 0x9C, 0x6B, 0xDC, 0xDE, 0x98, 0xE8, + 0xE7, 0x07, 0xC0, 0x7A, 0x22, 0x39, 0xB1, 0xB0, 0x97, + /* y */ + 0x53, 0xD7, 0xE0, 0x85, 0x29, 0x54, 0x70, 0x48, 0x12, 0x1E, 0x9C, 0x95, + 0xF3, 0x79, 0x1D, 0xD8, 0x04, 0x96, 0x39, 0x48, 0xF3, 0x4F, 0xAE, 0x7B, + 0xF4, 0x4E, 0xA8, 0x23, 0x65, 0xDC, 0x78, 0x68, 0xFE, 0x57, 0xE4, 0xAE, + 0x2D, 0xE2, 0x11, 0x30, 0x5A, 0x40, 0x71, 0x04, 0xBD, + /* order */ + 0x01, 0xAF, 0x28, 0x6B, 0xCA, 0x1A, 0xF2, 0x86, 0xBC, 0xA1, 0xAF, 0x28, + 0x6B, 0xCA, 0x1A, 0xF2, 0x86, 0xBC, 0xA1, 0xAF, 0x28, 0x6B, 0xC9, 0xFB, + 0x8F, 0x6B, 0x85, 0xC5, 0x56, 0x89, 0x2C, 0x20, 0xA7, 0xEB, 0x96, 0x4F, + 0xE7, 0x71, 0x9E, 0x74, 0xF4, 0x90, 0x75, 0x8D, 0x3B + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 47 * 6]; +} _EC_X9_62_CHAR2_368W1 = { + { + NID_X9_62_characteristic_two_field, 0, 47, 0xFF70 + }, + { + /* no seed */ + /* p */ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + /* a */ + 0x00, 0xE0, 0xD2, 0xEE, 0x25, 0x09, 0x52, 0x06, 0xF5, 0xE2, 0xA4, 0xF9, + 0xED, 0x22, 0x9F, 0x1F, 0x25, 0x6E, 0x79, 0xA0, 0xE2, 0xB4, 0x55, 0x97, + 0x0D, 0x8D, 0x0D, 0x86, 0x5B, 0xD9, 0x47, 0x78, 0xC5, 0x76, 0xD6, 0x2F, + 0x0A, 0xB7, 0x51, 0x9C, 0xCD, 0x2A, 0x1A, 0x90, 0x6A, 0xE3, 0x0D, + /* b */ + 0x00, 0xFC, 0x12, 0x17, 0xD4, 0x32, 0x0A, 0x90, 0x45, 0x2C, 0x76, 0x0A, + 0x58, 0xED, 0xCD, 0x30, 0xC8, 0xDD, 0x06, 0x9B, 0x3C, 0x34, 0x45, 0x38, + 0x37, 0xA3, 0x4E, 0xD5, 0x0C, 0xB5, 0x49, 0x17, 0xE1, 0xC2, 0x11, 0x2D, + 0x84, 0xD1, 0x64, 0xF4, 0x44, 0xF8, 0xF7, 0x47, 0x86, 0x04, 0x6A, + /* x */ + 0x00, 0x10, 0x85, 0xE2, 0x75, 0x53, 0x81, 0xDC, 0xCC, 0xE3, 0xC1, 0x55, + 0x7A, 0xFA, 0x10, 0xC2, 0xF0, 0xC0, 0xC2, 0x82, 0x56, 0x46, 0xC5, 0xB3, + 0x4A, 0x39, 0x4C, 0xBC, 0xFA, 0x8B, 0xC1, 0x6B, 0x22, 0xE7, 0xE7, 0x89, + 0xE9, 0x27, 0xBE, 0x21, 0x6F, 0x02, 0xE1, 0xFB, 0x13, 0x6A, 0x5F, + /* y */ + 0x00, 0x7B, 0x3E, 0xB1, 0xBD, 0xDC, 0xBA, 0x62, 0xD5, 0xD8, 0xB2, 0x05, + 0x9B, 0x52, 0x57, 0x97, 0xFC, 0x73, 0x82, 0x2C, 0x59, 0x05, 0x9C, 0x62, + 0x3A, 0x45, 0xFF, 0x38, 0x43, 0xCE, 0xE8, 0xF8, 0x7C, 0xD1, 0x85, 0x5A, + 0xDA, 0xA8, 0x1E, 0x2A, 0x07, 0x50, 0xB8, 0x0F, 0xDA, 0x23, 0x10, + /* order */ + 0x00, 0x00, 0x01, 0x00, 0x90, 0x51, 0x2D, 0xA9, 0xAF, 0x72, 0xB0, 0x83, + 0x49, 0xD9, 0x8A, 0x5D, 0xD4, 0xC7, 0xB0, 0x53, 0x2E, 0xCA, 0x51, 0xCE, + 0x03, 0xE2, 0xD1, 0x0F, 0x3B, 0x7A, 0xC5, 0x79, 0xBD, 0x87, 0xE9, 0x09, + 0xAE, 0x40, 0xA6, 0xF1, 0x31, 0xE9, 0xCF, 0xCE, 0x5B, 0xD9, 0x67 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 54 * 6]; +} _EC_X9_62_CHAR2_431R1 = { + { + NID_X9_62_characteristic_two_field, 0, 54, 0x2760 + }, + { + /* no seed */ + /* p */ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* a */ + 0x1A, 0x82, 0x7E, 0xF0, 0x0D, 0xD6, 0xFC, 0x0E, 0x23, 0x4C, 0xAF, 0x04, + 0x6C, 0x6A, 0x5D, 0x8A, 0x85, 0x39, 0x5B, 0x23, 0x6C, 0xC4, 0xAD, 0x2C, + 0xF3, 0x2A, 0x0C, 0xAD, 0xBD, 0xC9, 0xDD, 0xF6, 0x20, 0xB0, 0xEB, 0x99, + 0x06, 0xD0, 0x95, 0x7F, 0x6C, 0x6F, 0xEA, 0xCD, 0x61, 0x54, 0x68, 0xDF, + 0x10, 0x4D, 0xE2, 0x96, 0xCD, 0x8F, + /* b */ + 0x10, 0xD9, 0xB4, 0xA3, 0xD9, 0x04, 0x7D, 0x8B, 0x15, 0x43, 0x59, 0xAB, + 0xFB, 0x1B, 0x7F, 0x54, 0x85, 0xB0, 0x4C, 0xEB, 0x86, 0x82, 0x37, 0xDD, + 0xC9, 0xDE, 0xDA, 0x98, 0x2A, 0x67, 0x9A, 0x5A, 0x91, 0x9B, 0x62, 0x6D, + 0x4E, 0x50, 0xA8, 0xDD, 0x73, 0x1B, 0x10, 0x7A, 0x99, 0x62, 0x38, 0x1F, + 0xB5, 0xD8, 0x07, 0xBF, 0x26, 0x18, + /* x */ + 0x12, 0x0F, 0xC0, 0x5D, 0x3C, 0x67, 0xA9, 0x9D, 0xE1, 0x61, 0xD2, 0xF4, + 0x09, 0x26, 0x22, 0xFE, 0xCA, 0x70, 0x1B, 0xE4, 0xF5, 0x0F, 0x47, 0x58, + 0x71, 0x4E, 0x8A, 0x87, 0xBB, 0xF2, 0xA6, 0x58, 0xEF, 0x8C, 0x21, 0xE7, + 0xC5, 0xEF, 0xE9, 0x65, 0x36, 0x1F, 0x6C, 0x29, 0x99, 0xC0, 0xC2, 0x47, + 0xB0, 0xDB, 0xD7, 0x0C, 0xE6, 0xB7, + /* y */ + 0x20, 0xD0, 0xAF, 0x89, 0x03, 0xA9, 0x6F, 0x8D, 0x5F, 0xA2, 0xC2, 0x55, + 0x74, 0x5D, 0x3C, 0x45, 0x1B, 0x30, 0x2C, 0x93, 0x46, 0xD9, 0xB7, 0xE4, + 0x85, 0xE7, 0xBC, 0xE4, 0x1F, 0x6B, 0x59, 0x1F, 0x3E, 0x8F, 0x6A, 0xDD, + 0xCB, 0xB0, 0xBC, 0x4C, 0x2F, 0x94, 0x7A, 0x7D, 0xE1, 0xA8, 0x9B, 0x62, + 0x5D, 0x6A, 0x59, 0x8B, 0x37, 0x60, + /* order */ + 0x00, 0x03, 0x40, 0x34, 0x03, 0x40, 0x34, 0x03, 0x40, 0x34, 0x03, 0x40, + 0x34, 0x03, 0x40, 0x34, 0x03, 0x40, 0x34, 0x03, 0x40, 0x34, 0x03, 0x40, + 0x34, 0x03, 0x40, 0x34, 0x03, 0x23, 0xC3, 0x13, 0xFA, 0xB5, 0x05, 0x89, + 0x70, 0x3B, 0x5E, 0xC6, 0x8D, 0x35, 0x87, 0xFE, 0xC6, 0x0D, 0x16, 0x1C, + 0xC1, 0x49, 0xC1, 0xAD, 0x4A, 0x91 + } +}; + +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 15 * 6]; +} _EC_WTLS_1 = { + { + NID_X9_62_characteristic_two_field, 0, 15, 2 + }, + { + /* no seed */ + /* p */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x01, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, + /* x */ + 0x01, 0x66, 0x79, 0x79, 0xA4, 0x0B, 0xA4, 0x97, 0xE5, 0xD5, 0xC2, 0x70, + 0x78, 0x06, 0x17, + /* y */ + 0x00, 0xF4, 0x4B, 0x4A, 0xF1, 0xEC, 0xC2, 0x63, 0x0E, 0x08, 0x78, 0x5C, + 0xEB, 0xCC, 0x15, + /* order */ + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xBF, 0x91, 0xAF, + 0x6D, 0xEA, 0x73 + } +}; + +/* IPSec curves */ +/* + * NOTE: The of curves over a extension field of non prime degree is not + * recommended (Weil-descent). As the group order is not a prime this curve + * is not suitable for ECDSA. */ -static const struct { EC_CURVE_DATA h; unsigned char data[0+24*6]; } - _EC_IPSEC_185_ID4 = { - { NID_X9_62_characteristic_two_field,0,24,2 }, - { /* no seed */ - 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ - 0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x01, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x1e,0xe9, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* x */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x18, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* y */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x0d, - 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */ - 0xFF,0xFF,0xED,0xF9,0x7C,0x44,0xDB,0x9F,0x24,0x20, - 0xBA,0xFC,0xA7,0x5E } - }; +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 20 * 6]; +} _EC_IPSEC_155_ID3 = { + { + NID_X9_62_characteristic_two_field, 0, 20, 3 + }, + { + /* no seed */ + /* p */ + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x33, 0x8f, + /* x */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, + /* y */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc8, + /* order */ + 0x02, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xC7, 0xF3, + 0xC7, 0x88, 0x1B, 0xD0, 0x86, 0x8F, 0xA8, 0x6C + } +}; + +/* + * NOTE: The of curves over a extension field of non prime degree is not + * recommended (Weil-descent). As the group order is not a prime this curve + * is not suitable for ECDSA. + */ +static const struct { + EC_CURVE_DATA h; + unsigned char data[0 + 24 * 6]; +} _EC_IPSEC_185_ID4 = { + { + NID_X9_62_characteristic_two_field, 0, 24, 2 + }, + { + /* no seed */ + /* p */ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* a */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* b */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xe9, + /* x */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + /* y */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, + /* order */ + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xED, 0xF9, 0x7C, 0x44, 0xDB, 0x9F, 0x24, 0x20, 0xBA, 0xFC, 0xA7, 0x5E + } +}; #endif typedef struct _ec_list_element_st { - int nid; - const EC_CURVE_DATA *data; - const EC_METHOD *(*meth)(void); - const char *comment; - } ec_list_element; + int nid; + const EC_CURVE_DATA *data; + const EC_METHOD *(*meth) (void); + const char *comment; +} ec_list_element; static const ec_list_element curve_list[] = { - /* prime field curves */ - /* secg curves */ - { NID_secp112r1, &_EC_SECG_PRIME_112R1.h, 0, "SECG/WTLS curve over a 112 bit prime field" }, - { NID_secp112r2, &_EC_SECG_PRIME_112R2.h, 0, "SECG curve over a 112 bit prime field" }, - { NID_secp128r1, &_EC_SECG_PRIME_128R1.h, 0, "SECG curve over a 128 bit prime field" }, - { NID_secp128r2, &_EC_SECG_PRIME_128R2.h, 0, "SECG curve over a 128 bit prime field" }, - { NID_secp160k1, &_EC_SECG_PRIME_160K1.h, 0, "SECG curve over a 160 bit prime field" }, - { NID_secp160r1, &_EC_SECG_PRIME_160R1.h, 0, "SECG curve over a 160 bit prime field" }, - { NID_secp160r2, &_EC_SECG_PRIME_160R2.h, 0, "SECG/WTLS curve over a 160 bit prime field" }, - /* SECG secp192r1 is the same as X9.62 prime192v1 and hence omitted */ - { NID_secp192k1, &_EC_SECG_PRIME_192K1.h, 0, "SECG curve over a 192 bit prime field" }, - { NID_secp224k1, &_EC_SECG_PRIME_224K1.h, 0, "SECG curve over a 224 bit prime field" }, + /* prime field curves */ + /* secg curves */ + {NID_secp112r1, &_EC_SECG_PRIME_112R1.h, 0, + "SECG/WTLS curve over a 112 bit prime field"}, + {NID_secp112r2, &_EC_SECG_PRIME_112R2.h, 0, + "SECG curve over a 112 bit prime field"}, + {NID_secp128r1, &_EC_SECG_PRIME_128R1.h, 0, + "SECG curve over a 128 bit prime field"}, + {NID_secp128r2, &_EC_SECG_PRIME_128R2.h, 0, + "SECG curve over a 128 bit prime field"}, + {NID_secp160k1, &_EC_SECG_PRIME_160K1.h, 0, + "SECG curve over a 160 bit prime field"}, + {NID_secp160r1, &_EC_SECG_PRIME_160R1.h, 0, + "SECG curve over a 160 bit prime field"}, + {NID_secp160r2, &_EC_SECG_PRIME_160R2.h, 0, + "SECG/WTLS curve over a 160 bit prime field"}, + /* SECG secp192r1 is the same as X9.62 prime192v1 and hence omitted */ + {NID_secp192k1, &_EC_SECG_PRIME_192K1.h, 0, + "SECG curve over a 192 bit prime field"}, + {NID_secp224k1, &_EC_SECG_PRIME_224K1.h, 0, + "SECG curve over a 224 bit prime field"}, #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 - { NID_secp224r1, &_EC_NIST_PRIME_224.h, EC_GFp_nistp224_method, "NIST/SECG curve over a 224 bit prime field" }, + {NID_secp224r1, &_EC_NIST_PRIME_224.h, EC_GFp_nistp224_method, + "NIST/SECG curve over a 224 bit prime field"}, #else - { NID_secp224r1, &_EC_NIST_PRIME_224.h, 0, "NIST/SECG curve over a 224 bit prime field" }, + {NID_secp224r1, &_EC_NIST_PRIME_224.h, 0, + "NIST/SECG curve over a 224 bit prime field"}, #endif - { NID_secp256k1, &_EC_SECG_PRIME_256K1.h, 0, "SECG curve over a 256 bit prime field" }, - /* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */ - { NID_secp384r1, &_EC_NIST_PRIME_384.h, 0, "NIST/SECG curve over a 384 bit prime field" }, + {NID_secp256k1, &_EC_SECG_PRIME_256K1.h, 0, + "SECG curve over a 256 bit prime field"}, + /* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */ + {NID_secp384r1, &_EC_NIST_PRIME_384.h, 0, + "NIST/SECG curve over a 384 bit prime field"}, #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 - { NID_secp521r1, &_EC_NIST_PRIME_521.h, EC_GFp_nistp521_method, "NIST/SECG curve over a 521 bit prime field" }, + {NID_secp521r1, &_EC_NIST_PRIME_521.h, EC_GFp_nistp521_method, + "NIST/SECG curve over a 521 bit prime field"}, #else - { NID_secp521r1, &_EC_NIST_PRIME_521.h, 0, "NIST/SECG curve over a 521 bit prime field" }, + {NID_secp521r1, &_EC_NIST_PRIME_521.h, 0, + "NIST/SECG curve over a 521 bit prime field"}, #endif - /* X9.62 curves */ - { NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0, "NIST/X9.62/SECG curve over a 192 bit prime field" }, - { NID_X9_62_prime192v2, &_EC_X9_62_PRIME_192V2.h, 0, "X9.62 curve over a 192 bit prime field" }, - { NID_X9_62_prime192v3, &_EC_X9_62_PRIME_192V3.h, 0, "X9.62 curve over a 192 bit prime field" }, - { NID_X9_62_prime239v1, &_EC_X9_62_PRIME_239V1.h, 0, "X9.62 curve over a 239 bit prime field" }, - { NID_X9_62_prime239v2, &_EC_X9_62_PRIME_239V2.h, 0, "X9.62 curve over a 239 bit prime field" }, - { NID_X9_62_prime239v3, &_EC_X9_62_PRIME_239V3.h, 0, "X9.62 curve over a 239 bit prime field" }, + /* X9.62 curves */ + {NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0, + "NIST/X9.62/SECG curve over a 192 bit prime field"}, + {NID_X9_62_prime192v2, &_EC_X9_62_PRIME_192V2.h, 0, + "X9.62 curve over a 192 bit prime field"}, + {NID_X9_62_prime192v3, &_EC_X9_62_PRIME_192V3.h, 0, + "X9.62 curve over a 192 bit prime field"}, + {NID_X9_62_prime239v1, &_EC_X9_62_PRIME_239V1.h, 0, + "X9.62 curve over a 239 bit prime field"}, + {NID_X9_62_prime239v2, &_EC_X9_62_PRIME_239V2.h, 0, + "X9.62 curve over a 239 bit prime field"}, + {NID_X9_62_prime239v3, &_EC_X9_62_PRIME_239V3.h, 0, + "X9.62 curve over a 239 bit prime field"}, #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 - { NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h, EC_GFp_nistp256_method, "X9.62/SECG curve over a 256 bit prime field" }, + {NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h, EC_GFp_nistp256_method, + "X9.62/SECG curve over a 256 bit prime field"}, #else - { NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h, 0, "X9.62/SECG curve over a 256 bit prime field" }, + {NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h, 0, + "X9.62/SECG curve over a 256 bit prime field"}, #endif #ifndef OPENSSL_NO_EC2M - /* characteristic two field curves */ - /* NIST/SECG curves */ - { NID_sect113r1, &_EC_SECG_CHAR2_113R1.h, 0, "SECG curve over a 113 bit binary field" }, - { NID_sect113r2, &_EC_SECG_CHAR2_113R2.h, 0, "SECG curve over a 113 bit binary field" }, - { NID_sect131r1, &_EC_SECG_CHAR2_131R1.h, 0, "SECG/WTLS curve over a 131 bit binary field" }, - { NID_sect131r2, &_EC_SECG_CHAR2_131R2.h, 0, "SECG curve over a 131 bit binary field" }, - { NID_sect163k1, &_EC_NIST_CHAR2_163K.h, 0, "NIST/SECG/WTLS curve over a 163 bit binary field" }, - { NID_sect163r1, &_EC_SECG_CHAR2_163R1.h, 0, "SECG curve over a 163 bit binary field" }, - { NID_sect163r2, &_EC_NIST_CHAR2_163B.h, 0, "NIST/SECG curve over a 163 bit binary field" }, - { NID_sect193r1, &_EC_SECG_CHAR2_193R1.h, 0, "SECG curve over a 193 bit binary field" }, - { NID_sect193r2, &_EC_SECG_CHAR2_193R2.h, 0, "SECG curve over a 193 bit binary field" }, - { NID_sect233k1, &_EC_NIST_CHAR2_233K.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field" }, - { NID_sect233r1, &_EC_NIST_CHAR2_233B.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field" }, - { NID_sect239k1, &_EC_SECG_CHAR2_239K1.h, 0, "SECG curve over a 239 bit binary field" }, - { NID_sect283k1, &_EC_NIST_CHAR2_283K.h, 0, "NIST/SECG curve over a 283 bit binary field" }, - { NID_sect283r1, &_EC_NIST_CHAR2_283B.h, 0, "NIST/SECG curve over a 283 bit binary field" }, - { NID_sect409k1, &_EC_NIST_CHAR2_409K.h, 0, "NIST/SECG curve over a 409 bit binary field" }, - { NID_sect409r1, &_EC_NIST_CHAR2_409B.h, 0, "NIST/SECG curve over a 409 bit binary field" }, - { NID_sect571k1, &_EC_NIST_CHAR2_571K.h, 0, "NIST/SECG curve over a 571 bit binary field" }, - { NID_sect571r1, &_EC_NIST_CHAR2_571B.h, 0, "NIST/SECG curve over a 571 bit binary field" }, - /* X9.62 curves */ - { NID_X9_62_c2pnb163v1, &_EC_X9_62_CHAR2_163V1.h, 0, "X9.62 curve over a 163 bit binary field" }, - { NID_X9_62_c2pnb163v2, &_EC_X9_62_CHAR2_163V2.h, 0, "X9.62 curve over a 163 bit binary field" }, - { NID_X9_62_c2pnb163v3, &_EC_X9_62_CHAR2_163V3.h, 0, "X9.62 curve over a 163 bit binary field" }, - { NID_X9_62_c2pnb176v1, &_EC_X9_62_CHAR2_176V1.h, 0, "X9.62 curve over a 176 bit binary field" }, - { NID_X9_62_c2tnb191v1, &_EC_X9_62_CHAR2_191V1.h, 0, "X9.62 curve over a 191 bit binary field" }, - { NID_X9_62_c2tnb191v2, &_EC_X9_62_CHAR2_191V2.h, 0, "X9.62 curve over a 191 bit binary field" }, - { NID_X9_62_c2tnb191v3, &_EC_X9_62_CHAR2_191V3.h, 0, "X9.62 curve over a 191 bit binary field" }, - { NID_X9_62_c2pnb208w1, &_EC_X9_62_CHAR2_208W1.h, 0, "X9.62 curve over a 208 bit binary field" }, - { NID_X9_62_c2tnb239v1, &_EC_X9_62_CHAR2_239V1.h, 0, "X9.62 curve over a 239 bit binary field" }, - { NID_X9_62_c2tnb239v2, &_EC_X9_62_CHAR2_239V2.h, 0, "X9.62 curve over a 239 bit binary field" }, - { NID_X9_62_c2tnb239v3, &_EC_X9_62_CHAR2_239V3.h, 0, "X9.62 curve over a 239 bit binary field" }, - { NID_X9_62_c2pnb272w1, &_EC_X9_62_CHAR2_272W1.h, 0, "X9.62 curve over a 272 bit binary field" }, - { NID_X9_62_c2pnb304w1, &_EC_X9_62_CHAR2_304W1.h, 0, "X9.62 curve over a 304 bit binary field" }, - { NID_X9_62_c2tnb359v1, &_EC_X9_62_CHAR2_359V1.h, 0, "X9.62 curve over a 359 bit binary field" }, - { NID_X9_62_c2pnb368w1, &_EC_X9_62_CHAR2_368W1.h, 0, "X9.62 curve over a 368 bit binary field" }, - { NID_X9_62_c2tnb431r1, &_EC_X9_62_CHAR2_431R1.h, 0, "X9.62 curve over a 431 bit binary field" }, - /* the WAP/WTLS curves - * [unlike SECG, spec has its own OIDs for curves from X9.62] */ - { NID_wap_wsg_idm_ecid_wtls1, &_EC_WTLS_1.h, 0, "WTLS curve over a 113 bit binary field" }, - { NID_wap_wsg_idm_ecid_wtls3, &_EC_NIST_CHAR2_163K.h, 0, "NIST/SECG/WTLS curve over a 163 bit binary field" }, - { NID_wap_wsg_idm_ecid_wtls4, &_EC_SECG_CHAR2_113R1.h, 0, "SECG curve over a 113 bit binary field" }, - { NID_wap_wsg_idm_ecid_wtls5, &_EC_X9_62_CHAR2_163V1.h, 0, "X9.62 curve over a 163 bit binary field" }, + /* characteristic two field curves */ + /* NIST/SECG curves */ + {NID_sect113r1, &_EC_SECG_CHAR2_113R1.h, 0, + "SECG curve over a 113 bit binary field"}, + {NID_sect113r2, &_EC_SECG_CHAR2_113R2.h, 0, + "SECG curve over a 113 bit binary field"}, + {NID_sect131r1, &_EC_SECG_CHAR2_131R1.h, 0, + "SECG/WTLS curve over a 131 bit binary field"}, + {NID_sect131r2, &_EC_SECG_CHAR2_131R2.h, 0, + "SECG curve over a 131 bit binary field"}, + {NID_sect163k1, &_EC_NIST_CHAR2_163K.h, 0, + "NIST/SECG/WTLS curve over a 163 bit binary field"}, + {NID_sect163r1, &_EC_SECG_CHAR2_163R1.h, 0, + "SECG curve over a 163 bit binary field"}, + {NID_sect163r2, &_EC_NIST_CHAR2_163B.h, 0, + "NIST/SECG curve over a 163 bit binary field"}, + {NID_sect193r1, &_EC_SECG_CHAR2_193R1.h, 0, + "SECG curve over a 193 bit binary field"}, + {NID_sect193r2, &_EC_SECG_CHAR2_193R2.h, 0, + "SECG curve over a 193 bit binary field"}, + {NID_sect233k1, &_EC_NIST_CHAR2_233K.h, 0, + "NIST/SECG/WTLS curve over a 233 bit binary field"}, + {NID_sect233r1, &_EC_NIST_CHAR2_233B.h, 0, + "NIST/SECG/WTLS curve over a 233 bit binary field"}, + {NID_sect239k1, &_EC_SECG_CHAR2_239K1.h, 0, + "SECG curve over a 239 bit binary field"}, + {NID_sect283k1, &_EC_NIST_CHAR2_283K.h, 0, + "NIST/SECG curve over a 283 bit binary field"}, + {NID_sect283r1, &_EC_NIST_CHAR2_283B.h, 0, + "NIST/SECG curve over a 283 bit binary field"}, + {NID_sect409k1, &_EC_NIST_CHAR2_409K.h, 0, + "NIST/SECG curve over a 409 bit binary field"}, + {NID_sect409r1, &_EC_NIST_CHAR2_409B.h, 0, + "NIST/SECG curve over a 409 bit binary field"}, + {NID_sect571k1, &_EC_NIST_CHAR2_571K.h, 0, + "NIST/SECG curve over a 571 bit binary field"}, + {NID_sect571r1, &_EC_NIST_CHAR2_571B.h, 0, + "NIST/SECG curve over a 571 bit binary field"}, + /* X9.62 curves */ + {NID_X9_62_c2pnb163v1, &_EC_X9_62_CHAR2_163V1.h, 0, + "X9.62 curve over a 163 bit binary field"}, + {NID_X9_62_c2pnb163v2, &_EC_X9_62_CHAR2_163V2.h, 0, + "X9.62 curve over a 163 bit binary field"}, + {NID_X9_62_c2pnb163v3, &_EC_X9_62_CHAR2_163V3.h, 0, + "X9.62 curve over a 163 bit binary field"}, + {NID_X9_62_c2pnb176v1, &_EC_X9_62_CHAR2_176V1.h, 0, + "X9.62 curve over a 176 bit binary field"}, + {NID_X9_62_c2tnb191v1, &_EC_X9_62_CHAR2_191V1.h, 0, + "X9.62 curve over a 191 bit binary field"}, + {NID_X9_62_c2tnb191v2, &_EC_X9_62_CHAR2_191V2.h, 0, + "X9.62 curve over a 191 bit binary field"}, + {NID_X9_62_c2tnb191v3, &_EC_X9_62_CHAR2_191V3.h, 0, + "X9.62 curve over a 191 bit binary field"}, + {NID_X9_62_c2pnb208w1, &_EC_X9_62_CHAR2_208W1.h, 0, + "X9.62 curve over a 208 bit binary field"}, + {NID_X9_62_c2tnb239v1, &_EC_X9_62_CHAR2_239V1.h, 0, + "X9.62 curve over a 239 bit binary field"}, + {NID_X9_62_c2tnb239v2, &_EC_X9_62_CHAR2_239V2.h, 0, + "X9.62 curve over a 239 bit binary field"}, + {NID_X9_62_c2tnb239v3, &_EC_X9_62_CHAR2_239V3.h, 0, + "X9.62 curve over a 239 bit binary field"}, + {NID_X9_62_c2pnb272w1, &_EC_X9_62_CHAR2_272W1.h, 0, + "X9.62 curve over a 272 bit binary field"}, + {NID_X9_62_c2pnb304w1, &_EC_X9_62_CHAR2_304W1.h, 0, + "X9.62 curve over a 304 bit binary field"}, + {NID_X9_62_c2tnb359v1, &_EC_X9_62_CHAR2_359V1.h, 0, + "X9.62 curve over a 359 bit binary field"}, + {NID_X9_62_c2pnb368w1, &_EC_X9_62_CHAR2_368W1.h, 0, + "X9.62 curve over a 368 bit binary field"}, + {NID_X9_62_c2tnb431r1, &_EC_X9_62_CHAR2_431R1.h, 0, + "X9.62 curve over a 431 bit binary field"}, + /* + * the WAP/WTLS curves [unlike SECG, spec has its own OIDs for curves + * from X9.62] + */ + {NID_wap_wsg_idm_ecid_wtls1, &_EC_WTLS_1.h, 0, + "WTLS curve over a 113 bit binary field"}, + {NID_wap_wsg_idm_ecid_wtls3, &_EC_NIST_CHAR2_163K.h, 0, + "NIST/SECG/WTLS curve over a 163 bit binary field"}, + {NID_wap_wsg_idm_ecid_wtls4, &_EC_SECG_CHAR2_113R1.h, 0, + "SECG curve over a 113 bit binary field"}, + {NID_wap_wsg_idm_ecid_wtls5, &_EC_X9_62_CHAR2_163V1.h, 0, + "X9.62 curve over a 163 bit binary field"}, #endif - { NID_wap_wsg_idm_ecid_wtls6, &_EC_SECG_PRIME_112R1.h, 0, "SECG/WTLS curve over a 112 bit prime field" }, - { NID_wap_wsg_idm_ecid_wtls7, &_EC_SECG_PRIME_160R2.h, 0, "SECG/WTLS curve over a 160 bit prime field" }, - { NID_wap_wsg_idm_ecid_wtls8, &_EC_WTLS_8.h, 0, "WTLS curve over a 112 bit prime field" }, - { NID_wap_wsg_idm_ecid_wtls9, &_EC_WTLS_9.h, 0, "WTLS curve over a 160 bit prime field" }, + {NID_wap_wsg_idm_ecid_wtls6, &_EC_SECG_PRIME_112R1.h, 0, + "SECG/WTLS curve over a 112 bit prime field"}, + {NID_wap_wsg_idm_ecid_wtls7, &_EC_SECG_PRIME_160R2.h, 0, + "SECG/WTLS curve over a 160 bit prime field"}, + {NID_wap_wsg_idm_ecid_wtls8, &_EC_WTLS_8.h, 0, + "WTLS curve over a 112 bit prime field"}, + {NID_wap_wsg_idm_ecid_wtls9, &_EC_WTLS_9.h, 0, + "WTLS curve over a 160 bit prime field"}, #ifndef OPENSSL_NO_EC2M - { NID_wap_wsg_idm_ecid_wtls10, &_EC_NIST_CHAR2_233K.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field" }, - { NID_wap_wsg_idm_ecid_wtls11, &_EC_NIST_CHAR2_233B.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field" }, + {NID_wap_wsg_idm_ecid_wtls10, &_EC_NIST_CHAR2_233K.h, 0, + "NIST/SECG/WTLS curve over a 233 bit binary field"}, + {NID_wap_wsg_idm_ecid_wtls11, &_EC_NIST_CHAR2_233B.h, 0, + "NIST/SECG/WTLS curve over a 233 bit binary field"}, #endif - { NID_wap_wsg_idm_ecid_wtls12, &_EC_WTLS_12.h, 0, "WTLS curvs over a 224 bit prime field" }, + {NID_wap_wsg_idm_ecid_wtls12, &_EC_WTLS_12.h, 0, + "WTLS curvs over a 224 bit prime field"}, #ifndef OPENSSL_NO_EC2M - /* IPSec curves */ - { NID_ipsec3, &_EC_IPSEC_155_ID3.h, 0, "\n\tIPSec/IKE/Oakley curve #3 over a 155 bit binary field.\n" - "\tNot suitable for ECDSA.\n\tQuestionable extension field!" }, - { NID_ipsec4, &_EC_IPSEC_185_ID4.h, 0, "\n\tIPSec/IKE/Oakley curve #4 over a 185 bit binary field.\n" - "\tNot suitable for ECDSA.\n\tQuestionable extension field!" }, + /* IPSec curves */ + {NID_ipsec3, &_EC_IPSEC_155_ID3.h, 0, + "\n\tIPSec/IKE/Oakley curve #3 over a 155 bit binary field.\n" + "\tNot suitable for ECDSA.\n\tQuestionable extension field!"}, + {NID_ipsec4, &_EC_IPSEC_185_ID4.h, 0, + "\n\tIPSec/IKE/Oakley curve #4 over a 185 bit binary field.\n" + "\tNot suitable for ECDSA.\n\tQuestionable extension field!"}, #endif }; #define curve_list_length (sizeof(curve_list)/sizeof(ec_list_element)) static EC_GROUP *ec_group_new_from_data(const ec_list_element curve) - { - EC_GROUP *group=NULL; - EC_POINT *P=NULL; - BN_CTX *ctx=NULL; - BIGNUM *p=NULL, *a=NULL, *b=NULL, *x=NULL, *y=NULL, *order=NULL; - int ok=0; - int seed_len,param_len; - const EC_METHOD *meth; - const EC_CURVE_DATA *data; - const unsigned char *params; - - if ((ctx = BN_CTX_new()) == NULL) - { - ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_MALLOC_FAILURE); - goto err; - } - - data = curve.data; - seed_len = data->seed_len; - param_len = data->param_len; - params = (const unsigned char *)(data+1); /* skip header */ - params += seed_len; /* skip seed */ - - if (!(p = BN_bin2bn(params+0*param_len, param_len, NULL)) - || !(a = BN_bin2bn(params+1*param_len, param_len, NULL)) - || !(b = BN_bin2bn(params+2*param_len, param_len, NULL))) - { - ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB); - goto err; - } - - if (curve.meth != 0) - { - meth = curve.meth(); - if (((group = EC_GROUP_new(meth)) == NULL) || - (!(group->meth->group_set_curve(group, p, a, b, ctx)))) - { - ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); - goto err; - } - } - else if (data->field_type == NID_X9_62_prime_field) - { - if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) - { - ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); - goto err; - } - } +{ + EC_GROUP *group = NULL; + EC_POINT *P = NULL; + BN_CTX *ctx = NULL; + BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL, *order = + NULL; + int ok = 0; + int seed_len, param_len; + const EC_METHOD *meth; + const EC_CURVE_DATA *data; + const unsigned char *params; + + if ((ctx = BN_CTX_new()) == NULL) { + ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_MALLOC_FAILURE); + goto err; + } + + data = curve.data; + seed_len = data->seed_len; + param_len = data->param_len; + params = (const unsigned char *)(data + 1); /* skip header */ + params += seed_len; /* skip seed */ + + if (!(p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) + || !(a = BN_bin2bn(params + 1 * param_len, param_len, NULL)) + || !(b = BN_bin2bn(params + 2 * param_len, param_len, NULL))) { + ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB); + goto err; + } + + if (curve.meth != 0) { + meth = curve.meth(); + if (((group = EC_GROUP_new(meth)) == NULL) || + (!(group->meth->group_set_curve(group, p, a, b, ctx)))) { + ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); + goto err; + } + } else if (data->field_type == NID_X9_62_prime_field) { + if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) { + ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); + goto err; + } + } #ifndef OPENSSL_NO_EC2M - else /* field_type == NID_X9_62_characteristic_two_field */ - { - if ((group = EC_GROUP_new_curve_GF2m(p, a, b, ctx)) == NULL) - { - ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); - goto err; - } - } + else { /* field_type == + * NID_X9_62_characteristic_two_field */ + + if ((group = EC_GROUP_new_curve_GF2m(p, a, b, ctx)) == NULL) { + ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); + goto err; + } + } #endif - if ((P = EC_POINT_new(group)) == NULL) - { - ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); - goto err; - } - - if (!(x = BN_bin2bn(params+3*param_len, param_len, NULL)) - || !(y = BN_bin2bn(params+4*param_len, param_len, NULL))) - { - ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB); - goto err; - } - if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) - { - ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); - goto err; - } - if (!(order = BN_bin2bn(params+5*param_len, param_len, NULL)) - || !BN_set_word(x, (BN_ULONG)data->cofactor)) - { - ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB); - goto err; - } - if (!EC_GROUP_set_generator(group, P, order, x)) - { - ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); - goto err; - } - if (seed_len) - { - if (!EC_GROUP_set_seed(group, params-seed_len, seed_len)) - { - ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); - goto err; - } - } - ok=1; -err: - if (!ok) - { - EC_GROUP_free(group); - group = NULL; - } - if (P) - EC_POINT_free(P); - if (ctx) - BN_CTX_free(ctx); - if (p) - BN_free(p); - if (a) - BN_free(a); - if (b) - BN_free(b); - if (order) - BN_free(order); - if (x) - BN_free(x); - if (y) - BN_free(y); - return group; - } + if ((P = EC_POINT_new(group)) == NULL) { + ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); + goto err; + } + + if (!(x = BN_bin2bn(params + 3 * param_len, param_len, NULL)) + || !(y = BN_bin2bn(params + 4 * param_len, param_len, NULL))) { + ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB); + goto err; + } + if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) { + ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); + goto err; + } + if (!(order = BN_bin2bn(params + 5 * param_len, param_len, NULL)) + || !BN_set_word(x, (BN_ULONG)data->cofactor)) { + ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB); + goto err; + } + if (!EC_GROUP_set_generator(group, P, order, x)) { + ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); + goto err; + } + if (seed_len) { + if (!EC_GROUP_set_seed(group, params - seed_len, seed_len)) { + ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); + goto err; + } + } + ok = 1; + err: + if (!ok) { + EC_GROUP_free(group); + group = NULL; + } + if (P) + EC_POINT_free(P); + if (ctx) + BN_CTX_free(ctx); + if (p) + BN_free(p); + if (a) + BN_free(a); + if (b) + BN_free(b); + if (order) + BN_free(order); + if (x) + BN_free(x); + if (y) + BN_free(y); + return group; +} EC_GROUP *EC_GROUP_new_by_curve_name(int nid) - { - size_t i; - EC_GROUP *ret = NULL; +{ + size_t i; + EC_GROUP *ret = NULL; - if (nid <= 0) - return NULL; + if (nid <= 0) + return NULL; - for (i=0; i<curve_list_length; i++) - if (curve_list[i].nid == nid) - { - ret = ec_group_new_from_data(curve_list[i]); - break; - } + for (i = 0; i < curve_list_length; i++) + if (curve_list[i].nid == nid) { + ret = ec_group_new_from_data(curve_list[i]); + break; + } - if (ret == NULL) - { - ECerr(EC_F_EC_GROUP_NEW_BY_CURVE_NAME, EC_R_UNKNOWN_GROUP); - return NULL; - } + if (ret == NULL) { + ECerr(EC_F_EC_GROUP_NEW_BY_CURVE_NAME, EC_R_UNKNOWN_GROUP); + return NULL; + } - EC_GROUP_set_curve_name(ret, nid); + EC_GROUP_set_curve_name(ret, nid); - return ret; - } + return ret; +} size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems) - { - size_t i, min; +{ + size_t i, min; - if (r == NULL || nitems == 0) - return curve_list_length; + if (r == NULL || nitems == 0) + return curve_list_length; - min = nitems < curve_list_length ? nitems : curve_list_length; + min = nitems < curve_list_length ? nitems : curve_list_length; - for (i = 0; i < min; i++) - { - r[i].nid = curve_list[i].nid; - r[i].comment = curve_list[i].comment; - } + for (i = 0; i < min; i++) { + r[i].nid = curve_list[i].nid; + r[i].comment = curve_list[i].comment; + } - return curve_list_length; - } + return curve_list_length; +} diff --git a/openssl/crypto/ec/ec_cvt.c b/openssl/crypto/ec/ec_cvt.c index bfcbab35f..487d72740 100644 --- a/openssl/crypto/ec/ec_cvt.c +++ b/openssl/crypto/ec/ec_cvt.c @@ -10,7 +10,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -58,7 +58,7 @@ /* ==================================================================== * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. * - * Portions of the attached software ("Contribution") are developed by + * Portions of the attached software ("Contribution") are developed by * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. * * The Contribution is licensed pursuant to the OpenSSL open source @@ -72,99 +72,97 @@ #include <openssl/err.h> #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; +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; #if defined(OPENSSL_BN_ASM_MONT) - /* - * This might appear controversial, but the fact is that generic - * prime method was observed to deliver better performance even - * for NIST primes on a range of platforms, e.g.: 60%-15% - * improvement on IA-64, ~25% on ARM, 30%-90% on P4, 20%-25% - * in 32-bit build and 35%--12% in 64-bit build on Core2... - * Coefficients are relative to optimized bn_nist.c for most - * intensive ECDSA verify and ECDH operations for 192- and 521- - * bit keys respectively. Choice of these boundary values is - * arguable, because the dependency of improvement coefficient - * from key length is not a "monotone" curve. For example while - * 571-bit result is 23% on ARM, 384-bit one is -1%. But it's - * generally faster, sometimes "respectfully" faster, sometimes - * "tolerably" slower... What effectively happens is that loop - * with bn_mul_add_words is put against bn_mul_mont, and the - * latter "wins" on short vectors. Correct solution should be - * implementing dedicated NxN multiplication subroutines for - * small N. But till it materializes, let's stick to generic - * prime method... - * <appro> - */ - meth = EC_GFp_mont_method(); + /* + * This might appear controversial, but the fact is that generic + * prime method was observed to deliver better performance even + * for NIST primes on a range of platforms, e.g.: 60%-15% + * improvement on IA-64, ~25% on ARM, 30%-90% on P4, 20%-25% + * in 32-bit build and 35%--12% in 64-bit build on Core2... + * Coefficients are relative to optimized bn_nist.c for most + * intensive ECDSA verify and ECDH operations for 192- and 521- + * bit keys respectively. Choice of these boundary values is + * arguable, because the dependency of improvement coefficient + * from key length is not a "monotone" curve. For example while + * 571-bit result is 23% on ARM, 384-bit one is -1%. But it's + * generally faster, sometimes "respectfully" faster, sometimes + * "tolerably" slower... What effectively happens is that loop + * with bn_mul_add_words is put against bn_mul_mont, and the + * latter "wins" on short vectors. Correct solution should be + * implementing dedicated NxN multiplication subroutines for + * small N. But till it materializes, let's stick to generic + * prime method... + * <appro> + */ + meth = EC_GFp_mont_method(); #else - meth = EC_GFp_nist_method(); + meth = EC_GFp_nist_method(); #endif - - ret = EC_GROUP_new(meth); - if (ret == NULL) - return NULL; - - if (!EC_GROUP_set_curve_GFp(ret, p, a, b, ctx)) - { - unsigned long err; - - err = ERR_peek_last_error(); - - if (!(ERR_GET_LIB(err) == ERR_LIB_EC && - ((ERR_GET_REASON(err) == EC_R_NOT_A_NIST_PRIME) || - (ERR_GET_REASON(err) == EC_R_NOT_A_SUPPORTED_NIST_PRIME)))) - { - /* real error */ - - EC_GROUP_clear_free(ret); - return NULL; - } - - - /* not an actual error, we just cannot use EC_GFp_nist_method */ - - ERR_clear_error(); - - EC_GROUP_clear_free(ret); - meth = EC_GFp_mont_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; - } + + ret = EC_GROUP_new(meth); + if (ret == NULL) + return NULL; + + if (!EC_GROUP_set_curve_GFp(ret, p, a, b, ctx)) { + unsigned long err; + + err = ERR_peek_last_error(); + + if (!(ERR_GET_LIB(err) == ERR_LIB_EC && + ((ERR_GET_REASON(err) == EC_R_NOT_A_NIST_PRIME) || + (ERR_GET_REASON(err) == EC_R_NOT_A_SUPPORTED_NIST_PRIME)))) { + /* real error */ + + EC_GROUP_clear_free(ret); + return NULL; + } + + /* + * not an actual error, we just cannot use EC_GFp_nist_method + */ + + ERR_clear_error(); + + EC_GROUP_clear_free(ret); + meth = EC_GFp_mont_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; +} #ifndef OPENSSL_NO_EC2M -EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) - { - const EC_METHOD *meth; - EC_GROUP *ret; - - meth = EC_GF2m_simple_method(); - - ret = EC_GROUP_new(meth); - if (ret == NULL) - return NULL; - - if (!EC_GROUP_set_curve_GF2m(ret, p, a, b, ctx)) - { - EC_GROUP_clear_free(ret); - return NULL; - } - - return ret; - } +EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx) +{ + const EC_METHOD *meth; + EC_GROUP *ret; + + meth = EC_GF2m_simple_method(); + + ret = EC_GROUP_new(meth); + if (ret == NULL) + return NULL; + + if (!EC_GROUP_set_curve_GF2m(ret, p, a, b, ctx)) { + EC_GROUP_clear_free(ret); + return NULL; + } + + return ret; +} #endif diff --git a/openssl/crypto/ec/ec_err.c b/openssl/crypto/ec/ec_err.c index 0d1939873..58eae7c66 100644 --- a/openssl/crypto/ec/ec_err.c +++ b/openssl/crypto/ec/ec_err.c @@ -7,7 +7,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -53,7 +53,8 @@ * */ -/* NOTE: this file was auto generated by the mkerr.pl script: any changes +/* + * NOTE: this file was auto generated by the mkerr.pl script: any changes * made to it will be overwritten when the script next updates this file, * only reason strings will be preserved. */ @@ -65,212 +66,254 @@ /* BEGIN ERROR CODES */ #ifndef OPENSSL_NO_ERR -#define ERR_FUNC(func) ERR_PACK(ERR_LIB_EC,func,0) -#define ERR_REASON(reason) ERR_PACK(ERR_LIB_EC,0,reason) +# define ERR_FUNC(func) ERR_PACK(ERR_LIB_EC,func,0) +# define ERR_REASON(reason) ERR_PACK(ERR_LIB_EC,0,reason) -static ERR_STRING_DATA EC_str_functs[]= - { -{ERR_FUNC(EC_F_BN_TO_FELEM), "BN_TO_FELEM"}, -{ERR_FUNC(EC_F_COMPUTE_WNAF), "COMPUTE_WNAF"}, -{ERR_FUNC(EC_F_D2I_ECPARAMETERS), "d2i_ECParameters"}, -{ERR_FUNC(EC_F_D2I_ECPKPARAMETERS), "d2i_ECPKParameters"}, -{ERR_FUNC(EC_F_D2I_ECPRIVATEKEY), "d2i_ECPrivateKey"}, -{ERR_FUNC(EC_F_DO_EC_KEY_PRINT), "DO_EC_KEY_PRINT"}, -{ERR_FUNC(EC_F_ECKEY_PARAM2TYPE), "ECKEY_PARAM2TYPE"}, -{ERR_FUNC(EC_F_ECKEY_PARAM_DECODE), "ECKEY_PARAM_DECODE"}, -{ERR_FUNC(EC_F_ECKEY_PRIV_DECODE), "ECKEY_PRIV_DECODE"}, -{ERR_FUNC(EC_F_ECKEY_PRIV_ENCODE), "ECKEY_PRIV_ENCODE"}, -{ERR_FUNC(EC_F_ECKEY_PUB_DECODE), "ECKEY_PUB_DECODE"}, -{ERR_FUNC(EC_F_ECKEY_PUB_ENCODE), "ECKEY_PUB_ENCODE"}, -{ERR_FUNC(EC_F_ECKEY_TYPE2PARAM), "ECKEY_TYPE2PARAM"}, -{ERR_FUNC(EC_F_ECPARAMETERS_PRINT), "ECParameters_print"}, -{ERR_FUNC(EC_F_ECPARAMETERS_PRINT_FP), "ECParameters_print_fp"}, -{ERR_FUNC(EC_F_ECPKPARAMETERS_PRINT), "ECPKParameters_print"}, -{ERR_FUNC(EC_F_ECPKPARAMETERS_PRINT_FP), "ECPKParameters_print_fp"}, -{ERR_FUNC(EC_F_ECP_NIST_MOD_192), "ECP_NIST_MOD_192"}, -{ERR_FUNC(EC_F_ECP_NIST_MOD_224), "ECP_NIST_MOD_224"}, -{ERR_FUNC(EC_F_ECP_NIST_MOD_256), "ECP_NIST_MOD_256"}, -{ERR_FUNC(EC_F_ECP_NIST_MOD_521), "ECP_NIST_MOD_521"}, -{ERR_FUNC(EC_F_EC_ASN1_GROUP2CURVE), "EC_ASN1_GROUP2CURVE"}, -{ERR_FUNC(EC_F_EC_ASN1_GROUP2FIELDID), "EC_ASN1_GROUP2FIELDID"}, -{ERR_FUNC(EC_F_EC_ASN1_GROUP2PARAMETERS), "EC_ASN1_GROUP2PARAMETERS"}, -{ERR_FUNC(EC_F_EC_ASN1_GROUP2PKPARAMETERS), "EC_ASN1_GROUP2PKPARAMETERS"}, -{ERR_FUNC(EC_F_EC_ASN1_PARAMETERS2GROUP), "EC_ASN1_PARAMETERS2GROUP"}, -{ERR_FUNC(EC_F_EC_ASN1_PKPARAMETERS2GROUP), "EC_ASN1_PKPARAMETERS2GROUP"}, -{ERR_FUNC(EC_F_EC_EX_DATA_SET_DATA), "EC_EX_DATA_set_data"}, -{ERR_FUNC(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY), "EC_GF2M_MONTGOMERY_POINT_MULTIPLY"}, -{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT), "ec_GF2m_simple_group_check_discriminant"}, -{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE), "ec_GF2m_simple_group_set_curve"}, -{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_OCT2POINT), "ec_GF2m_simple_oct2point"}, -{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_POINT2OCT), "ec_GF2m_simple_point2oct"}, -{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES), "ec_GF2m_simple_point_get_affine_coordinates"}, -{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES), "ec_GF2m_simple_point_set_affine_coordinates"}, -{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES), "ec_GF2m_simple_set_compressed_coordinates"}, -{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_DECODE), "ec_GFp_mont_field_decode"}, -{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_ENCODE), "ec_GFp_mont_field_encode"}, -{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_MUL), "ec_GFp_mont_field_mul"}, -{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE), "ec_GFp_mont_field_set_to_one"}, -{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_SQR), "ec_GFp_mont_field_sqr"}, -{ERR_FUNC(EC_F_EC_GFP_MONT_GROUP_SET_CURVE), "ec_GFp_mont_group_set_curve"}, -{ERR_FUNC(EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP), "EC_GFP_MONT_GROUP_SET_CURVE_GFP"}, -{ERR_FUNC(EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE), "ec_GFp_nistp224_group_set_curve"}, -{ERR_FUNC(EC_F_EC_GFP_NISTP224_POINTS_MUL), "ec_GFp_nistp224_points_mul"}, -{ERR_FUNC(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES), "ec_GFp_nistp224_point_get_affine_coordinates"}, -{ERR_FUNC(EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE), "ec_GFp_nistp256_group_set_curve"}, -{ERR_FUNC(EC_F_EC_GFP_NISTP256_POINTS_MUL), "ec_GFp_nistp256_points_mul"}, -{ERR_FUNC(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES), "ec_GFp_nistp256_point_get_affine_coordinates"}, -{ERR_FUNC(EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE), "ec_GFp_nistp521_group_set_curve"}, -{ERR_FUNC(EC_F_EC_GFP_NISTP521_POINTS_MUL), "ec_GFp_nistp521_points_mul"}, -{ERR_FUNC(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES), "ec_GFp_nistp521_point_get_affine_coordinates"}, -{ERR_FUNC(EC_F_EC_GFP_NIST_FIELD_MUL), "ec_GFp_nist_field_mul"}, -{ERR_FUNC(EC_F_EC_GFP_NIST_FIELD_SQR), "ec_GFp_nist_field_sqr"}, -{ERR_FUNC(EC_F_EC_GFP_NIST_GROUP_SET_CURVE), "ec_GFp_nist_group_set_curve"}, -{ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT), "ec_GFp_simple_group_check_discriminant"}, -{ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE), "ec_GFp_simple_group_set_curve"}, -{ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP), "EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP"}, -{ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR), "EC_GFP_SIMPLE_GROUP_SET_GENERATOR"}, -{ERR_FUNC(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE), "ec_GFp_simple_make_affine"}, -{ERR_FUNC(EC_F_EC_GFP_SIMPLE_OCT2POINT), "ec_GFp_simple_oct2point"}, -{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT2OCT), "ec_GFp_simple_point2oct"}, -{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE), "ec_GFp_simple_points_make_affine"}, -{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES), "ec_GFp_simple_point_get_affine_coordinates"}, -{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP), "EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP"}, -{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES), "ec_GFp_simple_point_set_affine_coordinates"}, -{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP), "EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP"}, -{ERR_FUNC(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES), "ec_GFp_simple_set_compressed_coordinates"}, -{ERR_FUNC(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP), "EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP"}, -{ERR_FUNC(EC_F_EC_GROUP_CHECK), "EC_GROUP_check"}, -{ERR_FUNC(EC_F_EC_GROUP_CHECK_DISCRIMINANT), "EC_GROUP_check_discriminant"}, -{ERR_FUNC(EC_F_EC_GROUP_COPY), "EC_GROUP_copy"}, -{ERR_FUNC(EC_F_EC_GROUP_GET0_GENERATOR), "EC_GROUP_get0_generator"}, -{ERR_FUNC(EC_F_EC_GROUP_GET_COFACTOR), "EC_GROUP_get_cofactor"}, -{ERR_FUNC(EC_F_EC_GROUP_GET_CURVE_GF2M), "EC_GROUP_get_curve_GF2m"}, -{ERR_FUNC(EC_F_EC_GROUP_GET_CURVE_GFP), "EC_GROUP_get_curve_GFp"}, -{ERR_FUNC(EC_F_EC_GROUP_GET_DEGREE), "EC_GROUP_get_degree"}, -{ERR_FUNC(EC_F_EC_GROUP_GET_ORDER), "EC_GROUP_get_order"}, -{ERR_FUNC(EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS), "EC_GROUP_get_pentanomial_basis"}, -{ERR_FUNC(EC_F_EC_GROUP_GET_TRINOMIAL_BASIS), "EC_GROUP_get_trinomial_basis"}, -{ERR_FUNC(EC_F_EC_GROUP_NEW), "EC_GROUP_new"}, -{ERR_FUNC(EC_F_EC_GROUP_NEW_BY_CURVE_NAME), "EC_GROUP_new_by_curve_name"}, -{ERR_FUNC(EC_F_EC_GROUP_NEW_FROM_DATA), "EC_GROUP_NEW_FROM_DATA"}, -{ERR_FUNC(EC_F_EC_GROUP_PRECOMPUTE_MULT), "EC_GROUP_precompute_mult"}, -{ERR_FUNC(EC_F_EC_GROUP_SET_CURVE_GF2M), "EC_GROUP_set_curve_GF2m"}, -{ERR_FUNC(EC_F_EC_GROUP_SET_CURVE_GFP), "EC_GROUP_set_curve_GFp"}, -{ERR_FUNC(EC_F_EC_GROUP_SET_EXTRA_DATA), "EC_GROUP_SET_EXTRA_DATA"}, -{ERR_FUNC(EC_F_EC_GROUP_SET_GENERATOR), "EC_GROUP_set_generator"}, -{ERR_FUNC(EC_F_EC_KEY_CHECK_KEY), "EC_KEY_check_key"}, -{ERR_FUNC(EC_F_EC_KEY_COPY), "EC_KEY_copy"}, -{ERR_FUNC(EC_F_EC_KEY_GENERATE_KEY), "EC_KEY_generate_key"}, -{ERR_FUNC(EC_F_EC_KEY_NEW), "EC_KEY_new"}, -{ERR_FUNC(EC_F_EC_KEY_PRINT), "EC_KEY_print"}, -{ERR_FUNC(EC_F_EC_KEY_PRINT_FP), "EC_KEY_print_fp"}, -{ERR_FUNC(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES), "EC_KEY_set_public_key_affine_coordinates"}, -{ERR_FUNC(EC_F_EC_POINTS_MAKE_AFFINE), "EC_POINTs_make_affine"}, -{ERR_FUNC(EC_F_EC_POINT_ADD), "EC_POINT_add"}, -{ERR_FUNC(EC_F_EC_POINT_CMP), "EC_POINT_cmp"}, -{ERR_FUNC(EC_F_EC_POINT_COPY), "EC_POINT_copy"}, -{ERR_FUNC(EC_F_EC_POINT_DBL), "EC_POINT_dbl"}, -{ERR_FUNC(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M), "EC_POINT_get_affine_coordinates_GF2m"}, -{ERR_FUNC(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP), "EC_POINT_get_affine_coordinates_GFp"}, -{ERR_FUNC(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP), "EC_POINT_get_Jprojective_coordinates_GFp"}, -{ERR_FUNC(EC_F_EC_POINT_INVERT), "EC_POINT_invert"}, -{ERR_FUNC(EC_F_EC_POINT_IS_AT_INFINITY), "EC_POINT_is_at_infinity"}, -{ERR_FUNC(EC_F_EC_POINT_IS_ON_CURVE), "EC_POINT_is_on_curve"}, -{ERR_FUNC(EC_F_EC_POINT_MAKE_AFFINE), "EC_POINT_make_affine"}, -{ERR_FUNC(EC_F_EC_POINT_MUL), "EC_POINT_mul"}, -{ERR_FUNC(EC_F_EC_POINT_NEW), "EC_POINT_new"}, -{ERR_FUNC(EC_F_EC_POINT_OCT2POINT), "EC_POINT_oct2point"}, -{ERR_FUNC(EC_F_EC_POINT_POINT2OCT), "EC_POINT_point2oct"}, -{ERR_FUNC(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M), "EC_POINT_set_affine_coordinates_GF2m"}, -{ERR_FUNC(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP), "EC_POINT_set_affine_coordinates_GFp"}, -{ERR_FUNC(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M), "EC_POINT_set_compressed_coordinates_GF2m"}, -{ERR_FUNC(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP), "EC_POINT_set_compressed_coordinates_GFp"}, -{ERR_FUNC(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP), "EC_POINT_set_Jprojective_coordinates_GFp"}, -{ERR_FUNC(EC_F_EC_POINT_SET_TO_INFINITY), "EC_POINT_set_to_infinity"}, -{ERR_FUNC(EC_F_EC_PRE_COMP_DUP), "EC_PRE_COMP_DUP"}, -{ERR_FUNC(EC_F_EC_PRE_COMP_NEW), "EC_PRE_COMP_NEW"}, -{ERR_FUNC(EC_F_EC_WNAF_MUL), "ec_wNAF_mul"}, -{ERR_FUNC(EC_F_EC_WNAF_PRECOMPUTE_MULT), "ec_wNAF_precompute_mult"}, -{ERR_FUNC(EC_F_I2D_ECPARAMETERS), "i2d_ECParameters"}, -{ERR_FUNC(EC_F_I2D_ECPKPARAMETERS), "i2d_ECPKParameters"}, -{ERR_FUNC(EC_F_I2D_ECPRIVATEKEY), "i2d_ECPrivateKey"}, -{ERR_FUNC(EC_F_I2O_ECPUBLICKEY), "i2o_ECPublicKey"}, -{ERR_FUNC(EC_F_NISTP224_PRE_COMP_NEW), "NISTP224_PRE_COMP_NEW"}, -{ERR_FUNC(EC_F_NISTP256_PRE_COMP_NEW), "NISTP256_PRE_COMP_NEW"}, -{ERR_FUNC(EC_F_NISTP521_PRE_COMP_NEW), "NISTP521_PRE_COMP_NEW"}, -{ERR_FUNC(EC_F_O2I_ECPUBLICKEY), "o2i_ECPublicKey"}, -{ERR_FUNC(EC_F_OLD_EC_PRIV_DECODE), "OLD_EC_PRIV_DECODE"}, -{ERR_FUNC(EC_F_PKEY_EC_CTRL), "PKEY_EC_CTRL"}, -{ERR_FUNC(EC_F_PKEY_EC_CTRL_STR), "PKEY_EC_CTRL_STR"}, -{ERR_FUNC(EC_F_PKEY_EC_DERIVE), "PKEY_EC_DERIVE"}, -{ERR_FUNC(EC_F_PKEY_EC_KEYGEN), "PKEY_EC_KEYGEN"}, -{ERR_FUNC(EC_F_PKEY_EC_PARAMGEN), "PKEY_EC_PARAMGEN"}, -{ERR_FUNC(EC_F_PKEY_EC_SIGN), "PKEY_EC_SIGN"}, -{0,NULL} - }; +static ERR_STRING_DATA EC_str_functs[] = { + {ERR_FUNC(EC_F_BN_TO_FELEM), "BN_TO_FELEM"}, + {ERR_FUNC(EC_F_COMPUTE_WNAF), "COMPUTE_WNAF"}, + {ERR_FUNC(EC_F_D2I_ECPARAMETERS), "d2i_ECParameters"}, + {ERR_FUNC(EC_F_D2I_ECPKPARAMETERS), "d2i_ECPKParameters"}, + {ERR_FUNC(EC_F_D2I_ECPRIVATEKEY), "d2i_ECPrivateKey"}, + {ERR_FUNC(EC_F_DO_EC_KEY_PRINT), "DO_EC_KEY_PRINT"}, + {ERR_FUNC(EC_F_ECKEY_PARAM2TYPE), "ECKEY_PARAM2TYPE"}, + {ERR_FUNC(EC_F_ECKEY_PARAM_DECODE), "ECKEY_PARAM_DECODE"}, + {ERR_FUNC(EC_F_ECKEY_PRIV_DECODE), "ECKEY_PRIV_DECODE"}, + {ERR_FUNC(EC_F_ECKEY_PRIV_ENCODE), "ECKEY_PRIV_ENCODE"}, + {ERR_FUNC(EC_F_ECKEY_PUB_DECODE), "ECKEY_PUB_DECODE"}, + {ERR_FUNC(EC_F_ECKEY_PUB_ENCODE), "ECKEY_PUB_ENCODE"}, + {ERR_FUNC(EC_F_ECKEY_TYPE2PARAM), "ECKEY_TYPE2PARAM"}, + {ERR_FUNC(EC_F_ECPARAMETERS_PRINT), "ECParameters_print"}, + {ERR_FUNC(EC_F_ECPARAMETERS_PRINT_FP), "ECParameters_print_fp"}, + {ERR_FUNC(EC_F_ECPKPARAMETERS_PRINT), "ECPKParameters_print"}, + {ERR_FUNC(EC_F_ECPKPARAMETERS_PRINT_FP), "ECPKParameters_print_fp"}, + {ERR_FUNC(EC_F_ECP_NIST_MOD_192), "ECP_NIST_MOD_192"}, + {ERR_FUNC(EC_F_ECP_NIST_MOD_224), "ECP_NIST_MOD_224"}, + {ERR_FUNC(EC_F_ECP_NIST_MOD_256), "ECP_NIST_MOD_256"}, + {ERR_FUNC(EC_F_ECP_NIST_MOD_521), "ECP_NIST_MOD_521"}, + {ERR_FUNC(EC_F_EC_ASN1_GROUP2CURVE), "EC_ASN1_GROUP2CURVE"}, + {ERR_FUNC(EC_F_EC_ASN1_GROUP2FIELDID), "EC_ASN1_GROUP2FIELDID"}, + {ERR_FUNC(EC_F_EC_ASN1_GROUP2PARAMETERS), "EC_ASN1_GROUP2PARAMETERS"}, + {ERR_FUNC(EC_F_EC_ASN1_GROUP2PKPARAMETERS), "EC_ASN1_GROUP2PKPARAMETERS"}, + {ERR_FUNC(EC_F_EC_ASN1_PARAMETERS2GROUP), "EC_ASN1_PARAMETERS2GROUP"}, + {ERR_FUNC(EC_F_EC_ASN1_PKPARAMETERS2GROUP), "EC_ASN1_PKPARAMETERS2GROUP"}, + {ERR_FUNC(EC_F_EC_EX_DATA_SET_DATA), "EC_EX_DATA_set_data"}, + {ERR_FUNC(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY), + "EC_GF2M_MONTGOMERY_POINT_MULTIPLY"}, + {ERR_FUNC(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT), + "ec_GF2m_simple_group_check_discriminant"}, + {ERR_FUNC(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE), + "ec_GF2m_simple_group_set_curve"}, + {ERR_FUNC(EC_F_EC_GF2M_SIMPLE_OCT2POINT), "ec_GF2m_simple_oct2point"}, + {ERR_FUNC(EC_F_EC_GF2M_SIMPLE_POINT2OCT), "ec_GF2m_simple_point2oct"}, + {ERR_FUNC(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES), + "ec_GF2m_simple_point_get_affine_coordinates"}, + {ERR_FUNC(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES), + "ec_GF2m_simple_point_set_affine_coordinates"}, + {ERR_FUNC(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES), + "ec_GF2m_simple_set_compressed_coordinates"}, + {ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_DECODE), "ec_GFp_mont_field_decode"}, + {ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_ENCODE), "ec_GFp_mont_field_encode"}, + {ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_MUL), "ec_GFp_mont_field_mul"}, + {ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE), + "ec_GFp_mont_field_set_to_one"}, + {ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_SQR), "ec_GFp_mont_field_sqr"}, + {ERR_FUNC(EC_F_EC_GFP_MONT_GROUP_SET_CURVE), + "ec_GFp_mont_group_set_curve"}, + {ERR_FUNC(EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP), + "EC_GFP_MONT_GROUP_SET_CURVE_GFP"}, + {ERR_FUNC(EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE), + "ec_GFp_nistp224_group_set_curve"}, + {ERR_FUNC(EC_F_EC_GFP_NISTP224_POINTS_MUL), "ec_GFp_nistp224_points_mul"}, + {ERR_FUNC(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES), + "ec_GFp_nistp224_point_get_affine_coordinates"}, + {ERR_FUNC(EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE), + "ec_GFp_nistp256_group_set_curve"}, + {ERR_FUNC(EC_F_EC_GFP_NISTP256_POINTS_MUL), "ec_GFp_nistp256_points_mul"}, + {ERR_FUNC(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES), + "ec_GFp_nistp256_point_get_affine_coordinates"}, + {ERR_FUNC(EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE), + "ec_GFp_nistp521_group_set_curve"}, + {ERR_FUNC(EC_F_EC_GFP_NISTP521_POINTS_MUL), "ec_GFp_nistp521_points_mul"}, + {ERR_FUNC(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES), + "ec_GFp_nistp521_point_get_affine_coordinates"}, + {ERR_FUNC(EC_F_EC_GFP_NIST_FIELD_MUL), "ec_GFp_nist_field_mul"}, + {ERR_FUNC(EC_F_EC_GFP_NIST_FIELD_SQR), "ec_GFp_nist_field_sqr"}, + {ERR_FUNC(EC_F_EC_GFP_NIST_GROUP_SET_CURVE), + "ec_GFp_nist_group_set_curve"}, + {ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT), + "ec_GFp_simple_group_check_discriminant"}, + {ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE), + "ec_GFp_simple_group_set_curve"}, + {ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP), + "EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP"}, + {ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR), + "EC_GFP_SIMPLE_GROUP_SET_GENERATOR"}, + {ERR_FUNC(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE), "ec_GFp_simple_make_affine"}, + {ERR_FUNC(EC_F_EC_GFP_SIMPLE_OCT2POINT), "ec_GFp_simple_oct2point"}, + {ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT2OCT), "ec_GFp_simple_point2oct"}, + {ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE), + "ec_GFp_simple_points_make_affine"}, + {ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES), + "ec_GFp_simple_point_get_affine_coordinates"}, + {ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP), + "EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP"}, + {ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES), + "ec_GFp_simple_point_set_affine_coordinates"}, + {ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP), + "EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP"}, + {ERR_FUNC(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES), + "ec_GFp_simple_set_compressed_coordinates"}, + {ERR_FUNC(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP), + "EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP"}, + {ERR_FUNC(EC_F_EC_GROUP_CHECK), "EC_GROUP_check"}, + {ERR_FUNC(EC_F_EC_GROUP_CHECK_DISCRIMINANT), + "EC_GROUP_check_discriminant"}, + {ERR_FUNC(EC_F_EC_GROUP_COPY), "EC_GROUP_copy"}, + {ERR_FUNC(EC_F_EC_GROUP_GET0_GENERATOR), "EC_GROUP_get0_generator"}, + {ERR_FUNC(EC_F_EC_GROUP_GET_COFACTOR), "EC_GROUP_get_cofactor"}, + {ERR_FUNC(EC_F_EC_GROUP_GET_CURVE_GF2M), "EC_GROUP_get_curve_GF2m"}, + {ERR_FUNC(EC_F_EC_GROUP_GET_CURVE_GFP), "EC_GROUP_get_curve_GFp"}, + {ERR_FUNC(EC_F_EC_GROUP_GET_DEGREE), "EC_GROUP_get_degree"}, + {ERR_FUNC(EC_F_EC_GROUP_GET_ORDER), "EC_GROUP_get_order"}, + {ERR_FUNC(EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS), + "EC_GROUP_get_pentanomial_basis"}, + {ERR_FUNC(EC_F_EC_GROUP_GET_TRINOMIAL_BASIS), + "EC_GROUP_get_trinomial_basis"}, + {ERR_FUNC(EC_F_EC_GROUP_NEW), "EC_GROUP_new"}, + {ERR_FUNC(EC_F_EC_GROUP_NEW_BY_CURVE_NAME), "EC_GROUP_new_by_curve_name"}, + {ERR_FUNC(EC_F_EC_GROUP_NEW_FROM_DATA), "EC_GROUP_NEW_FROM_DATA"}, + {ERR_FUNC(EC_F_EC_GROUP_PRECOMPUTE_MULT), "EC_GROUP_precompute_mult"}, + {ERR_FUNC(EC_F_EC_GROUP_SET_CURVE_GF2M), "EC_GROUP_set_curve_GF2m"}, + {ERR_FUNC(EC_F_EC_GROUP_SET_CURVE_GFP), "EC_GROUP_set_curve_GFp"}, + {ERR_FUNC(EC_F_EC_GROUP_SET_EXTRA_DATA), "EC_GROUP_SET_EXTRA_DATA"}, + {ERR_FUNC(EC_F_EC_GROUP_SET_GENERATOR), "EC_GROUP_set_generator"}, + {ERR_FUNC(EC_F_EC_KEY_CHECK_KEY), "EC_KEY_check_key"}, + {ERR_FUNC(EC_F_EC_KEY_COPY), "EC_KEY_copy"}, + {ERR_FUNC(EC_F_EC_KEY_GENERATE_KEY), "EC_KEY_generate_key"}, + {ERR_FUNC(EC_F_EC_KEY_NEW), "EC_KEY_new"}, + {ERR_FUNC(EC_F_EC_KEY_PRINT), "EC_KEY_print"}, + {ERR_FUNC(EC_F_EC_KEY_PRINT_FP), "EC_KEY_print_fp"}, + {ERR_FUNC(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES), + "EC_KEY_set_public_key_affine_coordinates"}, + {ERR_FUNC(EC_F_EC_POINTS_MAKE_AFFINE), "EC_POINTs_make_affine"}, + {ERR_FUNC(EC_F_EC_POINT_ADD), "EC_POINT_add"}, + {ERR_FUNC(EC_F_EC_POINT_CMP), "EC_POINT_cmp"}, + {ERR_FUNC(EC_F_EC_POINT_COPY), "EC_POINT_copy"}, + {ERR_FUNC(EC_F_EC_POINT_DBL), "EC_POINT_dbl"}, + {ERR_FUNC(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M), + "EC_POINT_get_affine_coordinates_GF2m"}, + {ERR_FUNC(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP), + "EC_POINT_get_affine_coordinates_GFp"}, + {ERR_FUNC(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP), + "EC_POINT_get_Jprojective_coordinates_GFp"}, + {ERR_FUNC(EC_F_EC_POINT_INVERT), "EC_POINT_invert"}, + {ERR_FUNC(EC_F_EC_POINT_IS_AT_INFINITY), "EC_POINT_is_at_infinity"}, + {ERR_FUNC(EC_F_EC_POINT_IS_ON_CURVE), "EC_POINT_is_on_curve"}, + {ERR_FUNC(EC_F_EC_POINT_MAKE_AFFINE), "EC_POINT_make_affine"}, + {ERR_FUNC(EC_F_EC_POINT_MUL), "EC_POINT_mul"}, + {ERR_FUNC(EC_F_EC_POINT_NEW), "EC_POINT_new"}, + {ERR_FUNC(EC_F_EC_POINT_OCT2POINT), "EC_POINT_oct2point"}, + {ERR_FUNC(EC_F_EC_POINT_POINT2OCT), "EC_POINT_point2oct"}, + {ERR_FUNC(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M), + "EC_POINT_set_affine_coordinates_GF2m"}, + {ERR_FUNC(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP), + "EC_POINT_set_affine_coordinates_GFp"}, + {ERR_FUNC(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M), + "EC_POINT_set_compressed_coordinates_GF2m"}, + {ERR_FUNC(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP), + "EC_POINT_set_compressed_coordinates_GFp"}, + {ERR_FUNC(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP), + "EC_POINT_set_Jprojective_coordinates_GFp"}, + {ERR_FUNC(EC_F_EC_POINT_SET_TO_INFINITY), "EC_POINT_set_to_infinity"}, + {ERR_FUNC(EC_F_EC_PRE_COMP_DUP), "EC_PRE_COMP_DUP"}, + {ERR_FUNC(EC_F_EC_PRE_COMP_NEW), "EC_PRE_COMP_NEW"}, + {ERR_FUNC(EC_F_EC_WNAF_MUL), "ec_wNAF_mul"}, + {ERR_FUNC(EC_F_EC_WNAF_PRECOMPUTE_MULT), "ec_wNAF_precompute_mult"}, + {ERR_FUNC(EC_F_I2D_ECPARAMETERS), "i2d_ECParameters"}, + {ERR_FUNC(EC_F_I2D_ECPKPARAMETERS), "i2d_ECPKParameters"}, + {ERR_FUNC(EC_F_I2D_ECPRIVATEKEY), "i2d_ECPrivateKey"}, + {ERR_FUNC(EC_F_I2O_ECPUBLICKEY), "i2o_ECPublicKey"}, + {ERR_FUNC(EC_F_NISTP224_PRE_COMP_NEW), "NISTP224_PRE_COMP_NEW"}, + {ERR_FUNC(EC_F_NISTP256_PRE_COMP_NEW), "NISTP256_PRE_COMP_NEW"}, + {ERR_FUNC(EC_F_NISTP521_PRE_COMP_NEW), "NISTP521_PRE_COMP_NEW"}, + {ERR_FUNC(EC_F_O2I_ECPUBLICKEY), "o2i_ECPublicKey"}, + {ERR_FUNC(EC_F_OLD_EC_PRIV_DECODE), "OLD_EC_PRIV_DECODE"}, + {ERR_FUNC(EC_F_PKEY_EC_CTRL), "PKEY_EC_CTRL"}, + {ERR_FUNC(EC_F_PKEY_EC_CTRL_STR), "PKEY_EC_CTRL_STR"}, + {ERR_FUNC(EC_F_PKEY_EC_DERIVE), "PKEY_EC_DERIVE"}, + {ERR_FUNC(EC_F_PKEY_EC_KEYGEN), "PKEY_EC_KEYGEN"}, + {ERR_FUNC(EC_F_PKEY_EC_PARAMGEN), "PKEY_EC_PARAMGEN"}, + {ERR_FUNC(EC_F_PKEY_EC_SIGN), "PKEY_EC_SIGN"}, + {0, NULL} +}; -static ERR_STRING_DATA EC_str_reasons[]= - { -{ERR_REASON(EC_R_ASN1_ERROR) ,"asn1 error"}, -{ERR_REASON(EC_R_ASN1_UNKNOWN_FIELD) ,"asn1 unknown field"}, -{ERR_REASON(EC_R_BIGNUM_OUT_OF_RANGE) ,"bignum out of range"}, -{ERR_REASON(EC_R_BUFFER_TOO_SMALL) ,"buffer too small"}, -{ERR_REASON(EC_R_COORDINATES_OUT_OF_RANGE),"coordinates out of range"}, -{ERR_REASON(EC_R_D2I_ECPKPARAMETERS_FAILURE),"d2i ecpkparameters failure"}, -{ERR_REASON(EC_R_DECODE_ERROR) ,"decode error"}, -{ERR_REASON(EC_R_DISCRIMINANT_IS_ZERO) ,"discriminant is zero"}, -{ERR_REASON(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE),"ec group new by name failure"}, -{ERR_REASON(EC_R_FIELD_TOO_LARGE) ,"field too large"}, -{ERR_REASON(EC_R_GF2M_NOT_SUPPORTED) ,"gf2m not supported"}, -{ERR_REASON(EC_R_GROUP2PKPARAMETERS_FAILURE),"group2pkparameters failure"}, -{ERR_REASON(EC_R_I2D_ECPKPARAMETERS_FAILURE),"i2d ecpkparameters failure"}, -{ERR_REASON(EC_R_INCOMPATIBLE_OBJECTS) ,"incompatible objects"}, -{ERR_REASON(EC_R_INVALID_ARGUMENT) ,"invalid argument"}, -{ERR_REASON(EC_R_INVALID_COMPRESSED_POINT),"invalid compressed point"}, -{ERR_REASON(EC_R_INVALID_COMPRESSION_BIT),"invalid compression bit"}, -{ERR_REASON(EC_R_INVALID_CURVE) ,"invalid curve"}, -{ERR_REASON(EC_R_INVALID_DIGEST_TYPE) ,"invalid digest type"}, -{ERR_REASON(EC_R_INVALID_ENCODING) ,"invalid encoding"}, -{ERR_REASON(EC_R_INVALID_FIELD) ,"invalid field"}, -{ERR_REASON(EC_R_INVALID_FORM) ,"invalid form"}, -{ERR_REASON(EC_R_INVALID_GROUP_ORDER) ,"invalid group order"}, -{ERR_REASON(EC_R_INVALID_PENTANOMIAL_BASIS),"invalid pentanomial basis"}, -{ERR_REASON(EC_R_INVALID_PRIVATE_KEY) ,"invalid private key"}, -{ERR_REASON(EC_R_INVALID_TRINOMIAL_BASIS),"invalid trinomial basis"}, -{ERR_REASON(EC_R_KEYS_NOT_SET) ,"keys not set"}, -{ERR_REASON(EC_R_MISSING_PARAMETERS) ,"missing parameters"}, -{ERR_REASON(EC_R_MISSING_PRIVATE_KEY) ,"missing private key"}, -{ERR_REASON(EC_R_NOT_A_NIST_PRIME) ,"not a NIST prime"}, -{ERR_REASON(EC_R_NOT_A_SUPPORTED_NIST_PRIME),"not a supported NIST prime"}, -{ERR_REASON(EC_R_NOT_IMPLEMENTED) ,"not implemented"}, -{ERR_REASON(EC_R_NOT_INITIALIZED) ,"not initialized"}, -{ERR_REASON(EC_R_NO_FIELD_MOD) ,"no field mod"}, -{ERR_REASON(EC_R_NO_PARAMETERS_SET) ,"no parameters set"}, -{ERR_REASON(EC_R_PASSED_NULL_PARAMETER) ,"passed null parameter"}, -{ERR_REASON(EC_R_PKPARAMETERS2GROUP_FAILURE),"pkparameters2group failure"}, -{ERR_REASON(EC_R_POINT_AT_INFINITY) ,"point at infinity"}, -{ERR_REASON(EC_R_POINT_IS_NOT_ON_CURVE) ,"point is not on curve"}, -{ERR_REASON(EC_R_SLOT_FULL) ,"slot full"}, -{ERR_REASON(EC_R_UNDEFINED_GENERATOR) ,"undefined generator"}, -{ERR_REASON(EC_R_UNDEFINED_ORDER) ,"undefined order"}, -{ERR_REASON(EC_R_UNKNOWN_GROUP) ,"unknown group"}, -{ERR_REASON(EC_R_UNKNOWN_ORDER) ,"unknown order"}, -{ERR_REASON(EC_R_UNSUPPORTED_FIELD) ,"unsupported field"}, -{ERR_REASON(EC_R_WRONG_CURVE_PARAMETERS) ,"wrong curve parameters"}, -{ERR_REASON(EC_R_WRONG_ORDER) ,"wrong order"}, -{0,NULL} - }; +static ERR_STRING_DATA EC_str_reasons[] = { + {ERR_REASON(EC_R_ASN1_ERROR), "asn1 error"}, + {ERR_REASON(EC_R_ASN1_UNKNOWN_FIELD), "asn1 unknown field"}, + {ERR_REASON(EC_R_BIGNUM_OUT_OF_RANGE), "bignum out of range"}, + {ERR_REASON(EC_R_BUFFER_TOO_SMALL), "buffer too small"}, + {ERR_REASON(EC_R_COORDINATES_OUT_OF_RANGE), "coordinates out of range"}, + {ERR_REASON(EC_R_D2I_ECPKPARAMETERS_FAILURE), + "d2i ecpkparameters failure"}, + {ERR_REASON(EC_R_DECODE_ERROR), "decode error"}, + {ERR_REASON(EC_R_DISCRIMINANT_IS_ZERO), "discriminant is zero"}, + {ERR_REASON(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE), + "ec group new by name failure"}, + {ERR_REASON(EC_R_FIELD_TOO_LARGE), "field too large"}, + {ERR_REASON(EC_R_GF2M_NOT_SUPPORTED), "gf2m not supported"}, + {ERR_REASON(EC_R_GROUP2PKPARAMETERS_FAILURE), + "group2pkparameters failure"}, + {ERR_REASON(EC_R_I2D_ECPKPARAMETERS_FAILURE), + "i2d ecpkparameters failure"}, + {ERR_REASON(EC_R_INCOMPATIBLE_OBJECTS), "incompatible objects"}, + {ERR_REASON(EC_R_INVALID_ARGUMENT), "invalid argument"}, + {ERR_REASON(EC_R_INVALID_COMPRESSED_POINT), "invalid compressed point"}, + {ERR_REASON(EC_R_INVALID_COMPRESSION_BIT), "invalid compression bit"}, + {ERR_REASON(EC_R_INVALID_CURVE), "invalid curve"}, + {ERR_REASON(EC_R_INVALID_DIGEST_TYPE), "invalid digest type"}, + {ERR_REASON(EC_R_INVALID_ENCODING), "invalid encoding"}, + {ERR_REASON(EC_R_INVALID_FIELD), "invalid field"}, + {ERR_REASON(EC_R_INVALID_FORM), "invalid form"}, + {ERR_REASON(EC_R_INVALID_GROUP_ORDER), "invalid group order"}, + {ERR_REASON(EC_R_INVALID_PENTANOMIAL_BASIS), "invalid pentanomial basis"}, + {ERR_REASON(EC_R_INVALID_PRIVATE_KEY), "invalid private key"}, + {ERR_REASON(EC_R_INVALID_TRINOMIAL_BASIS), "invalid trinomial basis"}, + {ERR_REASON(EC_R_KEYS_NOT_SET), "keys not set"}, + {ERR_REASON(EC_R_MISSING_PARAMETERS), "missing parameters"}, + {ERR_REASON(EC_R_MISSING_PRIVATE_KEY), "missing private key"}, + {ERR_REASON(EC_R_NOT_A_NIST_PRIME), "not a NIST prime"}, + {ERR_REASON(EC_R_NOT_A_SUPPORTED_NIST_PRIME), + "not a supported NIST prime"}, + {ERR_REASON(EC_R_NOT_IMPLEMENTED), "not implemented"}, + {ERR_REASON(EC_R_NOT_INITIALIZED), "not initialized"}, + {ERR_REASON(EC_R_NO_FIELD_MOD), "no field mod"}, + {ERR_REASON(EC_R_NO_PARAMETERS_SET), "no parameters set"}, + {ERR_REASON(EC_R_PASSED_NULL_PARAMETER), "passed null parameter"}, + {ERR_REASON(EC_R_PKPARAMETERS2GROUP_FAILURE), + "pkparameters2group failure"}, + {ERR_REASON(EC_R_POINT_AT_INFINITY), "point at infinity"}, + {ERR_REASON(EC_R_POINT_IS_NOT_ON_CURVE), "point is not on curve"}, + {ERR_REASON(EC_R_SLOT_FULL), "slot full"}, + {ERR_REASON(EC_R_UNDEFINED_GENERATOR), "undefined generator"}, + {ERR_REASON(EC_R_UNDEFINED_ORDER), "undefined order"}, + {ERR_REASON(EC_R_UNKNOWN_GROUP), "unknown group"}, + {ERR_REASON(EC_R_UNKNOWN_ORDER), "unknown order"}, + {ERR_REASON(EC_R_UNSUPPORTED_FIELD), "unsupported field"}, + {ERR_REASON(EC_R_WRONG_CURVE_PARAMETERS), "wrong curve parameters"}, + {ERR_REASON(EC_R_WRONG_ORDER), "wrong order"}, + {0, NULL} +}; #endif void ERR_load_EC_strings(void) - { +{ #ifndef OPENSSL_NO_ERR - if (ERR_func_error_string(EC_str_functs[0].error) == NULL) - { - ERR_load_strings(0,EC_str_functs); - ERR_load_strings(0,EC_str_reasons); - } + if (ERR_func_error_string(EC_str_functs[0].error) == NULL) { + ERR_load_strings(0, EC_str_functs); + ERR_load_strings(0, EC_str_reasons); + } #endif - } +} diff --git a/openssl/crypto/ec/ec_key.c b/openssl/crypto/ec/ec_key.c index 7fa247593..ebdffc821 100644 --- a/openssl/crypto/ec/ec_key.c +++ b/openssl/crypto/ec/ec_key.c @@ -10,7 +10,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -57,7 +57,7 @@ */ /* ==================================================================== * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. - * Portions originally developed by SUN MICROSYSTEMS, INC., and + * Portions originally developed by SUN MICROSYSTEMS, INC., and * contributed to the OpenSSL project. */ @@ -65,508 +65,495 @@ #include "ec_lcl.h" #include <openssl/err.h> #ifdef OPENSSL_FIPS -#include <openssl/fips.h> +# include <openssl/fips.h> #endif EC_KEY *EC_KEY_new(void) - { - EC_KEY *ret; - - ret=(EC_KEY *)OPENSSL_malloc(sizeof(EC_KEY)); - if (ret == NULL) - { - ECerr(EC_F_EC_KEY_NEW, ERR_R_MALLOC_FAILURE); - return(NULL); - } - - ret->version = 1; - ret->flags = 0; - ret->group = NULL; - ret->pub_key = NULL; - ret->priv_key= NULL; - ret->enc_flag= 0; - ret->conv_form = POINT_CONVERSION_UNCOMPRESSED; - ret->references= 1; - ret->method_data = NULL; - return(ret); - } +{ + EC_KEY *ret; + + ret = (EC_KEY *)OPENSSL_malloc(sizeof(EC_KEY)); + if (ret == NULL) { + ECerr(EC_F_EC_KEY_NEW, ERR_R_MALLOC_FAILURE); + return (NULL); + } + + ret->version = 1; + ret->flags = 0; + ret->group = NULL; + ret->pub_key = NULL; + ret->priv_key = NULL; + ret->enc_flag = 0; + ret->conv_form = POINT_CONVERSION_UNCOMPRESSED; + ret->references = 1; + ret->method_data = NULL; + return (ret); +} EC_KEY *EC_KEY_new_by_curve_name(int nid) - { - EC_KEY *ret = EC_KEY_new(); - if (ret == NULL) - return NULL; - ret->group = EC_GROUP_new_by_curve_name(nid); - if (ret->group == NULL) - { - EC_KEY_free(ret); - return NULL; - } - return ret; - } +{ + EC_KEY *ret = EC_KEY_new(); + if (ret == NULL) + return NULL; + ret->group = EC_GROUP_new_by_curve_name(nid); + if (ret->group == NULL) { + EC_KEY_free(ret); + return NULL; + } + return ret; +} void EC_KEY_free(EC_KEY *r) - { - int i; +{ + int i; - if (r == NULL) return; + if (r == NULL) + return; - i=CRYPTO_add(&r->references,-1,CRYPTO_LOCK_EC); + i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_EC); #ifdef REF_PRINT - REF_PRINT("EC_KEY",r); + REF_PRINT("EC_KEY", r); #endif - if (i > 0) return; + if (i > 0) + return; #ifdef REF_CHECK - if (i < 0) - { - fprintf(stderr,"EC_KEY_free, bad reference count\n"); - abort(); - } + if (i < 0) { + fprintf(stderr, "EC_KEY_free, bad reference count\n"); + abort(); + } #endif - if (r->group != NULL) - EC_GROUP_free(r->group); - if (r->pub_key != NULL) - EC_POINT_free(r->pub_key); - if (r->priv_key != NULL) - BN_clear_free(r->priv_key); + if (r->group != NULL) + EC_GROUP_free(r->group); + if (r->pub_key != NULL) + EC_POINT_free(r->pub_key); + if (r->priv_key != NULL) + BN_clear_free(r->priv_key); - EC_EX_DATA_free_all_data(&r->method_data); + EC_EX_DATA_free_all_data(&r->method_data); - OPENSSL_cleanse((void *)r, sizeof(EC_KEY)); + OPENSSL_cleanse((void *)r, sizeof(EC_KEY)); - OPENSSL_free(r); - } + OPENSSL_free(r); +} EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) - { - EC_EXTRA_DATA *d; - - if (dest == NULL || src == NULL) - { - ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER); - return NULL; - } - /* copy the parameters */ - if (src->group) - { - const EC_METHOD *meth = EC_GROUP_method_of(src->group); - /* clear the old group */ - if (dest->group) - EC_GROUP_free(dest->group); - dest->group = EC_GROUP_new(meth); - if (dest->group == NULL) - return NULL; - if (!EC_GROUP_copy(dest->group, src->group)) - return NULL; - } - /* copy the public key */ - if (src->pub_key && src->group) - { - if (dest->pub_key) - EC_POINT_free(dest->pub_key); - dest->pub_key = EC_POINT_new(src->group); - if (dest->pub_key == NULL) - return NULL; - if (!EC_POINT_copy(dest->pub_key, src->pub_key)) - return NULL; - } - /* copy the private key */ - if (src->priv_key) - { - if (dest->priv_key == NULL) - { - dest->priv_key = BN_new(); - if (dest->priv_key == NULL) - return NULL; - } - if (!BN_copy(dest->priv_key, src->priv_key)) - return NULL; - } - /* copy method/extra data */ - EC_EX_DATA_free_all_data(&dest->method_data); - - for (d = src->method_data; d != NULL; d = d->next) - { - void *t = d->dup_func(d->data); - - if (t == NULL) - return 0; - if (!EC_EX_DATA_set_data(&dest->method_data, t, d->dup_func, d->free_func, d->clear_free_func)) - return 0; - } - - /* copy the rest */ - dest->enc_flag = src->enc_flag; - dest->conv_form = src->conv_form; - dest->version = src->version; - dest->flags = src->flags; - - return dest; - } +{ + EC_EXTRA_DATA *d; + + if (dest == NULL || src == NULL) { + ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + /* copy the parameters */ + if (src->group) { + const EC_METHOD *meth = EC_GROUP_method_of(src->group); + /* clear the old group */ + if (dest->group) + EC_GROUP_free(dest->group); + dest->group = EC_GROUP_new(meth); + if (dest->group == NULL) + return NULL; + if (!EC_GROUP_copy(dest->group, src->group)) + return NULL; + } + /* copy the public key */ + if (src->pub_key && src->group) { + if (dest->pub_key) + EC_POINT_free(dest->pub_key); + dest->pub_key = EC_POINT_new(src->group); + if (dest->pub_key == NULL) + return NULL; + if (!EC_POINT_copy(dest->pub_key, src->pub_key)) + return NULL; + } + /* copy the private key */ + if (src->priv_key) { + if (dest->priv_key == NULL) { + dest->priv_key = BN_new(); + if (dest->priv_key == NULL) + return NULL; + } + if (!BN_copy(dest->priv_key, src->priv_key)) + return NULL; + } + /* copy method/extra data */ + EC_EX_DATA_free_all_data(&dest->method_data); + + for (d = src->method_data; d != NULL; d = d->next) { + void *t = d->dup_func(d->data); + + if (t == NULL) + return 0; + if (!EC_EX_DATA_set_data + (&dest->method_data, t, d->dup_func, d->free_func, + d->clear_free_func)) + return 0; + } + + /* copy the rest */ + dest->enc_flag = src->enc_flag; + dest->conv_form = src->conv_form; + dest->version = src->version; + dest->flags = src->flags; + + return dest; +} EC_KEY *EC_KEY_dup(const EC_KEY *ec_key) - { - EC_KEY *ret = EC_KEY_new(); - if (ret == NULL) - return NULL; - if (EC_KEY_copy(ret, ec_key) == NULL) - { - EC_KEY_free(ret); - return NULL; - } - return ret; - } +{ + EC_KEY *ret = EC_KEY_new(); + if (ret == NULL) + return NULL; + if (EC_KEY_copy(ret, ec_key) == NULL) { + EC_KEY_free(ret); + return NULL; + } + return ret; +} int EC_KEY_up_ref(EC_KEY *r) - { - int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_EC); +{ + int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_EC); #ifdef REF_PRINT - REF_PRINT("EC_KEY",r); + REF_PRINT("EC_KEY", r); #endif #ifdef REF_CHECK - if (i < 2) - { - fprintf(stderr, "EC_KEY_up, bad reference count\n"); - abort(); - } + if (i < 2) { + fprintf(stderr, "EC_KEY_up, bad reference count\n"); + abort(); + } #endif - return ((i > 1) ? 1 : 0); - } + return ((i > 1) ? 1 : 0); +} int EC_KEY_generate_key(EC_KEY *eckey) - { - int ok = 0; - BN_CTX *ctx = NULL; - BIGNUM *priv_key = NULL, *order = NULL; - EC_POINT *pub_key = NULL; +{ + int ok = 0; + BN_CTX *ctx = NULL; + BIGNUM *priv_key = NULL, *order = NULL; + EC_POINT *pub_key = NULL; #ifdef OPENSSL_FIPS - if (FIPS_mode()) - return FIPS_ec_key_generate_key(eckey); + if (FIPS_mode()) + return FIPS_ec_key_generate_key(eckey); #endif - if (!eckey || !eckey->group) - { - ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - - if ((order = BN_new()) == NULL) goto err; - if ((ctx = BN_CTX_new()) == NULL) goto err; - - if (eckey->priv_key == NULL) - { - priv_key = BN_new(); - if (priv_key == NULL) - goto err; - } - else - priv_key = eckey->priv_key; - - if (!EC_GROUP_get_order(eckey->group, order, ctx)) - goto err; - - do - if (!BN_rand_range(priv_key, order)) - goto err; - while (BN_is_zero(priv_key)); - - if (eckey->pub_key == NULL) - { - pub_key = EC_POINT_new(eckey->group); - if (pub_key == NULL) - goto err; - } - else - pub_key = eckey->pub_key; - - if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, ctx)) - goto err; - - eckey->priv_key = priv_key; - eckey->pub_key = pub_key; - - ok=1; - -err: - if (order) - BN_free(order); - if (pub_key != NULL && eckey->pub_key == NULL) - EC_POINT_free(pub_key); - if (priv_key != NULL && eckey->priv_key == NULL) - BN_free(priv_key); - if (ctx != NULL) - BN_CTX_free(ctx); - return(ok); - } + if (!eckey || !eckey->group) { + ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if ((order = BN_new()) == NULL) + goto err; + if ((ctx = BN_CTX_new()) == NULL) + goto err; + + if (eckey->priv_key == NULL) { + priv_key = BN_new(); + if (priv_key == NULL) + goto err; + } else + priv_key = eckey->priv_key; + + if (!EC_GROUP_get_order(eckey->group, order, ctx)) + goto err; + + do + if (!BN_rand_range(priv_key, order)) + goto err; + while (BN_is_zero(priv_key)) ; + + if (eckey->pub_key == NULL) { + pub_key = EC_POINT_new(eckey->group); + if (pub_key == NULL) + goto err; + } else + pub_key = eckey->pub_key; + + if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, ctx)) + goto err; + + eckey->priv_key = priv_key; + eckey->pub_key = pub_key; + + ok = 1; + + err: + if (order) + BN_free(order); + if (pub_key != NULL && eckey->pub_key == NULL) + EC_POINT_free(pub_key); + if (priv_key != NULL && eckey->priv_key == NULL) + BN_free(priv_key); + if (ctx != NULL) + BN_CTX_free(ctx); + return (ok); +} int EC_KEY_check_key(const EC_KEY *eckey) - { - int ok = 0; - BN_CTX *ctx = NULL; - const BIGNUM *order = NULL; - EC_POINT *point = NULL; - - if (!eckey || !eckey->group || !eckey->pub_key) - { - ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - - if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) - { - ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_AT_INFINITY); - goto err; - } - - if ((ctx = BN_CTX_new()) == NULL) - goto err; - if ((point = EC_POINT_new(eckey->group)) == NULL) - goto err; - - /* testing whether the pub_key is on the elliptic curve */ - if (!EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx)) - { - ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE); - goto err; - } - /* testing whether pub_key * order is the point at infinity */ - order = &eckey->group->order; - if (BN_is_zero(order)) - { - ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_GROUP_ORDER); - goto err; - } - if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) - { - ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB); - goto err; - } - if (!EC_POINT_is_at_infinity(eckey->group, point)) - { - ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER); - goto err; - } - /* in case the priv_key is present : - * check if generator * priv_key == pub_key - */ - if (eckey->priv_key) - { - if (BN_cmp(eckey->priv_key, order) >= 0) - { - ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER); - goto err; - } - if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, - NULL, NULL, ctx)) - { - ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB); - goto err; - } - if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, - ctx) != 0) - { - ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY); - goto err; - } - } - ok = 1; -err: - if (ctx != NULL) - BN_CTX_free(ctx); - if (point != NULL) - EC_POINT_free(point); - return(ok); - } - -int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y) - { - BN_CTX *ctx = NULL; - BIGNUM *tx, *ty; - EC_POINT *point = NULL; - int ok = 0, tmp_nid, is_char_two = 0; - - if (!key || !key->group || !x || !y) - { - ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, - ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - ctx = BN_CTX_new(); - if (!ctx) - goto err; - - point = EC_POINT_new(key->group); - - if (!point) - goto err; - - tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(key->group)); - - if (tmp_nid == NID_X9_62_characteristic_two_field) - is_char_two = 1; - - tx = BN_CTX_get(ctx); - ty = BN_CTX_get(ctx); +{ + int ok = 0; + BN_CTX *ctx = NULL; + const BIGNUM *order = NULL; + EC_POINT *point = NULL; + + if (!eckey || !eckey->group || !eckey->pub_key) { + ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) { + ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_AT_INFINITY); + goto err; + } + + if ((ctx = BN_CTX_new()) == NULL) + goto err; + if ((point = EC_POINT_new(eckey->group)) == NULL) + goto err; + + /* testing whether the pub_key is on the elliptic curve */ + if (!EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx)) { + ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE); + goto err; + } + /* testing whether pub_key * order is the point at infinity */ + order = &eckey->group->order; + if (BN_is_zero(order)) { + ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_GROUP_ORDER); + goto err; + } + if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) { + ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB); + goto err; + } + if (!EC_POINT_is_at_infinity(eckey->group, point)) { + ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER); + goto err; + } + /* + * in case the priv_key is present : check if generator * priv_key == + * pub_key + */ + if (eckey->priv_key) { + if (BN_cmp(eckey->priv_key, order) >= 0) { + ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER); + goto err; + } + if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, + NULL, NULL, ctx)) { + ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB); + goto err; + } + if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) { + ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY); + goto err; + } + } + ok = 1; + err: + if (ctx != NULL) + BN_CTX_free(ctx); + if (point != NULL) + EC_POINT_free(point); + return (ok); +} + +int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, + BIGNUM *y) +{ + BN_CTX *ctx = NULL; + BIGNUM *tx, *ty; + EC_POINT *point = NULL; + int ok = 0, tmp_nid, is_char_two = 0; + + if (!key || !key->group || !x || !y) { + ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + ctx = BN_CTX_new(); + if (!ctx) + goto err; + + point = EC_POINT_new(key->group); + + if (!point) + goto err; + + tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(key->group)); + + if (tmp_nid == NID_X9_62_characteristic_two_field) + is_char_two = 1; + + tx = BN_CTX_get(ctx); + ty = BN_CTX_get(ctx); #ifndef OPENSSL_NO_EC2M - if (is_char_two) - { - if (!EC_POINT_set_affine_coordinates_GF2m(key->group, point, - x, y, ctx)) - goto err; - if (!EC_POINT_get_affine_coordinates_GF2m(key->group, point, - tx, ty, ctx)) - goto err; - } - else + if (is_char_two) { + if (!EC_POINT_set_affine_coordinates_GF2m(key->group, point, + x, y, ctx)) + goto err; + if (!EC_POINT_get_affine_coordinates_GF2m(key->group, point, + tx, ty, ctx)) + goto err; + } else #endif - { - if (!EC_POINT_set_affine_coordinates_GFp(key->group, point, - x, y, ctx)) - goto err; - if (!EC_POINT_get_affine_coordinates_GFp(key->group, point, - tx, ty, ctx)) - goto err; - } - /* Check if retrieved coordinates match originals: if not values - * are out of range. - */ - if (BN_cmp(x, tx) || BN_cmp(y, ty)) - { - ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, - EC_R_COORDINATES_OUT_OF_RANGE); - goto err; - } - - if (!EC_KEY_set_public_key(key, point)) - goto err; - - if (EC_KEY_check_key(key) == 0) - goto err; - - ok = 1; - - err: - if (ctx) - BN_CTX_free(ctx); - if (point) - EC_POINT_free(point); - return ok; - - } + { + if (!EC_POINT_set_affine_coordinates_GFp(key->group, point, + x, y, ctx)) + goto err; + if (!EC_POINT_get_affine_coordinates_GFp(key->group, point, + tx, ty, ctx)) + goto err; + } + /* + * Check if retrieved coordinates match originals: if not values are out + * of range. + */ + if (BN_cmp(x, tx) || BN_cmp(y, ty)) { + ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, + EC_R_COORDINATES_OUT_OF_RANGE); + goto err; + } + + if (!EC_KEY_set_public_key(key, point)) + goto err; + + if (EC_KEY_check_key(key) == 0) + goto err; + + ok = 1; + + err: + if (ctx) + BN_CTX_free(ctx); + if (point) + EC_POINT_free(point); + return ok; + +} const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key) - { - return key->group; - } +{ + return key->group; +} int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) - { - if (key->group != NULL) - EC_GROUP_free(key->group); - key->group = EC_GROUP_dup(group); - return (key->group == NULL) ? 0 : 1; - } +{ + if (key->group != NULL) + EC_GROUP_free(key->group); + key->group = EC_GROUP_dup(group); + return (key->group == NULL) ? 0 : 1; +} const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key) - { - return key->priv_key; - } +{ + return key->priv_key; +} int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key) - { - if (key->priv_key) - BN_clear_free(key->priv_key); - key->priv_key = BN_dup(priv_key); - return (key->priv_key == NULL) ? 0 : 1; - } +{ + if (key->priv_key) + BN_clear_free(key->priv_key); + key->priv_key = BN_dup(priv_key); + return (key->priv_key == NULL) ? 0 : 1; +} const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key) - { - return key->pub_key; - } +{ + return key->pub_key; +} int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key) - { - if (key->pub_key != NULL) - EC_POINT_free(key->pub_key); - key->pub_key = EC_POINT_dup(pub_key, key->group); - return (key->pub_key == NULL) ? 0 : 1; - } +{ + if (key->pub_key != NULL) + EC_POINT_free(key->pub_key); + key->pub_key = EC_POINT_dup(pub_key, key->group); + return (key->pub_key == NULL) ? 0 : 1; +} unsigned int EC_KEY_get_enc_flags(const EC_KEY *key) - { - return key->enc_flag; - } +{ + return key->enc_flag; +} void EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags) - { - key->enc_flag = flags; - } +{ + key->enc_flag = flags; +} point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key) - { - return key->conv_form; - } +{ + return key->conv_form; +} void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform) - { - key->conv_form = cform; - if (key->group != NULL) - EC_GROUP_set_point_conversion_form(key->group, cform); - } +{ + key->conv_form = cform; + if (key->group != NULL) + EC_GROUP_set_point_conversion_form(key->group, cform); +} void *EC_KEY_get_key_method_data(EC_KEY *key, - void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)) - { - void *ret; + void *(*dup_func) (void *), + void (*free_func) (void *), + void (*clear_free_func) (void *)) +{ + void *ret; - CRYPTO_r_lock(CRYPTO_LOCK_EC); - ret = EC_EX_DATA_get_data(key->method_data, dup_func, free_func, clear_free_func); - CRYPTO_r_unlock(CRYPTO_LOCK_EC); + CRYPTO_r_lock(CRYPTO_LOCK_EC); + ret = + EC_EX_DATA_get_data(key->method_data, dup_func, free_func, + clear_free_func); + CRYPTO_r_unlock(CRYPTO_LOCK_EC); - return ret; - } + return ret; +} void *EC_KEY_insert_key_method_data(EC_KEY *key, void *data, - void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)) - { - EC_EXTRA_DATA *ex_data; - - CRYPTO_w_lock(CRYPTO_LOCK_EC); - ex_data = EC_EX_DATA_get_data(key->method_data, dup_func, free_func, clear_free_func); - if (ex_data == NULL) - EC_EX_DATA_set_data(&key->method_data, data, dup_func, free_func, clear_free_func); - CRYPTO_w_unlock(CRYPTO_LOCK_EC); - - return ex_data; - } + void *(*dup_func) (void *), + void (*free_func) (void *), + void (*clear_free_func) (void *)) +{ + EC_EXTRA_DATA *ex_data; + + CRYPTO_w_lock(CRYPTO_LOCK_EC); + ex_data = + EC_EX_DATA_get_data(key->method_data, dup_func, free_func, + clear_free_func); + if (ex_data == NULL) + EC_EX_DATA_set_data(&key->method_data, data, dup_func, free_func, + clear_free_func); + CRYPTO_w_unlock(CRYPTO_LOCK_EC); + + return ex_data; +} void EC_KEY_set_asn1_flag(EC_KEY *key, int flag) - { - if (key->group != NULL) - EC_GROUP_set_asn1_flag(key->group, flag); - } +{ + if (key->group != NULL) + EC_GROUP_set_asn1_flag(key->group, flag); +} int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx) - { - if (key->group == NULL) - return 0; - return EC_GROUP_precompute_mult(key->group, ctx); - } +{ + if (key->group == NULL) + return 0; + return EC_GROUP_precompute_mult(key->group, ctx); +} int EC_KEY_get_flags(const EC_KEY *key) - { - return key->flags; - } +{ + return key->flags; +} void EC_KEY_set_flags(EC_KEY *key, int flags) - { - key->flags |= flags; - } +{ + key->flags |= flags; +} void EC_KEY_clear_flags(EC_KEY *key, int flags) - { - key->flags &= ~flags; - } +{ + key->flags &= ~flags; +} diff --git a/openssl/crypto/ec/ec_lcl.h b/openssl/crypto/ec/ec_lcl.h index b0d48b6b5..319e651f6 100644 --- a/openssl/crypto/ec/ec_lcl.h +++ b/openssl/crypto/ec/ec_lcl.h @@ -10,7 +10,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -58,18 +58,17 @@ /* ==================================================================== * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. * - * Portions of the attached software ("Contribution") are developed by + * Portions of the attached software ("Contribution") are developed by * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. * * The Contribution is licensed pursuant to the OpenSSL open source * license provided above. * - * The elliptic curve binary polynomial software is originally written by + * The elliptic curve binary polynomial software is originally written by * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories. * */ - #include <stdlib.h> #include <openssl/obj_mac.h> @@ -78,230 +77,250 @@ #if defined(__SUNPRO_C) # if __SUNPRO_C >= 0x520 -# pragma error_messages (off,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE) +# pragma error_messages (off,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE) # endif #endif /* Use default functions for poin2oct, oct2point and compressed coordinates */ -#define EC_FLAGS_DEFAULT_OCT 0x1 +#define EC_FLAGS_DEFAULT_OCT 0x1 -/* Structure details are not part of the exported interface, - * so all this may change in future versions. */ +/* + * Structure details are not part of the exported interface, so all this may + * change in future versions. + */ struct ec_method_st { - /* Various method flags */ - int flags; - /* used by EC_METHOD_get_field_type: */ - int field_type; /* a NID */ - - /* used by EC_GROUP_new, EC_GROUP_free, EC_GROUP_clear_free, EC_GROUP_copy: */ - int (*group_init)(EC_GROUP *); - void (*group_finish)(EC_GROUP *); - void (*group_clear_finish)(EC_GROUP *); - int (*group_copy)(EC_GROUP *, const EC_GROUP *); - - /* used by EC_GROUP_set_curve_GFp, EC_GROUP_get_curve_GFp, */ - /* EC_GROUP_set_curve_GF2m, and EC_GROUP_get_curve_GF2m: */ - int (*group_set_curve)(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *); - int (*group_get_curve)(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *); - - /* used by EC_GROUP_get_degree: */ - int (*group_get_degree)(const EC_GROUP *); - - /* used by EC_GROUP_check: */ - int (*group_check_discriminant)(const EC_GROUP *, BN_CTX *); - - /* used by EC_POINT_new, EC_POINT_free, EC_POINT_clear_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 *); - - /* used by EC_POINT_set_to_infinity, - * EC_POINT_set_Jprojective_coordinates_GFp, - * EC_POINT_get_Jprojective_coordinates_GFp, - * EC_POINT_set_affine_coordinates_GFp, ..._GF2m, - * EC_POINT_get_affine_coordinates_GFp, ..._GF2m, - * EC_POINT_set_compressed_coordinates_GFp, ..._GF2m: - */ - int (*point_set_to_infinity)(const EC_GROUP *, EC_POINT *); - int (*point_set_Jprojective_coordinates_GFp)(const EC_GROUP *, EC_POINT *, - const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *); - int (*point_get_Jprojective_coordinates_GFp)(const EC_GROUP *, const EC_POINT *, - BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *); - int (*point_set_affine_coordinates)(const EC_GROUP *, EC_POINT *, - const BIGNUM *x, const BIGNUM *y, BN_CTX *); - int (*point_get_affine_coordinates)(const EC_GROUP *, const EC_POINT *, - BIGNUM *x, BIGNUM *y, BN_CTX *); - int (*point_set_compressed_coordinates)(const EC_GROUP *, EC_POINT *, - const BIGNUM *x, int y_bit, BN_CTX *); - - /* used by EC_POINT_point2oct, EC_POINT_oct2point: */ - size_t (*point2oct)(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form, - unsigned char *buf, size_t len, BN_CTX *); - int (*oct2point)(const EC_GROUP *, EC_POINT *, - const unsigned char *buf, size_t len, BN_CTX *); - - /* used by EC_POINT_add, EC_POINT_dbl, ECP_POINT_invert: */ - int (*add)(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *); - int (*dbl)(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *); - int (*invert)(const EC_GROUP *, EC_POINT *, BN_CTX *); - - /* used by EC_POINT_is_at_infinity, EC_POINT_is_on_curve, EC_POINT_cmp: */ - int (*is_at_infinity)(const EC_GROUP *, const EC_POINT *); - int (*is_on_curve)(const EC_GROUP *, const EC_POINT *, BN_CTX *); - int (*point_cmp)(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, BN_CTX *); - - /* used by EC_POINT_make_affine, EC_POINTs_make_affine: */ - int (*make_affine)(const EC_GROUP *, EC_POINT *, BN_CTX *); - int (*points_make_affine)(const EC_GROUP *, size_t num, EC_POINT *[], BN_CTX *); - - /* used by EC_POINTs_mul, EC_POINT_mul, EC_POINT_precompute_mult, EC_POINT_have_precompute_mult - * (default implementations are used if the 'mul' pointer is 0): */ - int (*mul)(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, - size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *); - int (*precompute_mult)(EC_GROUP *group, BN_CTX *); - int (*have_precompute_mult)(const EC_GROUP *group); - - - /* internal functions */ - - /* 'field_mul', 'field_sqr', and 'field_div' can be used by 'add' and 'dbl' so that - * the same implementations of point operations can be used with different - * optimized implementations of expensive field operations: */ - int (*field_mul)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *); - int (*field_sqr)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); - int (*field_div)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *); - - int (*field_encode)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); /* e.g. to Montgomery */ - int (*field_decode)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); /* e.g. from Montgomery */ - int (*field_set_to_one)(const EC_GROUP *, BIGNUM *r, BN_CTX *); -} /* EC_METHOD */; + /* Various method flags */ + int flags; + /* used by EC_METHOD_get_field_type: */ + int field_type; /* a NID */ + /* + * used by EC_GROUP_new, EC_GROUP_free, EC_GROUP_clear_free, + * EC_GROUP_copy: + */ + int (*group_init) (EC_GROUP *); + void (*group_finish) (EC_GROUP *); + void (*group_clear_finish) (EC_GROUP *); + int (*group_copy) (EC_GROUP *, const EC_GROUP *); + /* used by EC_GROUP_set_curve_GFp, EC_GROUP_get_curve_GFp, */ + /* EC_GROUP_set_curve_GF2m, and EC_GROUP_get_curve_GF2m: */ + int (*group_set_curve) (EC_GROUP *, const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); + int (*group_get_curve) (const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, + BN_CTX *); + /* used by EC_GROUP_get_degree: */ + int (*group_get_degree) (const EC_GROUP *); + /* used by EC_GROUP_check: */ + int (*group_check_discriminant) (const EC_GROUP *, BN_CTX *); + /* + * used by EC_POINT_new, EC_POINT_free, EC_POINT_clear_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 *); + /*- + * used by EC_POINT_set_to_infinity, + * EC_POINT_set_Jprojective_coordinates_GFp, + * EC_POINT_get_Jprojective_coordinates_GFp, + * EC_POINT_set_affine_coordinates_GFp, ..._GF2m, + * EC_POINT_get_affine_coordinates_GFp, ..._GF2m, + * EC_POINT_set_compressed_coordinates_GFp, ..._GF2m: + */ + int (*point_set_to_infinity) (const EC_GROUP *, EC_POINT *); + int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *, + EC_POINT *, const BIGNUM *x, + const BIGNUM *y, + const BIGNUM *z, BN_CTX *); + int (*point_get_Jprojective_coordinates_GFp) (const EC_GROUP *, + const EC_POINT *, BIGNUM *x, + BIGNUM *y, BIGNUM *z, + BN_CTX *); + int (*point_set_affine_coordinates) (const EC_GROUP *, EC_POINT *, + const BIGNUM *x, const BIGNUM *y, + BN_CTX *); + int (*point_get_affine_coordinates) (const EC_GROUP *, const EC_POINT *, + BIGNUM *x, BIGNUM *y, BN_CTX *); + int (*point_set_compressed_coordinates) (const EC_GROUP *, EC_POINT *, + const BIGNUM *x, int y_bit, + BN_CTX *); + /* used by EC_POINT_point2oct, EC_POINT_oct2point: */ + size_t (*point2oct) (const EC_GROUP *, const EC_POINT *, + point_conversion_form_t form, unsigned char *buf, + size_t len, BN_CTX *); + int (*oct2point) (const EC_GROUP *, EC_POINT *, const unsigned char *buf, + size_t len, BN_CTX *); + /* used by EC_POINT_add, EC_POINT_dbl, ECP_POINT_invert: */ + int (*add) (const EC_GROUP *, EC_POINT *r, const EC_POINT *a, + const EC_POINT *b, BN_CTX *); + int (*dbl) (const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *); + int (*invert) (const EC_GROUP *, EC_POINT *, BN_CTX *); + /* + * used by EC_POINT_is_at_infinity, EC_POINT_is_on_curve, EC_POINT_cmp: + */ + int (*is_at_infinity) (const EC_GROUP *, const EC_POINT *); + int (*is_on_curve) (const EC_GROUP *, const EC_POINT *, BN_CTX *); + int (*point_cmp) (const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, + BN_CTX *); + /* used by EC_POINT_make_affine, EC_POINTs_make_affine: */ + int (*make_affine) (const EC_GROUP *, EC_POINT *, BN_CTX *); + int (*points_make_affine) (const EC_GROUP *, size_t num, EC_POINT *[], + BN_CTX *); + /* + * used by EC_POINTs_mul, EC_POINT_mul, EC_POINT_precompute_mult, + * EC_POINT_have_precompute_mult (default implementations are used if the + * 'mul' pointer is 0): + */ + int (*mul) (const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, + size_t num, const EC_POINT *points[], const BIGNUM *scalars[], + BN_CTX *); + int (*precompute_mult) (EC_GROUP *group, BN_CTX *); + int (*have_precompute_mult) (const EC_GROUP *group); + /* internal functions */ + /* + * 'field_mul', 'field_sqr', and 'field_div' can be used by 'add' and + * 'dbl' so that the same implementations of point operations can be used + * with different optimized implementations of expensive field + * operations: + */ + int (*field_mul) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); + int (*field_sqr) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); + int (*field_div) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); + /* e.g. to Montgomery */ + int (*field_encode) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); + /* e.g. from Montgomery */ + int (*field_decode) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); + int (*field_set_to_one) (const EC_GROUP *, BIGNUM *r, BN_CTX *); +} /* EC_METHOD */ ; typedef struct ec_extra_data_st { - struct ec_extra_data_st *next; - void *data; - void *(*dup_func)(void *); - void (*free_func)(void *); - void (*clear_free_func)(void *); -} EC_EXTRA_DATA; /* used in EC_GROUP */ + struct ec_extra_data_st *next; + void *data; + void *(*dup_func) (void *); + void (*free_func) (void *); + void (*clear_free_func) (void *); +} EC_EXTRA_DATA; /* used in EC_GROUP */ struct ec_group_st { - const EC_METHOD *meth; - - EC_POINT *generator; /* optional */ - BIGNUM order, cofactor; - - int curve_name;/* optional NID for named curve */ - int asn1_flag; /* flag to control the asn1 encoding */ - point_conversion_form_t asn1_form; - - unsigned char *seed; /* optional seed for parameters (appears in ASN1) */ - size_t seed_len; - - EC_EXTRA_DATA *extra_data; /* linked list */ - - /* The following members are handled by the method functions, - * even if they appear generic */ - - BIGNUM field; /* Field specification. - * For curves over GF(p), this is the modulus; - * for curves over GF(2^m), this is the - * irreducible polynomial defining the field. - */ - - int poly[6]; /* Field specification for curves over GF(2^m). - * The irreducible f(t) is then of the form: - * t^poly[0] + t^poly[1] + ... + t^poly[k] - * where m = poly[0] > poly[1] > ... > poly[k] = 0. - * The array is terminated with poly[k+1]=-1. - * All elliptic curve irreducibles have at most 5 - * non-zero terms. - */ - - BIGNUM a, b; /* Curve coefficients. - * (Here the assumption is that BIGNUMs can be used - * or abused for all kinds of fields, not just GF(p).) - * For characteristic > 3, the curve is defined - * by a Weierstrass equation of the form - * y^2 = x^3 + a*x + b. - * For characteristic 2, the curve is defined by - * an equation of the form - * y^2 + x*y = x^3 + a*x^2 + b. - */ - - int a_is_minus3; /* enable optimized point arithmetics for special case */ - - void *field_data1; /* method-specific (e.g., Montgomery structure) */ - void *field_data2; /* method-specific */ - int (*field_mod_func)(BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); /* method-specific */ -} /* EC_GROUP */; + const EC_METHOD *meth; + EC_POINT *generator; /* optional */ + BIGNUM order, cofactor; + int curve_name; /* optional NID for named curve */ + int asn1_flag; /* flag to control the asn1 encoding */ + point_conversion_form_t asn1_form; + unsigned char *seed; /* optional seed for parameters (appears in + * ASN1) */ + size_t seed_len; + EC_EXTRA_DATA *extra_data; /* linked list */ + /* + * The following members are handled by the method functions, even if + * they appear generic + */ + /* + * Field specification. For curves over GF(p), this is the modulus; for + * curves over GF(2^m), this is the irreducible polynomial defining the + * field. + */ + BIGNUM field; + /* + * Field specification for curves over GF(2^m). The irreducible f(t) is + * then of the form: t^poly[0] + t^poly[1] + ... + t^poly[k] where m = + * poly[0] > poly[1] > ... > poly[k] = 0. The array is terminated with + * poly[k+1]=-1. All elliptic curve irreducibles have at most 5 non-zero + * terms. + */ + int poly[6]; + /* + * Curve coefficients. (Here the assumption is that BIGNUMs can be used + * or abused for all kinds of fields, not just GF(p).) For characteristic + * > 3, the curve is defined by a Weierstrass equation of the form y^2 = + * x^3 + a*x + b. For characteristic 2, the curve is defined by an + * equation of the form y^2 + x*y = x^3 + a*x^2 + b. + */ + BIGNUM a, b; + /* enable optimized point arithmetics for special case */ + int a_is_minus3; + /* method-specific (e.g., Montgomery structure) */ + void *field_data1; + /* method-specific */ + void *field_data2; + /* method-specific */ + int (*field_mod_func) (BIGNUM *, const BIGNUM *, const BIGNUM *, + BN_CTX *); +} /* EC_GROUP */ ; struct ec_key_st { - int version; - - EC_GROUP *group; - - EC_POINT *pub_key; - BIGNUM *priv_key; + int version; + EC_GROUP *group; + EC_POINT *pub_key; + BIGNUM *priv_key; + unsigned int enc_flag; + point_conversion_form_t conv_form; + int references; + int flags; + EC_EXTRA_DATA *method_data; +} /* EC_KEY */ ; - unsigned int enc_flag; - point_conversion_form_t conv_form; - - int references; - int flags; - - EC_EXTRA_DATA *method_data; -} /* EC_KEY */; - -/* Basically a 'mixin' for extra data, but available for EC_GROUPs/EC_KEYs only - * (with visibility limited to 'package' level for now). - * We use the function pointers as index for retrieval; this obviates - * global ex_data-style index tables. +/* + * Basically a 'mixin' for extra data, but available for EC_GROUPs/EC_KEYs + * only (with visibility limited to 'package' level for now). We use the + * function pointers as index for retrieval; this obviates global + * ex_data-style index tables. */ int EC_EX_DATA_set_data(EC_EXTRA_DATA **, void *data, - void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)); -void *EC_EX_DATA_get_data(const EC_EXTRA_DATA *, - void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)); -void EC_EX_DATA_free_data(EC_EXTRA_DATA **, - void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)); -void EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **, - void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)); + void *(*dup_func) (void *), + void (*free_func) (void *), + void (*clear_free_func) (void *)); +void *EC_EX_DATA_get_data(const EC_EXTRA_DATA *, void *(*dup_func) (void *), + void (*free_func) (void *), + void (*clear_free_func) (void *)); +void EC_EX_DATA_free_data(EC_EXTRA_DATA **, void *(*dup_func) (void *), + void (*free_func) (void *), + void (*clear_free_func) (void *)); +void EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **, void *(*dup_func) (void *), + void (*free_func) (void *), + void (*clear_free_func) (void *)); void EC_EX_DATA_free_all_data(EC_EXTRA_DATA **); void EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **); - - struct ec_point_st { - const 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; + BIGNUM Z; /* Jacobian projective coordinates: (X, Y, Z) + * represents (X/Z^2, Y/Z^3) if Z != 0 */ + int Z_is_one; /* enable optimized point arithmetics for + * special case */ +} /* EC_POINT */ ; - /* All members except 'meth' are handled by the method functions, - * even if they appear generic */ - - BIGNUM X; - BIGNUM Y; - BIGNUM Z; /* Jacobian projective coordinates: - * (X, Y, Z) represents (X/Z^2, Y/Z^3) if Z != 0 */ - int Z_is_one; /* enable optimized point arithmetics for special case */ -} /* EC_POINT */; - - - -/* method functions in ec_mult.c - * (ec_lib.c uses these as defaults if group->method->mul is 0) */ +/* + * method functions in ec_mult.c (ec_lib.c uses these as defaults if + * group->method->mul is 0) + */ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, - size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *); + size_t num, const EC_POINT *points[], const BIGNUM *scalars[], + BN_CTX *); int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *); int ec_wNAF_have_precompute_mult(const EC_GROUP *group); - /* method functions in ecp_smpl.c */ int ec_GFp_simple_group_init(EC_GROUP *); void ec_GFp_simple_group_finish(EC_GROUP *); void ec_GFp_simple_group_clear_finish(EC_GROUP *); int ec_GFp_simple_group_copy(EC_GROUP *, const EC_GROUP *); -int ec_GFp_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *); -int ec_GFp_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *); +int ec_GFp_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *b, BN_CTX *); +int ec_GFp_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a, + BIGNUM *b, BN_CTX *); int ec_GFp_simple_group_get_degree(const EC_GROUP *); int ec_GFp_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *); int ec_GFp_simple_point_init(EC_POINT *); @@ -309,59 +328,81 @@ 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 *); int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *); -int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *, EC_POINT *, - const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *); -int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *, const EC_POINT *, - BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *); +int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *, + EC_POINT *, const BIGNUM *x, + const BIGNUM *y, + const BIGNUM *z, BN_CTX *); +int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *, + const EC_POINT *, BIGNUM *x, + BIGNUM *y, BIGNUM *z, + BN_CTX *); int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *, - const BIGNUM *x, const BIGNUM *y, BN_CTX *); -int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *, const EC_POINT *, - BIGNUM *x, BIGNUM *y, BN_CTX *); + const BIGNUM *x, + const BIGNUM *y, BN_CTX *); +int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *, + const EC_POINT *, BIGNUM *x, + BIGNUM *y, BN_CTX *); int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *, - const BIGNUM *x, int y_bit, BN_CTX *); -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 *); + const BIGNUM *x, int y_bit, + BN_CTX *); +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 *, - const unsigned char *buf, size_t len, BN_CTX *); -int ec_GFp_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *); -int ec_GFp_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *); + const unsigned char *buf, size_t len, BN_CTX *); +int ec_GFp_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, + const EC_POINT *b, BN_CTX *); +int ec_GFp_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, + BN_CTX *); int ec_GFp_simple_invert(const EC_GROUP *, EC_POINT *, BN_CTX *); int ec_GFp_simple_is_at_infinity(const EC_GROUP *, const EC_POINT *); int ec_GFp_simple_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *); -int ec_GFp_simple_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, BN_CTX *); +int ec_GFp_simple_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, + BN_CTX *); int ec_GFp_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *); -int ec_GFp_simple_points_make_affine(const EC_GROUP *, size_t num, EC_POINT *[], BN_CTX *); -int ec_GFp_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *); -int ec_GFp_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); - +int ec_GFp_simple_points_make_affine(const EC_GROUP *, size_t num, + EC_POINT *[], BN_CTX *); +int ec_GFp_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); +int ec_GFp_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); /* method functions in ecp_mont.c */ int ec_GFp_mont_group_init(EC_GROUP *); -int ec_GFp_mont_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *); +int ec_GFp_mont_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); void ec_GFp_mont_group_finish(EC_GROUP *); void ec_GFp_mont_group_clear_finish(EC_GROUP *); int ec_GFp_mont_group_copy(EC_GROUP *, const EC_GROUP *); -int ec_GFp_mont_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *); -int ec_GFp_mont_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); -int ec_GFp_mont_field_encode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); -int ec_GFp_mont_field_decode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); +int ec_GFp_mont_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); +int ec_GFp_mont_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); +int ec_GFp_mont_field_encode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); +int ec_GFp_mont_field_decode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); int ec_GFp_mont_field_set_to_one(const EC_GROUP *, BIGNUM *r, BN_CTX *); - /* method functions in ecp_nist.c */ int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src); -int ec_GFp_nist_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *); -int ec_GFp_nist_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *); -int ec_GFp_nist_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); - +int ec_GFp_nist_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); +int ec_GFp_nist_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); +int ec_GFp_nist_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); /* method functions in ec2_smpl.c */ int ec_GF2m_simple_group_init(EC_GROUP *); void ec_GF2m_simple_group_finish(EC_GROUP *); void ec_GF2m_simple_group_clear_finish(EC_GROUP *); int ec_GF2m_simple_group_copy(EC_GROUP *, const EC_GROUP *); -int ec_GF2m_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *); -int ec_GF2m_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *); +int ec_GF2m_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *b, + BN_CTX *); +int ec_GF2m_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a, + BIGNUM *b, BN_CTX *); int ec_GF2m_simple_group_get_degree(const EC_GROUP *); int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *); int ec_GF2m_simple_point_init(EC_POINT *); @@ -370,77 +411,141 @@ void ec_GF2m_simple_point_clear_finish(EC_POINT *); int ec_GF2m_simple_point_copy(EC_POINT *, const EC_POINT *); int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *); int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *, - const BIGNUM *x, const BIGNUM *y, BN_CTX *); -int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *, const EC_POINT *, - BIGNUM *x, BIGNUM *y, BN_CTX *); + const BIGNUM *x, + const BIGNUM *y, BN_CTX *); +int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *, + const EC_POINT *, BIGNUM *x, + BIGNUM *y, BN_CTX *); int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *, - const BIGNUM *x, int y_bit, BN_CTX *); -size_t ec_GF2m_simple_point2oct(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form, - unsigned char *buf, size_t len, BN_CTX *); + const BIGNUM *x, int y_bit, + BN_CTX *); +size_t ec_GF2m_simple_point2oct(const EC_GROUP *, const EC_POINT *, + point_conversion_form_t form, + unsigned char *buf, size_t len, BN_CTX *); int ec_GF2m_simple_oct2point(const EC_GROUP *, EC_POINT *, - const unsigned char *buf, size_t len, BN_CTX *); -int ec_GF2m_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *); -int ec_GF2m_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *); + const unsigned char *buf, size_t len, BN_CTX *); +int ec_GF2m_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, + const EC_POINT *b, BN_CTX *); +int ec_GF2m_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, + BN_CTX *); int ec_GF2m_simple_invert(const EC_GROUP *, EC_POINT *, BN_CTX *); int ec_GF2m_simple_is_at_infinity(const EC_GROUP *, const EC_POINT *); int ec_GF2m_simple_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *); -int ec_GF2m_simple_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, BN_CTX *); +int ec_GF2m_simple_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, + BN_CTX *); int ec_GF2m_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *); -int ec_GF2m_simple_points_make_affine(const EC_GROUP *, size_t num, EC_POINT *[], BN_CTX *); -int ec_GF2m_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *); -int ec_GF2m_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); -int ec_GF2m_simple_field_div(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *); - +int ec_GF2m_simple_points_make_affine(const EC_GROUP *, size_t num, + EC_POINT *[], BN_CTX *); +int ec_GF2m_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); +int ec_GF2m_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); +int ec_GF2m_simple_field_div(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *); /* method functions in ec2_mult.c */ -int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, - size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *); +int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], const BIGNUM *scalars[], + BN_CTX *); int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx); int ec_GF2m_have_precompute_mult(const EC_GROUP *group); /* method functions in ec2_mult.c */ -int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, - size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *); +int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], const BIGNUM *scalars[], + BN_CTX *); int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx); int ec_GF2m_have_precompute_mult(const EC_GROUP *group); #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 /* method functions in ecp_nistp224.c */ int ec_GFp_nistp224_group_init(EC_GROUP *group); -int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *n, BN_CTX *); -int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx); -int ec_GFp_nistp224_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *); -int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx); +int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *n, + BN_CTX *); +int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx); +int ec_GFp_nistp224_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], const BIGNUM *scalars[], + BN_CTX *); +int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], + const BIGNUM *scalars[], BN_CTX *ctx); int ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx); int ec_GFp_nistp224_have_precompute_mult(const EC_GROUP *group); /* method functions in ecp_nistp256.c */ int ec_GFp_nistp256_group_init(EC_GROUP *group); -int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *n, BN_CTX *); -int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx); -int ec_GFp_nistp256_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *); -int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx); +int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *n, + BN_CTX *); +int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx); +int ec_GFp_nistp256_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], const BIGNUM *scalars[], + BN_CTX *); +int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], + const BIGNUM *scalars[], BN_CTX *ctx); int ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx); int ec_GFp_nistp256_have_precompute_mult(const EC_GROUP *group); /* method functions in ecp_nistp521.c */ int ec_GFp_nistp521_group_init(EC_GROUP *group); -int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *n, BN_CTX *); -int ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx); -int ec_GFp_nistp521_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *); -int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx); +int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *n, + BN_CTX *); +int ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx); +int ec_GFp_nistp521_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], const BIGNUM *scalars[], + BN_CTX *); +int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], + const BIGNUM *scalars[], BN_CTX *ctx); int ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx); int ec_GFp_nistp521_have_precompute_mult(const EC_GROUP *group); /* utility functions in ecp_nistputil.c */ void ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array, - size_t felem_size, void *tmp_felems, - void (*felem_one)(void *out), - int (*felem_is_zero)(const void *in), - void (*felem_assign)(void *out, const void *in), - void (*felem_square)(void *out, const void *in), - void (*felem_mul)(void *out, const void *in1, const void *in2), - void (*felem_inv)(void *out, const void *in), - void (*felem_contract)(void *out, const void *in)); -void ec_GFp_nistp_recode_scalar_bits(unsigned char *sign, unsigned char *digit, unsigned char in); + size_t felem_size, + void *tmp_felems, + void (*felem_one) (void *out), + int (*felem_is_zero) (const void + *in), + void (*felem_assign) (void *out, + const void + *in), + void (*felem_square) (void *out, + const void + *in), + void (*felem_mul) (void *out, + const void + *in1, + const void + *in2), + void (*felem_inv) (void *out, + const void + *in), + void (*felem_contract) (void + *out, + const + void + *in)); +void ec_GFp_nistp_recode_scalar_bits(unsigned char *sign, + unsigned char *digit, unsigned char in); #endif diff --git a/openssl/crypto/ec/ec_lib.c b/openssl/crypto/ec/ec_lib.c index 0992c393b..9a54f41e4 100644 --- a/openssl/crypto/ec/ec_lib.c +++ b/openssl/crypto/ec/ec_lib.c @@ -10,7 +10,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -57,7 +57,7 @@ */ /* ==================================================================== * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. - * Binary polynomial ECC support in OpenSSL originally developed by + * Binary polynomial ECC support in OpenSSL originally developed by * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. */ @@ -70,1027 +70,983 @@ const char EC_version[] = "EC" OPENSSL_VERSION_PTEXT; - /* 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, EC_R_SLOT_FULL); - 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; - - ret->extra_data = NULL; - - ret->generator = NULL; - BN_init(&ret->order); - BN_init(&ret->cofactor); - - ret->curve_name = 0; - ret->asn1_flag = 0; - ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED; - - ret->seed = NULL; - ret->seed_len = 0; - - if (!meth->group_init(ret)) - { - OPENSSL_free(ret); - return NULL; - } - - return ret; - } - +{ + EC_GROUP *ret; -void EC_GROUP_free(EC_GROUP *group) - { - if (!group) return; + if (meth == NULL) { + ECerr(EC_F_EC_GROUP_NEW, EC_R_SLOT_FULL); + return NULL; + } + if (meth->group_init == 0) { + ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return NULL; + } - if (group->meth->group_finish != 0) - group->meth->group_finish(group); + ret = OPENSSL_malloc(sizeof *ret); + if (ret == NULL) { + ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE); + return NULL; + } - EC_EX_DATA_free_all_data(&group->extra_data); + ret->meth = meth; - if (group->generator != NULL) - EC_POINT_free(group->generator); - BN_free(&group->order); - BN_free(&group->cofactor); + ret->extra_data = NULL; - if (group->seed) - OPENSSL_free(group->seed); + ret->generator = NULL; + BN_init(&ret->order); + BN_init(&ret->cofactor); - OPENSSL_free(group); - } - - -void EC_GROUP_clear_free(EC_GROUP *group) - { - if (!group) return; + ret->curve_name = 0; + ret->asn1_flag = 0; + ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED; - if (group->meth->group_clear_finish != 0) - group->meth->group_clear_finish(group); - else if (group->meth->group_finish != 0) - group->meth->group_finish(group); + ret->seed = NULL; + ret->seed_len = 0; - EC_EX_DATA_clear_free_all_data(&group->extra_data); + if (!meth->group_init(ret)) { + OPENSSL_free(ret); + return NULL; + } - if (group->generator != NULL) - EC_POINT_clear_free(group->generator); - BN_clear_free(&group->order); - BN_clear_free(&group->cofactor); + return ret; +} - if (group->seed) - { - OPENSSL_cleanse(group->seed, group->seed_len); - OPENSSL_free(group->seed); - } - - OPENSSL_cleanse(group, sizeof *group); - OPENSSL_free(group); - } +void EC_GROUP_free(EC_GROUP *group) +{ + if (!group) + return; + if (group->meth->group_finish != 0) + group->meth->group_finish(group); -int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) - { - EC_EXTRA_DATA *d; - - 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; - } - if (dest == src) - return 1; - - EC_EX_DATA_free_all_data(&dest->extra_data); - - for (d = src->extra_data; d != NULL; d = d->next) - { - void *t = d->dup_func(d->data); - - if (t == NULL) - return 0; - if (!EC_EX_DATA_set_data(&dest->extra_data, t, d->dup_func, d->free_func, d->clear_free_func)) - return 0; - } - - if (src->generator != NULL) - { - if (dest->generator == NULL) - { - dest->generator = EC_POINT_new(dest); - if (dest->generator == NULL) return 0; - } - if (!EC_POINT_copy(dest->generator, src->generator)) return 0; - } - else - { - /* src->generator == NULL */ - if (dest->generator != NULL) - { - EC_POINT_clear_free(dest->generator); - dest->generator = NULL; - } - } - - if (!BN_copy(&dest->order, &src->order)) return 0; - if (!BN_copy(&dest->cofactor, &src->cofactor)) return 0; - - dest->curve_name = src->curve_name; - dest->asn1_flag = src->asn1_flag; - dest->asn1_form = src->asn1_form; - - if (src->seed) - { - if (dest->seed) - OPENSSL_free(dest->seed); - dest->seed = OPENSSL_malloc(src->seed_len); - if (dest->seed == NULL) - return 0; - if (!memcpy(dest->seed, src->seed, src->seed_len)) - return 0; - dest->seed_len = src->seed_len; - } - else - { - if (dest->seed) - OPENSSL_free(dest->seed); - dest->seed = NULL; - dest->seed_len = 0; - } - - - return dest->meth->group_copy(dest, src); - } + EC_EX_DATA_free_all_data(&group->extra_data); + if (group->generator != NULL) + EC_POINT_free(group->generator); + BN_free(&group->order); + BN_free(&group->cofactor); -EC_GROUP *EC_GROUP_dup(const EC_GROUP *a) - { - EC_GROUP *t = NULL; - int ok = 0; + if (group->seed) + OPENSSL_free(group->seed); - if (a == NULL) return NULL; + OPENSSL_free(group); +} - if ((t = EC_GROUP_new(a->meth)) == NULL) return(NULL); - if (!EC_GROUP_copy(t, a)) goto err; +void EC_GROUP_clear_free(EC_GROUP *group) +{ + if (!group) + return; - ok = 1; + if (group->meth->group_clear_finish != 0) + group->meth->group_clear_finish(group); + else if (group->meth->group_finish != 0) + group->meth->group_finish(group); - err: - if (!ok) - { - if (t) EC_GROUP_free(t); - return NULL; - } - else return t; - } + EC_EX_DATA_clear_free_all_data(&group->extra_data); + if (group->generator != NULL) + EC_POINT_clear_free(group->generator); + BN_clear_free(&group->order); + BN_clear_free(&group->cofactor); -const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) - { - return group->meth; - } + if (group->seed) { + OPENSSL_cleanse(group->seed, group->seed_len); + OPENSSL_free(group->seed); + } + OPENSSL_cleanse(group, sizeof *group); + OPENSSL_free(group); +} -int EC_METHOD_get_field_type(const EC_METHOD *meth) - { - return meth->field_type; +int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) +{ + EC_EXTRA_DATA *d; + + 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; + } + if (dest == src) + return 1; + + EC_EX_DATA_free_all_data(&dest->extra_data); + + for (d = src->extra_data; d != NULL; d = d->next) { + void *t = d->dup_func(d->data); + + if (t == NULL) + return 0; + if (!EC_EX_DATA_set_data + (&dest->extra_data, t, d->dup_func, d->free_func, + d->clear_free_func)) + return 0; + } + + if (src->generator != NULL) { + if (dest->generator == NULL) { + dest->generator = EC_POINT_new(dest); + if (dest->generator == NULL) + return 0; + } + if (!EC_POINT_copy(dest->generator, src->generator)) + return 0; + } else { + /* src->generator == NULL */ + if (dest->generator != NULL) { + EC_POINT_clear_free(dest->generator); + dest->generator = NULL; } + } + + if (!BN_copy(&dest->order, &src->order)) + return 0; + if (!BN_copy(&dest->cofactor, &src->cofactor)) + return 0; + + dest->curve_name = src->curve_name; + dest->asn1_flag = src->asn1_flag; + dest->asn1_form = src->asn1_form; + + if (src->seed) { + if (dest->seed) + OPENSSL_free(dest->seed); + dest->seed = OPENSSL_malloc(src->seed_len); + if (dest->seed == NULL) + return 0; + if (!memcpy(dest->seed, src->seed, src->seed_len)) + return 0; + dest->seed_len = src->seed_len; + } else { + if (dest->seed) + OPENSSL_free(dest->seed); + dest->seed = NULL; + dest->seed_len = 0; + } + + return dest->meth->group_copy(dest, src); +} +EC_GROUP *EC_GROUP_dup(const EC_GROUP *a) +{ + EC_GROUP *t = NULL; + int ok = 0; -int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor) - { - if (generator == NULL) - { - ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER); - return 0 ; - } + if (a == NULL) + return NULL; - if (group->generator == NULL) - { - group->generator = EC_POINT_new(group); - if (group->generator == NULL) return 0; - } - if (!EC_POINT_copy(group->generator, generator)) return 0; + if ((t = EC_GROUP_new(a->meth)) == NULL) + return (NULL); + if (!EC_GROUP_copy(t, a)) + goto err; - if (order != NULL) - { if (!BN_copy(&group->order, order)) return 0; } - else - BN_zero(&group->order); + ok = 1; - if (cofactor != NULL) - { if (!BN_copy(&group->cofactor, cofactor)) return 0; } - else - BN_zero(&group->cofactor); + err: + if (!ok) { + if (t) + EC_GROUP_free(t); + return NULL; + } else + return t; +} - return 1; - } +const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) +{ + return group->meth; +} +int EC_METHOD_get_field_type(const EC_METHOD *meth) +{ + return meth->field_type; +} + +int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, + const BIGNUM *order, const BIGNUM *cofactor) +{ + if (generator == NULL) { + ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (group->generator == NULL) { + group->generator = EC_POINT_new(group); + if (group->generator == NULL) + return 0; + } + if (!EC_POINT_copy(group->generator, generator)) + return 0; + + if (order != NULL) { + if (!BN_copy(&group->order, order)) + return 0; + } else + BN_zero(&group->order); + + if (cofactor != NULL) { + if (!BN_copy(&group->cofactor, cofactor)) + return 0; + } else + BN_zero(&group->cofactor); + + return 1; +} const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) - { - return group->generator; - } - +{ + return group->generator; +} int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) - { - if (!BN_copy(order, &group->order)) - return 0; +{ + if (!BN_copy(order, &group->order)) + return 0; - return !BN_is_zero(order); - } + return !BN_is_zero(order); +} +int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, + BN_CTX *ctx) +{ + if (!BN_copy(cofactor, &group->cofactor)) + return 0; -int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx) - { - if (!BN_copy(cofactor, &group->cofactor)) - return 0; - - return !BN_is_zero(&group->cofactor); - } - + return !BN_is_zero(&group->cofactor); +} void EC_GROUP_set_curve_name(EC_GROUP *group, int nid) - { - group->curve_name = nid; - } - +{ + group->curve_name = nid; +} int EC_GROUP_get_curve_name(const EC_GROUP *group) - { - return group->curve_name; - } - +{ + return group->curve_name; +} void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) - { - group->asn1_flag = flag; - } - +{ + group->asn1_flag = flag; +} int EC_GROUP_get_asn1_flag(const EC_GROUP *group) - { - return group->asn1_flag; - } +{ + return group->asn1_flag; +} - -void EC_GROUP_set_point_conversion_form(EC_GROUP *group, +void EC_GROUP_set_point_conversion_form(EC_GROUP *group, point_conversion_form_t form) - { - group->asn1_form = form; - } - - -point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *group) - { - return group->asn1_form; - } +{ + group->asn1_form = form; +} +point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP + *group) +{ + return group->asn1_form; +} size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len) - { - if (group->seed) - { - OPENSSL_free(group->seed); - group->seed = NULL; - group->seed_len = 0; - } - - if (!len || !p) - return 1; +{ + if (group->seed) { + OPENSSL_free(group->seed); + group->seed = NULL; + group->seed_len = 0; + } - if ((group->seed = OPENSSL_malloc(len)) == NULL) - return 0; - memcpy(group->seed, p, len); - group->seed_len = len; + if (!len || !p) + return 1; - return len; - } + if ((group->seed = OPENSSL_malloc(len)) == NULL) + return 0; + memcpy(group->seed, p, len); + group->seed_len = len; + return len; +} unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group) - { - return group->seed; - } - +{ + return group->seed; +} size_t EC_GROUP_get_seed_len(const EC_GROUP *group) - { - return group->seed_len; - } - - -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 == 0) - { - ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } - return group->meth->group_set_curve(group, p, a, b, ctx); - } - - -int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx) - { - if (group->meth->group_get_curve == 0) - { - ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } - return group->meth->group_get_curve(group, p, a, b, ctx); - } +{ + return group->seed_len; +} + +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 == 0) { + ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + return group->meth->group_set_curve(group, p, a, b, ctx); +} + +int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, + BIGNUM *b, BN_CTX *ctx) +{ + if (group->meth->group_get_curve == 0) { + ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + return group->meth->group_get_curve(group, p, a, b, ctx); +} #ifndef OPENSSL_NO_EC2M -int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) - { - if (group->meth->group_set_curve == 0) - { - ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } - return group->meth->group_set_curve(group, p, a, b, ctx); - } - - -int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx) - { - if (group->meth->group_get_curve == 0) - { - ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } - return group->meth->group_get_curve(group, p, a, b, ctx); - } +int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx) +{ + if (group->meth->group_set_curve == 0) { + ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + return group->meth->group_set_curve(group, p, a, b, ctx); +} + +int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, + BIGNUM *b, BN_CTX *ctx) +{ + if (group->meth->group_get_curve == 0) { + ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + return group->meth->group_get_curve(group, p, a, b, ctx); +} #endif int EC_GROUP_get_degree(const EC_GROUP *group) - { - if (group->meth->group_get_degree == 0) - { - ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } - return group->meth->group_get_degree(group); - } - +{ + if (group->meth->group_get_degree == 0) { + ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + return group->meth->group_get_degree(group); +} int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) - { - if (group->meth->group_check_discriminant == 0) - { - ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } - return group->meth->group_check_discriminant(group, ctx); - } - +{ + if (group->meth->group_check_discriminant == 0) { + ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + return group->meth->group_check_discriminant(group, ctx); +} int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx) - { - int r = 0; - BIGNUM *a1, *a2, *a3, *b1, *b2, *b3; - BN_CTX *ctx_new = NULL; - - /* compare the field types*/ - if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) != - EC_METHOD_get_field_type(EC_GROUP_method_of(b))) - return 1; - /* compare the curve name (if present in both) */ - if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) && - EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b)) - return 1; - - if (!ctx) - ctx_new = ctx = BN_CTX_new(); - if (!ctx) - return -1; - - BN_CTX_start(ctx); - a1 = BN_CTX_get(ctx); - a2 = BN_CTX_get(ctx); - a3 = BN_CTX_get(ctx); - b1 = BN_CTX_get(ctx); - b2 = BN_CTX_get(ctx); - b3 = BN_CTX_get(ctx); - if (!b3) - { - BN_CTX_end(ctx); - if (ctx_new) - BN_CTX_free(ctx); - return -1; - } - - /* XXX This approach assumes that the external representation - * of curves over the same field type is the same. - */ - if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) || - !b->meth->group_get_curve(b, b1, b2, b3, ctx)) - r = 1; - - if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3)) - r = 1; - - /* XXX EC_POINT_cmp() assumes that the methods are equal */ - if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a), - EC_GROUP_get0_generator(b), ctx)) - r = 1; - - if (!r) - { - /* compare the order and cofactor */ - if (!EC_GROUP_get_order(a, a1, ctx) || - !EC_GROUP_get_order(b, b1, ctx) || - !EC_GROUP_get_cofactor(a, a2, ctx) || - !EC_GROUP_get_cofactor(b, b2, ctx)) - { - BN_CTX_end(ctx); - if (ctx_new) - BN_CTX_free(ctx); - return -1; - } - if (BN_cmp(a1, b1) || BN_cmp(a2, b2)) - r = 1; - } - - BN_CTX_end(ctx); - if (ctx_new) - BN_CTX_free(ctx); - - return r; - } +{ + int r = 0; + BIGNUM *a1, *a2, *a3, *b1, *b2, *b3; + BN_CTX *ctx_new = NULL; + + /* compare the field types */ + if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) != + EC_METHOD_get_field_type(EC_GROUP_method_of(b))) + return 1; + /* compare the curve name (if present in both) */ + if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) && + EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b)) + return 1; + + if (!ctx) + ctx_new = ctx = BN_CTX_new(); + if (!ctx) + return -1; + + BN_CTX_start(ctx); + a1 = BN_CTX_get(ctx); + a2 = BN_CTX_get(ctx); + a3 = BN_CTX_get(ctx); + b1 = BN_CTX_get(ctx); + b2 = BN_CTX_get(ctx); + b3 = BN_CTX_get(ctx); + if (!b3) { + BN_CTX_end(ctx); + if (ctx_new) + BN_CTX_free(ctx); + return -1; + } + + /* + * XXX This approach assumes that the external representation of curves + * over the same field type is the same. + */ + if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) || + !b->meth->group_get_curve(b, b1, b2, b3, ctx)) + r = 1; + + if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3)) + r = 1; + + /* XXX EC_POINT_cmp() assumes that the methods are equal */ + if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a), + EC_GROUP_get0_generator(b), ctx)) + r = 1; + + if (!r) { + /* compare the order and cofactor */ + if (!EC_GROUP_get_order(a, a1, ctx) || + !EC_GROUP_get_order(b, b1, ctx) || + !EC_GROUP_get_cofactor(a, a2, ctx) || + !EC_GROUP_get_cofactor(b, b2, ctx)) { + BN_CTX_end(ctx); + if (ctx_new) + BN_CTX_free(ctx); + return -1; + } + if (BN_cmp(a1, b1) || BN_cmp(a2, b2)) + r = 1; + } + BN_CTX_end(ctx); + if (ctx_new) + BN_CTX_free(ctx); + + return r; +} /* this has 'package' visibility */ int EC_EX_DATA_set_data(EC_EXTRA_DATA **ex_data, void *data, - void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)) - { - EC_EXTRA_DATA *d; - - if (ex_data == NULL) - return 0; - - for (d = *ex_data; d != NULL; d = d->next) - { - if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func) - { - ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL); - return 0; - } - } + void *(*dup_func) (void *), + void (*free_func) (void *), + void (*clear_free_func) (void *)) +{ + EC_EXTRA_DATA *d; + + if (ex_data == NULL) + return 0; + + for (d = *ex_data; d != NULL; d = d->next) { + if (d->dup_func == dup_func && d->free_func == free_func + && d->clear_free_func == clear_free_func) { + ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL); + return 0; + } + } - if (data == NULL) - /* no explicit entry needed */ - return 1; + if (data == NULL) + /* no explicit entry needed */ + return 1; - d = OPENSSL_malloc(sizeof *d); - if (d == NULL) - return 0; + d = OPENSSL_malloc(sizeof *d); + if (d == NULL) + return 0; - d->data = data; - d->dup_func = dup_func; - d->free_func = free_func; - d->clear_free_func = clear_free_func; + d->data = data; + d->dup_func = dup_func; + d->free_func = free_func; + d->clear_free_func = clear_free_func; - d->next = *ex_data; - *ex_data = d; + d->next = *ex_data; + *ex_data = d; - return 1; - } + return 1; +} /* this has 'package' visibility */ void *EC_EX_DATA_get_data(const EC_EXTRA_DATA *ex_data, - void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)) - { - const EC_EXTRA_DATA *d; - - for (d = ex_data; d != NULL; d = d->next) - { - if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func) - return d->data; - } - - return NULL; - } + void *(*dup_func) (void *), + void (*free_func) (void *), + void (*clear_free_func) (void *)) +{ + const EC_EXTRA_DATA *d; + + for (d = ex_data; d != NULL; d = d->next) { + if (d->dup_func == dup_func && d->free_func == free_func + && d->clear_free_func == clear_free_func) + return d->data; + } + + return NULL; +} /* this has 'package' visibility */ void EC_EX_DATA_free_data(EC_EXTRA_DATA **ex_data, - void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)) - { - EC_EXTRA_DATA **p; - - if (ex_data == NULL) - return; - - for (p = ex_data; *p != NULL; p = &((*p)->next)) - { - if ((*p)->dup_func == dup_func && (*p)->free_func == free_func && (*p)->clear_free_func == clear_free_func) - { - EC_EXTRA_DATA *next = (*p)->next; - - (*p)->free_func((*p)->data); - OPENSSL_free(*p); - - *p = next; - return; - } - } - } + void *(*dup_func) (void *), + void (*free_func) (void *), + void (*clear_free_func) (void *)) +{ + EC_EXTRA_DATA **p; + + if (ex_data == NULL) + return; + + for (p = ex_data; *p != NULL; p = &((*p)->next)) { + if ((*p)->dup_func == dup_func && (*p)->free_func == free_func + && (*p)->clear_free_func == clear_free_func) { + EC_EXTRA_DATA *next = (*p)->next; + + (*p)->free_func((*p)->data); + OPENSSL_free(*p); + + *p = next; + return; + } + } +} /* this has 'package' visibility */ void EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **ex_data, - void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)) - { - EC_EXTRA_DATA **p; - - if (ex_data == NULL) - return; - - for (p = ex_data; *p != NULL; p = &((*p)->next)) - { - if ((*p)->dup_func == dup_func && (*p)->free_func == free_func && (*p)->clear_free_func == clear_free_func) - { - EC_EXTRA_DATA *next = (*p)->next; - - (*p)->clear_free_func((*p)->data); - OPENSSL_free(*p); - - *p = next; - return; - } - } - } + void *(*dup_func) (void *), + void (*free_func) (void *), + void (*clear_free_func) (void *)) +{ + EC_EXTRA_DATA **p; + + if (ex_data == NULL) + return; + + for (p = ex_data; *p != NULL; p = &((*p)->next)) { + if ((*p)->dup_func == dup_func && (*p)->free_func == free_func + && (*p)->clear_free_func == clear_free_func) { + EC_EXTRA_DATA *next = (*p)->next; + + (*p)->clear_free_func((*p)->data); + OPENSSL_free(*p); + + *p = next; + return; + } + } +} /* this has 'package' visibility */ void EC_EX_DATA_free_all_data(EC_EXTRA_DATA **ex_data) - { - EC_EXTRA_DATA *d; - - if (ex_data == NULL) - return; - - d = *ex_data; - while (d) - { - EC_EXTRA_DATA *next = d->next; - - d->free_func(d->data); - OPENSSL_free(d); - - d = next; - } - *ex_data = NULL; - } +{ + EC_EXTRA_DATA *d; + + if (ex_data == NULL) + return; + + d = *ex_data; + while (d) { + EC_EXTRA_DATA *next = d->next; + + d->free_func(d->data); + OPENSSL_free(d); + + d = next; + } + *ex_data = NULL; +} /* this has 'package' visibility */ void EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **ex_data) - { - EC_EXTRA_DATA *d; - - if (ex_data == NULL) - return; - - d = *ex_data; - while (d) - { - EC_EXTRA_DATA *next = d->next; - - d->clear_free_func(d->data); - OPENSSL_free(d); - - d = next; - } - *ex_data = NULL; - } +{ + EC_EXTRA_DATA *d; + + if (ex_data == NULL) + return; + d = *ex_data; + while (d) { + EC_EXTRA_DATA *next = d->next; + + d->clear_free_func(d->data); + OPENSSL_free(d); + + d = next; + } + *ex_data = NULL; +} /* 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; - } - +{ + 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) return; +{ + if (!point) + return; - if (point->meth->point_finish != 0) - point->meth->point_finish(point); - OPENSSL_free(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) return; - - if (point->meth->point_clear_finish != 0) - point->meth->point_clear_finish(point); - else if (point->meth->point_finish != 0) - point->meth->point_finish(point); - OPENSSL_cleanse(point, sizeof *point); - OPENSSL_free(point); - } - +{ + if (!point) + return; + + if (point->meth->point_clear_finish != 0) + point->meth->point_clear_finish(point); + else if (point->meth->point_finish != 0) + point->meth->point_finish(point); + OPENSSL_cleanse(point, sizeof *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; - } - if (dest == src) - return 1; - return dest->meth->point_copy(dest, 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; + } + if (dest == src) + return 1; + return dest->meth->point_copy(dest, src); +} EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) - { - EC_POINT *t; - int r; - - if (a == NULL) return NULL; - - t = EC_POINT_new(group); - if (t == NULL) return(NULL); - r = EC_POINT_copy(t, a); - if (!r) - { - EC_POINT_free(t); - return NULL; - } - else return t; - } - +{ + EC_POINT *t; + int r; + + if (a == NULL) + return NULL; + + t = EC_POINT_new(group); + if (t == NULL) + return (NULL); + r = EC_POINT_copy(t, a); + if (!r) { + EC_POINT_free(t); + return NULL; + } else + return t; +} const EC_METHOD *EC_POINT_method_of(const EC_POINT *point) - { - return point->meth; - } - +{ + return point->meth; +} 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_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, - const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx) - { - if (group->meth->point_set_Jprojective_coordinates_GFp == 0) - { - ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } - if (group->meth != point->meth) - { - ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS); - return 0; - } - return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, y, z, ctx); - } - - -int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point, - BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx) - { - if (group->meth->point_get_Jprojective_coordinates_GFp == 0) - { - ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } - if (group->meth != point->meth) - { - ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS); - return 0; - } - return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x, y, z, ctx); - } - - -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 == 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(group, point, x, y, ctx); - } +{ + 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_Jprojective_coordinates_GFp(const EC_GROUP *group, + EC_POINT *point, const BIGNUM *x, + const BIGNUM *y, const BIGNUM *z, + BN_CTX *ctx) +{ + if (group->meth->point_set_Jprojective_coordinates_GFp == 0) { + ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (group->meth != point->meth) { + ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, + EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, + y, z, ctx); +} + +int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, + const EC_POINT *point, BIGNUM *x, + BIGNUM *y, BIGNUM *z, + BN_CTX *ctx) +{ + if (group->meth->point_get_Jprojective_coordinates_GFp == 0) { + ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (group->meth != point->meth) { + ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, + EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x, + y, z, ctx); +} + +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 == 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(group, point, x, y, ctx); +} #ifndef OPENSSL_NO_EC2M -int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point, - const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) - { - if (group->meth->point_set_affine_coordinates == 0) - { - ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } - if (group->meth != point->meth) - { - ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS); - return 0; - } - return group->meth->point_set_affine_coordinates(group, point, x, y, ctx); - } +int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, + EC_POINT *point, const BIGNUM *x, + const BIGNUM *y, BN_CTX *ctx) +{ + if (group->meth->point_set_affine_coordinates == 0) { + ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (group->meth != point->meth) { + ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, + EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->point_set_affine_coordinates(group, point, x, y, ctx); +} #endif -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 == 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(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 == 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(group, point, x, y, ctx); +} #ifndef OPENSSL_NO_EC2M -int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, const EC_POINT *point, - BIGNUM *x, BIGNUM *y, BN_CTX *ctx) - { - if (group->meth->point_get_affine_coordinates == 0) - { - ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } - if (group->meth != point->meth) - { - ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS); - return 0; - } - return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); - } +int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, + const EC_POINT *point, BIGNUM *x, + BIGNUM *y, BN_CTX *ctx) +{ + if (group->meth->point_get_affine_coordinates == 0) { + ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (group->meth != point->meth) { + ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, + EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); +} #endif -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_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_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) - { - if (group->meth->invert == 0) - { - ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } - if (group->meth != a->meth) - { - ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS); - return 0; - } - return group->meth->invert(group, a, ctx); - } - +{ + if (group->meth->invert == 0) { + ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (group->meth != a->meth) { + ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + return group->meth->invert(group, 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_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) - { - if (group->meth->point_cmp == 0) - { - ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return -1; - } - if ((group->meth != a->meth) || (a->meth != b->meth)) - { - ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS); - return -1; - } - return group->meth->point_cmp(group, a, b, ctx); - } - +{ + 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_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, + BN_CTX *ctx) +{ + if (group->meth->point_cmp == 0) { + ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return -1; + } + if ((group->meth != a->meth) || (a->meth != b->meth)) { + ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS); + return -1; + } + return group->meth->point_cmp(group, a, b, ctx); +} int EC_POINT_make_affine(const EC_GROUP *group, 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); - } - - -int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx) - { - size_t i; - - if (group->meth->points_make_affine == 0) - { - ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } - for (i = 0; i < num; i++) - { - if (group->meth != points[i]->meth) - { - ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS); - return 0; - } - } - return group->meth->points_make_affine(group, num, points, ctx); - } - - -/* Functions for point multiplication. - * - * If group->meth->mul is 0, we use the wNAF-based implementations in ec_mult.c; - * otherwise we dispatch through methods. +{ + 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); +} + +int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, + EC_POINT *points[], BN_CTX *ctx) +{ + size_t i; + + if (group->meth->points_make_affine == 0) { + ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + for (i = 0; i < num; i++) { + if (group->meth != points[i]->meth) { + ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + } + return group->meth->points_make_affine(group, num, points, ctx); +} + +/* + * Functions for point multiplication. If group->meth->mul is 0, we use the + * wNAF-based implementations in ec_mult.c; otherwise we dispatch through + * methods. */ int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, - size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx) - { - if (group->meth->mul == 0) - /* use default */ - return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); + size_t num, const EC_POINT *points[], + const BIGNUM *scalars[], BN_CTX *ctx) +{ + if (group->meth->mul == 0) + /* use default */ + return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); - return group->meth->mul(group, r, scalar, num, points, scalars, ctx); - } + return group->meth->mul(group, r, scalar, num, points, scalars, ctx); +} int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, - const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx) - { - /* just a convenient interface to EC_POINTs_mul() */ + const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx) +{ + /* just a convenient interface to EC_POINTs_mul() */ - const EC_POINT *points[1]; - const BIGNUM *scalars[1]; + const EC_POINT *points[1]; + const BIGNUM *scalars[1]; - points[0] = point; - scalars[0] = p_scalar; + points[0] = point; + scalars[0] = p_scalar; - return EC_POINTs_mul(group, r, g_scalar, (point != NULL && p_scalar != NULL), points, scalars, ctx); - } + return EC_POINTs_mul(group, r, g_scalar, + (point != NULL + && p_scalar != NULL), points, scalars, ctx); +} int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx) - { - if (group->meth->mul == 0) - /* use default */ - return ec_wNAF_precompute_mult(group, ctx); +{ + if (group->meth->mul == 0) + /* use default */ + return ec_wNAF_precompute_mult(group, ctx); - if (group->meth->precompute_mult != 0) - return group->meth->precompute_mult(group, ctx); - else - return 1; /* nothing to do, so report success */ - } + if (group->meth->precompute_mult != 0) + return group->meth->precompute_mult(group, ctx); + else + return 1; /* nothing to do, so report success */ +} int EC_GROUP_have_precompute_mult(const EC_GROUP *group) - { - if (group->meth->mul == 0) - /* use default */ - return ec_wNAF_have_precompute_mult(group); - - if (group->meth->have_precompute_mult != 0) - return group->meth->have_precompute_mult(group); - else - return 0; /* cannot tell whether precomputation has been performed */ - } +{ + if (group->meth->mul == 0) + /* use default */ + return ec_wNAF_have_precompute_mult(group); + + if (group->meth->have_precompute_mult != 0) + return group->meth->have_precompute_mult(group); + else + return 0; /* cannot tell whether precomputation has + * been performed */ +} diff --git a/openssl/crypto/ec/ec_mult.c b/openssl/crypto/ec/ec_mult.c index e81200b25..23b8c3089 100644 --- a/openssl/crypto/ec/ec_mult.c +++ b/openssl/crypto/ec/ec_mult.c @@ -10,7 +10,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -67,7 +67,6 @@ #include "ec_lcl.h" - /* * This file implements the wNAF-based interleaving multi-exponentation method * (<URL:http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#multiexp>); @@ -75,114 +74,107 @@ * (<URL:http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#fastexp>). */ - - - /* structure for precomputed multiples of the generator */ typedef struct ec_pre_comp_st { - const EC_GROUP *group; /* parent EC_GROUP object */ - size_t blocksize; /* block size for wNAF splitting */ - size_t numblocks; /* max. number of blocks for which we have precomputation */ - size_t w; /* window size */ - EC_POINT **points; /* array with pre-calculated multiples of generator: - * 'num' pointers to EC_POINT objects followed by a NULL */ - size_t num; /* numblocks * 2^(w-1) */ - int references; + const EC_GROUP *group; /* parent EC_GROUP object */ + size_t blocksize; /* block size for wNAF splitting */ + size_t numblocks; /* max. number of blocks for which we have + * precomputation */ + size_t w; /* window size */ + EC_POINT **points; /* array with pre-calculated multiples of + * generator: 'num' pointers to EC_POINT + * objects followed by a NULL */ + size_t num; /* numblocks * 2^(w-1) */ + int references; } EC_PRE_COMP; - + /* functions to manage EC_PRE_COMP within the EC_GROUP extra_data framework */ static void *ec_pre_comp_dup(void *); static void ec_pre_comp_free(void *); static void ec_pre_comp_clear_free(void *); static EC_PRE_COMP *ec_pre_comp_new(const EC_GROUP *group) - { - EC_PRE_COMP *ret = NULL; - - if (!group) - return NULL; - - ret = (EC_PRE_COMP *)OPENSSL_malloc(sizeof(EC_PRE_COMP)); - if (!ret) - { - ECerr(EC_F_EC_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); - return ret; - } - ret->group = group; - ret->blocksize = 8; /* default */ - ret->numblocks = 0; - ret->w = 4; /* default */ - ret->points = NULL; - ret->num = 0; - ret->references = 1; - return ret; - } +{ + EC_PRE_COMP *ret = NULL; + + if (!group) + return NULL; + + ret = (EC_PRE_COMP *)OPENSSL_malloc(sizeof(EC_PRE_COMP)); + if (!ret) { + ECerr(EC_F_EC_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + return ret; + } + ret->group = group; + ret->blocksize = 8; /* default */ + ret->numblocks = 0; + ret->w = 4; /* default */ + ret->points = NULL; + ret->num = 0; + ret->references = 1; + return ret; +} static void *ec_pre_comp_dup(void *src_) - { - EC_PRE_COMP *src = src_; +{ + EC_PRE_COMP *src = src_; - /* no need to actually copy, these objects never change! */ + /* no need to actually copy, these objects never change! */ - CRYPTO_add(&src->references, 1, CRYPTO_LOCK_EC_PRE_COMP); + CRYPTO_add(&src->references, 1, CRYPTO_LOCK_EC_PRE_COMP); - return src_; - } + return src_; +} static void ec_pre_comp_free(void *pre_) - { - int i; - EC_PRE_COMP *pre = pre_; +{ + int i; + EC_PRE_COMP *pre = pre_; - if (!pre) - return; + if (!pre) + return; - i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP); - if (i > 0) - return; + i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP); + if (i > 0) + return; - if (pre->points) - { - EC_POINT **p; + if (pre->points) { + EC_POINT **p; - for (p = pre->points; *p != NULL; p++) - EC_POINT_free(*p); - OPENSSL_free(pre->points); - } - OPENSSL_free(pre); - } + for (p = pre->points; *p != NULL; p++) + EC_POINT_free(*p); + OPENSSL_free(pre->points); + } + OPENSSL_free(pre); +} static void ec_pre_comp_clear_free(void *pre_) - { - int i; - EC_PRE_COMP *pre = pre_; - - if (!pre) - return; - - i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP); - if (i > 0) - return; - - if (pre->points) - { - EC_POINT **p; - - for (p = pre->points; *p != NULL; p++) - { - EC_POINT_clear_free(*p); - OPENSSL_cleanse(p, sizeof *p); - } - OPENSSL_free(pre->points); - } - OPENSSL_cleanse(pre, sizeof *pre); - OPENSSL_free(pre); - } - - - - -/* Determine the modified width-(w+1) Non-Adjacent Form (wNAF) of 'scalar'. +{ + int i; + EC_PRE_COMP *pre = pre_; + + if (!pre) + return; + + i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP); + if (i > 0) + return; + + if (pre->points) { + EC_POINT **p; + + for (p = pre->points; *p != NULL; p++) { + EC_POINT_clear_free(*p); + OPENSSL_cleanse(p, sizeof *p); + } + OPENSSL_free(pre->points); + } + OPENSSL_cleanse(pre, sizeof *pre); + OPENSSL_free(pre); +} + +/*- + * Determine the modified width-(w+1) Non-Adjacent Form (wNAF) of 'scalar'. * This is an array r[] of values that are either zero or odd with an * absolute value less than 2^w satisfying * scalar = \sum_j r[j]*2^j @@ -191,563 +183,546 @@ static void ec_pre_comp_clear_free(void *pre_) * w-1 zeros away from that next non-zero digit. */ static signed char *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len) - { - int window_val; - int ok = 0; - signed char *r = NULL; - int sign = 1; - int bit, next_bit, mask; - size_t len = 0, j; - - if (BN_is_zero(scalar)) - { - r = OPENSSL_malloc(1); - if (!r) - { - ECerr(EC_F_COMPUTE_WNAF, ERR_R_MALLOC_FAILURE); - goto err; - } - r[0] = 0; - *ret_len = 1; - return r; - } - - if (w <= 0 || w > 7) /* 'signed char' can represent integers with absolute values less than 2^7 */ - { - ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); - goto err; - } - bit = 1 << w; /* at most 128 */ - next_bit = bit << 1; /* at most 256 */ - mask = next_bit - 1; /* at most 255 */ - - if (BN_is_negative(scalar)) - { - sign = -1; - } - - if (scalar->d == NULL || scalar->top == 0) - { - ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); - goto err; - } - - len = BN_num_bits(scalar); - r = OPENSSL_malloc(len + 1); /* modified wNAF may be one digit longer than binary representation - * (*ret_len will be set to the actual length, i.e. at most - * BN_num_bits(scalar) + 1) */ - if (r == NULL) - { - ECerr(EC_F_COMPUTE_WNAF, ERR_R_MALLOC_FAILURE); - goto err; - } - window_val = scalar->d[0] & mask; - j = 0; - while ((window_val != 0) || (j + w + 1 < len)) /* if j+w+1 >= len, window_val will not increase */ - { - int digit = 0; - - /* 0 <= window_val <= 2^(w+1) */ - - if (window_val & 1) - { - /* 0 < window_val < 2^(w+1) */ - - if (window_val & bit) - { - digit = window_val - next_bit; /* -2^w < digit < 0 */ - -#if 1 /* modified wNAF */ - if (j + w + 1 >= len) - { - /* special case for generating modified wNAFs: - * no new bits will be added into window_val, - * so using a positive digit here will decrease - * the total length of the representation */ - - digit = window_val & (mask >> 1); /* 0 < digit < 2^w */ - } +{ + int window_val; + int ok = 0; + signed char *r = NULL; + int sign = 1; + int bit, next_bit, mask; + size_t len = 0, j; + + if (BN_is_zero(scalar)) { + r = OPENSSL_malloc(1); + if (!r) { + ECerr(EC_F_COMPUTE_WNAF, ERR_R_MALLOC_FAILURE); + goto err; + } + r[0] = 0; + *ret_len = 1; + return r; + } + + if (w <= 0 || w > 7) { /* 'signed char' can represent integers with + * absolute values less than 2^7 */ + ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); + goto err; + } + bit = 1 << w; /* at most 128 */ + next_bit = bit << 1; /* at most 256 */ + mask = next_bit - 1; /* at most 255 */ + + if (BN_is_negative(scalar)) { + sign = -1; + } + + if (scalar->d == NULL || scalar->top == 0) { + ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); + goto err; + } + + len = BN_num_bits(scalar); + r = OPENSSL_malloc(len + 1); /* modified wNAF may be one digit longer + * than binary representation (*ret_len will + * be set to the actual length, i.e. at most + * BN_num_bits(scalar) + 1) */ + if (r == NULL) { + ECerr(EC_F_COMPUTE_WNAF, ERR_R_MALLOC_FAILURE); + goto err; + } + window_val = scalar->d[0] & mask; + j = 0; + while ((window_val != 0) || (j + w + 1 < len)) { /* if j+w+1 >= len, + * window_val will not + * increase */ + int digit = 0; + + /* 0 <= window_val <= 2^(w+1) */ + + if (window_val & 1) { + /* 0 < window_val < 2^(w+1) */ + + if (window_val & bit) { + digit = window_val - next_bit; /* -2^w < digit < 0 */ + +#if 1 /* modified wNAF */ + if (j + w + 1 >= len) { + /* + * special case for generating modified wNAFs: no new + * bits will be added into window_val, so using a + * positive digit here will decrease the total length of + * the representation + */ + + digit = window_val & (mask >> 1); /* 0 < digit < 2^w */ + } #endif - } - else - { - digit = window_val; /* 0 < digit < 2^w */ - } - - if (digit <= -bit || digit >= bit || !(digit & 1)) - { - ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); - goto err; - } - - window_val -= digit; - - /* now window_val is 0 or 2^(w+1) in standard wNAF generation; - * for modified window NAFs, it may also be 2^w - */ - if (window_val != 0 && window_val != next_bit && window_val != bit) - { - ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); - goto err; - } - } - - r[j++] = sign * digit; - - window_val >>= 1; - window_val += bit * BN_is_bit_set(scalar, j + w); - - if (window_val > next_bit) - { - ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); - goto err; - } - } - - if (j > len + 1) - { - ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); - goto err; - } - len = j; - ok = 1; + } else { + digit = window_val; /* 0 < digit < 2^w */ + } + + if (digit <= -bit || digit >= bit || !(digit & 1)) { + ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); + goto err; + } + + window_val -= digit; + + /* + * now window_val is 0 or 2^(w+1) in standard wNAF generation; + * for modified window NAFs, it may also be 2^w + */ + if (window_val != 0 && window_val != next_bit + && window_val != bit) { + ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + r[j++] = sign * digit; + + window_val >>= 1; + window_val += bit * BN_is_bit_set(scalar, j + w); + + if (window_val > next_bit) { + ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + if (j > len + 1) { + ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); + goto err; + } + len = j; + ok = 1; err: - if (!ok) - { - OPENSSL_free(r); - r = NULL; - } - if (ok) - *ret_len = len; - return r; - } - - -/* TODO: table should be optimised for the wNAF-based implementation, - * sometimes smaller windows will give better performance - * (thus the boundaries should be increased) + if (!ok) { + OPENSSL_free(r); + r = NULL; + } + if (ok) + *ret_len = len; + return r; +} + +/* + * TODO: table should be optimised for the wNAF-based implementation, + * sometimes smaller windows will give better performance (thus the + * boundaries should be increased) */ #define EC_window_bits_for_scalar_size(b) \ - ((size_t) \ - ((b) >= 2000 ? 6 : \ - (b) >= 800 ? 5 : \ - (b) >= 300 ? 4 : \ - (b) >= 70 ? 3 : \ - (b) >= 20 ? 2 : \ - 1)) - -/* Compute + ((size_t) \ + ((b) >= 2000 ? 6 : \ + (b) >= 800 ? 5 : \ + (b) >= 300 ? 4 : \ + (b) >= 70 ? 3 : \ + (b) >= 20 ? 2 : \ + 1)) + +/*- + * Compute * \sum scalars[i]*points[i], * also including * scalar*generator * in the addition if scalar != NULL */ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, - size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx) - { - BN_CTX *new_ctx = NULL; - const EC_POINT *generator = NULL; - EC_POINT *tmp = NULL; - size_t totalnum; - size_t blocksize = 0, numblocks = 0; /* for wNAF splitting */ - size_t pre_points_per_block = 0; - size_t i, j; - int k; - int r_is_inverted = 0; - int r_is_at_infinity = 1; - size_t *wsize = NULL; /* individual window sizes */ - signed char **wNAF = NULL; /* individual wNAFs */ - size_t *wNAF_len = NULL; - size_t max_len = 0; - size_t num_val; - EC_POINT **val = NULL; /* precomputation */ - EC_POINT **v; - EC_POINT ***val_sub = NULL; /* pointers to sub-arrays of 'val' or 'pre_comp->points' */ - const EC_PRE_COMP *pre_comp = NULL; - int num_scalar = 0; /* flag: will be set to 1 if 'scalar' must be treated like other scalars, - * i.e. precomputation is not available */ - int ret = 0; - - if (group->meth != r->meth) - { - ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS); - return 0; - } - - if ((scalar == NULL) && (num == 0)) - { - return EC_POINT_set_to_infinity(group, r); - } - - for (i = 0; i < num; i++) - { - if (group->meth != points[i]->meth) - { - ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS); - return 0; - } - } - - if (ctx == NULL) - { - ctx = new_ctx = BN_CTX_new(); - if (ctx == NULL) - goto err; - } - - if (scalar != NULL) - { - generator = EC_GROUP_get0_generator(group); - if (generator == NULL) - { - ECerr(EC_F_EC_WNAF_MUL, EC_R_UNDEFINED_GENERATOR); - goto err; - } - - /* look if we can use precomputed multiples of generator */ - - pre_comp = EC_EX_DATA_get_data(group->extra_data, ec_pre_comp_dup, ec_pre_comp_free, ec_pre_comp_clear_free); - - if (pre_comp && pre_comp->numblocks && (EC_POINT_cmp(group, generator, pre_comp->points[0], ctx) == 0)) - { - blocksize = pre_comp->blocksize; - - /* determine maximum number of blocks that wNAF splitting may yield - * (NB: maximum wNAF length is bit length plus one) */ - numblocks = (BN_num_bits(scalar) / blocksize) + 1; - - /* we cannot use more blocks than we have precomputation for */ - if (numblocks > pre_comp->numblocks) - numblocks = pre_comp->numblocks; - - pre_points_per_block = (size_t)1 << (pre_comp->w - 1); - - /* check that pre_comp looks sane */ - if (pre_comp->num != (pre_comp->numblocks * pre_points_per_block)) - { - ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); - goto err; - } - } - else - { - /* can't use precomputation */ - pre_comp = NULL; - numblocks = 1; - num_scalar = 1; /* treat 'scalar' like 'num'-th element of 'scalars' */ - } - } - - totalnum = num + numblocks; - - wsize = OPENSSL_malloc(totalnum * sizeof wsize[0]); - wNAF_len = OPENSSL_malloc(totalnum * sizeof wNAF_len[0]); - wNAF = OPENSSL_malloc((totalnum + 1) * sizeof wNAF[0]); /* includes space for pivot */ - val_sub = OPENSSL_malloc(totalnum * sizeof val_sub[0]); - - /* Ensure wNAF is initialised in case we end up going to err */ - if (wNAF) wNAF[0] = NULL; /* preliminary pivot */ - - if (!wsize || !wNAF_len || !wNAF || !val_sub) - { - ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE); - goto err; - } - - /* num_val will be the total number of temporarily precomputed points */ - num_val = 0; - - for (i = 0; i < num + num_scalar; i++) - { - size_t bits; - - bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(scalar); - wsize[i] = EC_window_bits_for_scalar_size(bits); - num_val += (size_t)1 << (wsize[i] - 1); - wNAF[i + 1] = NULL; /* make sure we always have a pivot */ - wNAF[i] = compute_wNAF((i < num ? scalars[i] : scalar), wsize[i], &wNAF_len[i]); - if (wNAF[i] == NULL) - goto err; - if (wNAF_len[i] > max_len) - max_len = wNAF_len[i]; - } - - if (numblocks) - { - /* we go here iff scalar != NULL */ - - if (pre_comp == NULL) - { - if (num_scalar != 1) - { - ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); - goto err; - } - /* we have already generated a wNAF for 'scalar' */ - } - else - { - signed char *tmp_wNAF = NULL; - size_t tmp_len = 0; - - if (num_scalar != 0) - { - ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); - goto err; - } - - /* use the window size for which we have precomputation */ - wsize[num] = pre_comp->w; - tmp_wNAF = compute_wNAF(scalar, wsize[num], &tmp_len); - if (!tmp_wNAF) - goto err; - - if (tmp_len <= max_len) - { - /* One of the other wNAFs is at least as long - * as the wNAF belonging to the generator, - * so wNAF splitting will not buy us anything. */ - - numblocks = 1; - totalnum = num + 1; /* don't use wNAF splitting */ - wNAF[num] = tmp_wNAF; - wNAF[num + 1] = NULL; - wNAF_len[num] = tmp_len; - if (tmp_len > max_len) - max_len = tmp_len; - /* pre_comp->points starts with the points that we need here: */ - val_sub[num] = pre_comp->points; - } - else - { - /* don't include tmp_wNAF directly into wNAF array - * - use wNAF splitting and include the blocks */ - - signed char *pp; - EC_POINT **tmp_points; - - if (tmp_len < numblocks * blocksize) - { - /* possibly we can do with fewer blocks than estimated */ - numblocks = (tmp_len + blocksize - 1) / blocksize; - if (numblocks > pre_comp->numblocks) - { - ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); - goto err; - } - totalnum = num + numblocks; - } - - /* split wNAF in 'numblocks' parts */ - pp = tmp_wNAF; - tmp_points = pre_comp->points; - - for (i = num; i < totalnum; i++) - { - if (i < totalnum - 1) - { - wNAF_len[i] = blocksize; - if (tmp_len < blocksize) - { - ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); - goto err; - } - tmp_len -= blocksize; - } - else - /* last block gets whatever is left - * (this could be more or less than 'blocksize'!) */ - wNAF_len[i] = tmp_len; - - wNAF[i + 1] = NULL; - wNAF[i] = OPENSSL_malloc(wNAF_len[i]); - if (wNAF[i] == NULL) - { - ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE); - OPENSSL_free(tmp_wNAF); - goto err; - } - memcpy(wNAF[i], pp, wNAF_len[i]); - if (wNAF_len[i] > max_len) - max_len = wNAF_len[i]; - - if (*tmp_points == NULL) - { - ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); - OPENSSL_free(tmp_wNAF); - goto err; - } - val_sub[i] = tmp_points; - tmp_points += pre_points_per_block; - pp += blocksize; - } - OPENSSL_free(tmp_wNAF); - } - } - } - - /* All points we precompute now go into a single array 'val'. - * 'val_sub[i]' is a pointer to the subarray for the i-th point, - * or to a subarray of 'pre_comp->points' if we already have precomputation. */ - val = OPENSSL_malloc((num_val + 1) * sizeof val[0]); - if (val == NULL) - { - ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE); - goto err; - } - val[num_val] = NULL; /* pivot element */ - - /* allocate points for precomputation */ - v = val; - for (i = 0; i < num + num_scalar; i++) - { - val_sub[i] = v; - for (j = 0; j < ((size_t)1 << (wsize[i] - 1)); j++) - { - *v = EC_POINT_new(group); - if (*v == NULL) goto err; - v++; - } - } - if (!(v == val + num_val)) - { - ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); - goto err; - } - - if (!(tmp = EC_POINT_new(group))) - goto err; - - /* prepare precomputed values: - * val_sub[i][0] := points[i] - * val_sub[i][1] := 3 * points[i] - * val_sub[i][2] := 5 * points[i] - * ... - */ - for (i = 0; i < num + num_scalar; i++) - { - if (i < num) - { - if (!EC_POINT_copy(val_sub[i][0], points[i])) goto err; - } - else - { - if (!EC_POINT_copy(val_sub[i][0], generator)) goto err; - } - - if (wsize[i] > 1) - { - if (!EC_POINT_dbl(group, tmp, val_sub[i][0], ctx)) goto err; - for (j = 1; j < ((size_t)1 << (wsize[i] - 1)); j++) - { - if (!EC_POINT_add(group, val_sub[i][j], val_sub[i][j - 1], tmp, ctx)) goto err; - } - } - } - -#if 1 /* optional; EC_window_bits_for_scalar_size assumes we do this step */ - if (!EC_POINTs_make_affine(group, num_val, val, ctx)) - goto err; + size_t num, const EC_POINT *points[], const BIGNUM *scalars[], + BN_CTX *ctx) +{ + BN_CTX *new_ctx = NULL; + const EC_POINT *generator = NULL; + EC_POINT *tmp = NULL; + size_t totalnum; + size_t blocksize = 0, numblocks = 0; /* for wNAF splitting */ + size_t pre_points_per_block = 0; + size_t i, j; + int k; + int r_is_inverted = 0; + int r_is_at_infinity = 1; + size_t *wsize = NULL; /* individual window sizes */ + signed char **wNAF = NULL; /* individual wNAFs */ + size_t *wNAF_len = NULL; + size_t max_len = 0; + size_t num_val; + EC_POINT **val = NULL; /* precomputation */ + EC_POINT **v; + EC_POINT ***val_sub = NULL; /* pointers to sub-arrays of 'val' or + * 'pre_comp->points' */ + const EC_PRE_COMP *pre_comp = NULL; + int num_scalar = 0; /* flag: will be set to 1 if 'scalar' must be + * treated like other scalars, i.e. + * precomputation is not available */ + int ret = 0; + + if (group->meth != r->meth) { + ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + + if ((scalar == NULL) && (num == 0)) { + return EC_POINT_set_to_infinity(group, r); + } + + for (i = 0; i < num; i++) { + if (group->meth != points[i]->meth) { + ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + } + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + goto err; + } + + if (scalar != NULL) { + generator = EC_GROUP_get0_generator(group); + if (generator == NULL) { + ECerr(EC_F_EC_WNAF_MUL, EC_R_UNDEFINED_GENERATOR); + goto err; + } + + /* look if we can use precomputed multiples of generator */ + + pre_comp = + EC_EX_DATA_get_data(group->extra_data, ec_pre_comp_dup, + ec_pre_comp_free, ec_pre_comp_clear_free); + + if (pre_comp && pre_comp->numblocks + && (EC_POINT_cmp(group, generator, pre_comp->points[0], ctx) == + 0)) { + blocksize = pre_comp->blocksize; + + /* + * determine maximum number of blocks that wNAF splitting may + * yield (NB: maximum wNAF length is bit length plus one) + */ + numblocks = (BN_num_bits(scalar) / blocksize) + 1; + + /* + * we cannot use more blocks than we have precomputation for + */ + if (numblocks > pre_comp->numblocks) + numblocks = pre_comp->numblocks; + + pre_points_per_block = (size_t)1 << (pre_comp->w - 1); + + /* check that pre_comp looks sane */ + if (pre_comp->num != (pre_comp->numblocks * pre_points_per_block)) { + ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); + goto err; + } + } else { + /* can't use precomputation */ + pre_comp = NULL; + numblocks = 1; + num_scalar = 1; /* treat 'scalar' like 'num'-th element of + * 'scalars' */ + } + } + + totalnum = num + numblocks; + + wsize = OPENSSL_malloc(totalnum * sizeof wsize[0]); + wNAF_len = OPENSSL_malloc(totalnum * sizeof wNAF_len[0]); + wNAF = OPENSSL_malloc((totalnum + 1) * sizeof wNAF[0]); /* includes space + * for pivot */ + val_sub = OPENSSL_malloc(totalnum * sizeof val_sub[0]); + + /* Ensure wNAF is initialised in case we end up going to err */ + if (wNAF) + wNAF[0] = NULL; /* preliminary pivot */ + + if (!wsize || !wNAF_len || !wNAF || !val_sub) { + ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* + * num_val will be the total number of temporarily precomputed points + */ + num_val = 0; + + for (i = 0; i < num + num_scalar; i++) { + size_t bits; + + bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(scalar); + wsize[i] = EC_window_bits_for_scalar_size(bits); + num_val += (size_t)1 << (wsize[i] - 1); + wNAF[i + 1] = NULL; /* make sure we always have a pivot */ + wNAF[i] = + compute_wNAF((i < num ? scalars[i] : scalar), wsize[i], + &wNAF_len[i]); + if (wNAF[i] == NULL) + goto err; + if (wNAF_len[i] > max_len) + max_len = wNAF_len[i]; + } + + if (numblocks) { + /* we go here iff scalar != NULL */ + + if (pre_comp == NULL) { + if (num_scalar != 1) { + ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); + goto err; + } + /* we have already generated a wNAF for 'scalar' */ + } else { + signed char *tmp_wNAF = NULL; + size_t tmp_len = 0; + + if (num_scalar != 0) { + ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); + goto err; + } + + /* + * use the window size for which we have precomputation + */ + wsize[num] = pre_comp->w; + tmp_wNAF = compute_wNAF(scalar, wsize[num], &tmp_len); + if (!tmp_wNAF) + goto err; + + if (tmp_len <= max_len) { + /* + * One of the other wNAFs is at least as long as the wNAF + * belonging to the generator, so wNAF splitting will not buy + * us anything. + */ + + numblocks = 1; + totalnum = num + 1; /* don't use wNAF splitting */ + wNAF[num] = tmp_wNAF; + wNAF[num + 1] = NULL; + wNAF_len[num] = tmp_len; + if (tmp_len > max_len) + max_len = tmp_len; + /* + * pre_comp->points starts with the points that we need here: + */ + val_sub[num] = pre_comp->points; + } else { + /* + * don't include tmp_wNAF directly into wNAF array - use wNAF + * splitting and include the blocks + */ + + signed char *pp; + EC_POINT **tmp_points; + + if (tmp_len < numblocks * blocksize) { + /* + * possibly we can do with fewer blocks than estimated + */ + numblocks = (tmp_len + blocksize - 1) / blocksize; + if (numblocks > pre_comp->numblocks) { + ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); + goto err; + } + totalnum = num + numblocks; + } + + /* split wNAF in 'numblocks' parts */ + pp = tmp_wNAF; + tmp_points = pre_comp->points; + + for (i = num; i < totalnum; i++) { + if (i < totalnum - 1) { + wNAF_len[i] = blocksize; + if (tmp_len < blocksize) { + ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); + goto err; + } + tmp_len -= blocksize; + } else + /* + * last block gets whatever is left (this could be + * more or less than 'blocksize'!) + */ + wNAF_len[i] = tmp_len; + + wNAF[i + 1] = NULL; + wNAF[i] = OPENSSL_malloc(wNAF_len[i]); + if (wNAF[i] == NULL) { + ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE); + OPENSSL_free(tmp_wNAF); + goto err; + } + memcpy(wNAF[i], pp, wNAF_len[i]); + if (wNAF_len[i] > max_len) + max_len = wNAF_len[i]; + + if (*tmp_points == NULL) { + ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); + OPENSSL_free(tmp_wNAF); + goto err; + } + val_sub[i] = tmp_points; + tmp_points += pre_points_per_block; + pp += blocksize; + } + OPENSSL_free(tmp_wNAF); + } + } + } + + /* + * All points we precompute now go into a single array 'val'. + * 'val_sub[i]' is a pointer to the subarray for the i-th point, or to a + * subarray of 'pre_comp->points' if we already have precomputation. + */ + val = OPENSSL_malloc((num_val + 1) * sizeof val[0]); + if (val == NULL) { + ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE); + goto err; + } + val[num_val] = NULL; /* pivot element */ + + /* allocate points for precomputation */ + v = val; + for (i = 0; i < num + num_scalar; i++) { + val_sub[i] = v; + for (j = 0; j < ((size_t)1 << (wsize[i] - 1)); j++) { + *v = EC_POINT_new(group); + if (*v == NULL) + goto err; + v++; + } + } + if (!(v == val + num_val)) { + ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!(tmp = EC_POINT_new(group))) + goto err; + + /*- + * prepare precomputed values: + * val_sub[i][0] := points[i] + * val_sub[i][1] := 3 * points[i] + * val_sub[i][2] := 5 * points[i] + * ... + */ + for (i = 0; i < num + num_scalar; i++) { + if (i < num) { + if (!EC_POINT_copy(val_sub[i][0], points[i])) + goto err; + } else { + if (!EC_POINT_copy(val_sub[i][0], generator)) + goto err; + } + + if (wsize[i] > 1) { + if (!EC_POINT_dbl(group, tmp, val_sub[i][0], ctx)) + goto err; + for (j = 1; j < ((size_t)1 << (wsize[i] - 1)); j++) { + if (!EC_POINT_add + (group, val_sub[i][j], val_sub[i][j - 1], tmp, ctx)) + goto err; + } + } + } + +#if 1 /* optional; EC_window_bits_for_scalar_size + * assumes we do this step */ + if (!EC_POINTs_make_affine(group, num_val, val, ctx)) + goto err; #endif - r_is_at_infinity = 1; - - for (k = max_len - 1; k >= 0; k--) - { - if (!r_is_at_infinity) - { - if (!EC_POINT_dbl(group, r, r, ctx)) goto err; - } - - for (i = 0; i < totalnum; i++) - { - if (wNAF_len[i] > (size_t)k) - { - int digit = wNAF[i][k]; - int is_neg; - - if (digit) - { - is_neg = digit < 0; - - if (is_neg) - digit = -digit; - - if (is_neg != r_is_inverted) - { - if (!r_is_at_infinity) - { - if (!EC_POINT_invert(group, r, ctx)) goto err; - } - r_is_inverted = !r_is_inverted; - } - - /* digit > 0 */ - - if (r_is_at_infinity) - { - if (!EC_POINT_copy(r, val_sub[i][digit >> 1])) goto err; - r_is_at_infinity = 0; - } - else - { - if (!EC_POINT_add(group, r, r, val_sub[i][digit >> 1], ctx)) goto err; - } - } - } - } - } - - if (r_is_at_infinity) - { - if (!EC_POINT_set_to_infinity(group, r)) goto err; - } - else - { - if (r_is_inverted) - if (!EC_POINT_invert(group, r, ctx)) goto err; - } - - ret = 1; + r_is_at_infinity = 1; + + for (k = max_len - 1; k >= 0; k--) { + if (!r_is_at_infinity) { + if (!EC_POINT_dbl(group, r, r, ctx)) + goto err; + } + + for (i = 0; i < totalnum; i++) { + if (wNAF_len[i] > (size_t)k) { + int digit = wNAF[i][k]; + int is_neg; + + if (digit) { + is_neg = digit < 0; + + if (is_neg) + digit = -digit; + + if (is_neg != r_is_inverted) { + if (!r_is_at_infinity) { + if (!EC_POINT_invert(group, r, ctx)) + goto err; + } + r_is_inverted = !r_is_inverted; + } + + /* digit > 0 */ + + if (r_is_at_infinity) { + if (!EC_POINT_copy(r, val_sub[i][digit >> 1])) + goto err; + r_is_at_infinity = 0; + } else { + if (!EC_POINT_add + (group, r, r, val_sub[i][digit >> 1], ctx)) + goto err; + } + } + } + } + } + + if (r_is_at_infinity) { + if (!EC_POINT_set_to_infinity(group, r)) + goto err; + } else { + if (r_is_inverted) + if (!EC_POINT_invert(group, r, ctx)) + goto err; + } + + ret = 1; err: - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - if (tmp != NULL) - EC_POINT_free(tmp); - if (wsize != NULL) - OPENSSL_free(wsize); - if (wNAF_len != NULL) - OPENSSL_free(wNAF_len); - if (wNAF != NULL) - { - signed char **w; - - for (w = wNAF; *w != NULL; w++) - OPENSSL_free(*w); - - OPENSSL_free(wNAF); - } - if (val != NULL) - { - for (v = val; *v != NULL; v++) - EC_POINT_clear_free(*v); - - OPENSSL_free(val); - } - if (val_sub != NULL) - { - OPENSSL_free(val_sub); - } - return ret; - } - - -/* ec_wNAF_precompute_mult() + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + if (tmp != NULL) + EC_POINT_free(tmp); + if (wsize != NULL) + OPENSSL_free(wsize); + if (wNAF_len != NULL) + OPENSSL_free(wNAF_len); + if (wNAF != NULL) { + signed char **w; + + for (w = wNAF; *w != NULL; w++) + OPENSSL_free(*w); + + OPENSSL_free(wNAF); + } + if (val != NULL) { + for (v = val; *v != NULL; v++) + EC_POINT_clear_free(*v); + + OPENSSL_free(val); + } + if (val_sub != NULL) { + OPENSSL_free(val_sub); + } + return ret; +} + +/*- + * ec_wNAF_precompute_mult() * creates an EC_PRE_COMP object with preprecomputed multiples of the generator * for use with wNAF splitting as implemented in ec_wNAF_mul(). - * + * * 'pre_comp->points' is an array of multiples of the generator * of the following form: * points[0] = generator; @@ -764,178 +739,175 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, * points[2^(w-1)*numblocks] = NULL */ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx) - { - const EC_POINT *generator; - EC_POINT *tmp_point = NULL, *base = NULL, **var; - BN_CTX *new_ctx = NULL; - BIGNUM *order; - size_t i, bits, w, pre_points_per_block, blocksize, numblocks, num; - EC_POINT **points = NULL; - EC_PRE_COMP *pre_comp; - int ret = 0; - - /* if there is an old EC_PRE_COMP object, throw it away */ - EC_EX_DATA_free_data(&group->extra_data, ec_pre_comp_dup, ec_pre_comp_free, ec_pre_comp_clear_free); - - if ((pre_comp = ec_pre_comp_new(group)) == NULL) - return 0; - - generator = EC_GROUP_get0_generator(group); - if (generator == NULL) - { - ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNDEFINED_GENERATOR); - goto err; - } - - if (ctx == NULL) - { - ctx = new_ctx = BN_CTX_new(); - if (ctx == NULL) - goto err; - } - - BN_CTX_start(ctx); - order = BN_CTX_get(ctx); - if (order == NULL) goto err; - - if (!EC_GROUP_get_order(group, order, ctx)) goto err; - if (BN_is_zero(order)) - { - ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNKNOWN_ORDER); - goto err; - } - - bits = BN_num_bits(order); - /* The following parameters mean we precompute (approximately) - * one point per bit. - * - * TBD: The combination 8, 4 is perfect for 160 bits; for other - * bit lengths, other parameter combinations might provide better - * efficiency. - */ - blocksize = 8; - w = 4; - if (EC_window_bits_for_scalar_size(bits) > w) - { - /* let's not make the window too small ... */ - w = EC_window_bits_for_scalar_size(bits); - } - - numblocks = (bits + blocksize - 1) / blocksize; /* max. number of blocks to use for wNAF splitting */ - - pre_points_per_block = (size_t)1 << (w - 1); - num = pre_points_per_block * numblocks; /* number of points to compute and store */ - - points = OPENSSL_malloc(sizeof (EC_POINT*)*(num + 1)); - if (!points) - { - ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE); - goto err; - } - - var = points; - var[num] = NULL; /* pivot */ - for (i = 0; i < num; i++) - { - if ((var[i] = EC_POINT_new(group)) == NULL) - { - ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE); - goto err; - } - } - - if (!(tmp_point = EC_POINT_new(group)) || !(base = EC_POINT_new(group))) - { - ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE); - goto err; - } - - if (!EC_POINT_copy(base, generator)) - goto err; - - /* do the precomputation */ - for (i = 0; i < numblocks; i++) - { - size_t j; - - if (!EC_POINT_dbl(group, tmp_point, base, ctx)) - goto err; - - if (!EC_POINT_copy(*var++, base)) - goto err; - - for (j = 1; j < pre_points_per_block; j++, var++) - { - /* calculate odd multiples of the current base point */ - if (!EC_POINT_add(group, *var, tmp_point, *(var - 1), ctx)) - goto err; - } - - if (i < numblocks - 1) - { - /* get the next base (multiply current one by 2^blocksize) */ - size_t k; - - if (blocksize <= 2) - { - ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_INTERNAL_ERROR); - goto err; - } - - if (!EC_POINT_dbl(group, base, tmp_point, ctx)) - goto err; - for (k = 2; k < blocksize; k++) - { - if (!EC_POINT_dbl(group,base,base,ctx)) - goto err; - } - } - } - - if (!EC_POINTs_make_affine(group, num, points, ctx)) - goto err; - - pre_comp->group = group; - pre_comp->blocksize = blocksize; - pre_comp->numblocks = numblocks; - pre_comp->w = w; - pre_comp->points = points; - points = NULL; - pre_comp->num = num; - - if (!EC_EX_DATA_set_data(&group->extra_data, pre_comp, - ec_pre_comp_dup, ec_pre_comp_free, ec_pre_comp_clear_free)) - goto err; - pre_comp = NULL; - - ret = 1; +{ + const EC_POINT *generator; + EC_POINT *tmp_point = NULL, *base = NULL, **var; + BN_CTX *new_ctx = NULL; + BIGNUM *order; + size_t i, bits, w, pre_points_per_block, blocksize, numblocks, num; + EC_POINT **points = NULL; + EC_PRE_COMP *pre_comp; + int ret = 0; + + /* if there is an old EC_PRE_COMP object, throw it away */ + EC_EX_DATA_free_data(&group->extra_data, ec_pre_comp_dup, + ec_pre_comp_free, ec_pre_comp_clear_free); + + if ((pre_comp = ec_pre_comp_new(group)) == NULL) + return 0; + + generator = EC_GROUP_get0_generator(group); + if (generator == NULL) { + ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNDEFINED_GENERATOR); + goto err; + } + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + goto err; + } + + BN_CTX_start(ctx); + order = BN_CTX_get(ctx); + if (order == NULL) + goto err; + + if (!EC_GROUP_get_order(group, order, ctx)) + goto err; + if (BN_is_zero(order)) { + ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNKNOWN_ORDER); + goto err; + } + + bits = BN_num_bits(order); + /* + * The following parameters mean we precompute (approximately) one point + * per bit. TBD: The combination 8, 4 is perfect for 160 bits; for other + * bit lengths, other parameter combinations might provide better + * efficiency. + */ + blocksize = 8; + w = 4; + if (EC_window_bits_for_scalar_size(bits) > w) { + /* let's not make the window too small ... */ + w = EC_window_bits_for_scalar_size(bits); + } + + numblocks = (bits + blocksize - 1) / blocksize; /* max. number of blocks + * to use for wNAF + * splitting */ + + pre_points_per_block = (size_t)1 << (w - 1); + num = pre_points_per_block * numblocks; /* number of points to compute + * and store */ + + points = OPENSSL_malloc(sizeof(EC_POINT *) * (num + 1)); + if (!points) { + ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE); + goto err; + } + + var = points; + var[num] = NULL; /* pivot */ + for (i = 0; i < num; i++) { + if ((var[i] = EC_POINT_new(group)) == NULL) { + ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + if (!(tmp_point = EC_POINT_new(group)) || !(base = EC_POINT_new(group))) { + ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!EC_POINT_copy(base, generator)) + goto err; + + /* do the precomputation */ + for (i = 0; i < numblocks; i++) { + size_t j; + + if (!EC_POINT_dbl(group, tmp_point, base, ctx)) + goto err; + + if (!EC_POINT_copy(*var++, base)) + goto err; + + for (j = 1; j < pre_points_per_block; j++, var++) { + /* + * calculate odd multiples of the current base point + */ + if (!EC_POINT_add(group, *var, tmp_point, *(var - 1), ctx)) + goto err; + } + + if (i < numblocks - 1) { + /* + * get the next base (multiply current one by 2^blocksize) + */ + size_t k; + + if (blocksize <= 2) { + ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!EC_POINT_dbl(group, base, tmp_point, ctx)) + goto err; + for (k = 2; k < blocksize; k++) { + if (!EC_POINT_dbl(group, base, base, ctx)) + goto err; + } + } + } + + if (!EC_POINTs_make_affine(group, num, points, ctx)) + goto err; + + pre_comp->group = group; + pre_comp->blocksize = blocksize; + pre_comp->numblocks = numblocks; + pre_comp->w = w; + pre_comp->points = points; + points = NULL; + pre_comp->num = num; + + if (!EC_EX_DATA_set_data(&group->extra_data, pre_comp, + ec_pre_comp_dup, ec_pre_comp_free, + ec_pre_comp_clear_free)) + goto err; + pre_comp = NULL; + + ret = 1; err: - if (ctx != NULL) - BN_CTX_end(ctx); - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - if (pre_comp) - ec_pre_comp_free(pre_comp); - if (points) - { - EC_POINT **p; - - for (p = points; *p != NULL; p++) - EC_POINT_free(*p); - OPENSSL_free(points); - } - if (tmp_point) - EC_POINT_free(tmp_point); - if (base) - EC_POINT_free(base); - return ret; - } - + if (ctx != NULL) + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + if (pre_comp) + ec_pre_comp_free(pre_comp); + if (points) { + EC_POINT **p; + + for (p = points; *p != NULL; p++) + EC_POINT_free(*p); + OPENSSL_free(points); + } + if (tmp_point) + EC_POINT_free(tmp_point); + if (base) + EC_POINT_free(base); + return ret; +} int ec_wNAF_have_precompute_mult(const EC_GROUP *group) - { - if (EC_EX_DATA_get_data(group->extra_data, ec_pre_comp_dup, ec_pre_comp_free, ec_pre_comp_clear_free) != NULL) - return 1; - else - return 0; - } +{ + if (EC_EX_DATA_get_data + (group->extra_data, ec_pre_comp_dup, ec_pre_comp_free, + ec_pre_comp_clear_free) != NULL) + return 1; + else + return 0; +} diff --git a/openssl/crypto/ec/ec_oct.c b/openssl/crypto/ec/ec_oct.c index fd9db0798..040c414a3 100644 --- a/openssl/crypto/ec/ec_oct.c +++ b/openssl/crypto/ec/ec_oct.c @@ -10,7 +10,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -57,7 +57,7 @@ */ /* ==================================================================== * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. - * Binary polynomial ECC support in OpenSSL originally developed by + * Binary polynomial ECC support in OpenSSL originally developed by * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. */ @@ -68,132 +68,125 @@ #include "ec_lcl.h" -int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, - const BIGNUM *x, int y_bit, BN_CTX *ctx) - { - if (group->meth->point_set_compressed_coordinates == 0 - && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) - { - ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } - if (group->meth != point->meth) - { - ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS); - return 0; - } - if(group->meth->flags & EC_FLAGS_DEFAULT_OCT) - { - if (group->meth->field_type == NID_X9_62_prime_field) - return ec_GFp_simple_set_compressed_coordinates( - group, point, x, y_bit, ctx); - else +int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, + EC_POINT *point, const BIGNUM *x, + int y_bit, BN_CTX *ctx) +{ + if (group->meth->point_set_compressed_coordinates == 0 + && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) { + ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (group->meth != point->meth) { + ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, + EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) { + if (group->meth->field_type == NID_X9_62_prime_field) + return ec_GFp_simple_set_compressed_coordinates(group, point, x, + y_bit, ctx); + else #ifdef OPENSSL_NO_EC2M - { - ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, EC_R_GF2M_NOT_SUPPORTED); - return 0; - } + { + ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, + EC_R_GF2M_NOT_SUPPORTED); + return 0; + } #else - return ec_GF2m_simple_set_compressed_coordinates( - group, point, x, y_bit, ctx); + return ec_GF2m_simple_set_compressed_coordinates(group, point, x, + y_bit, ctx); #endif - } - return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx); - } + } + return group->meth->point_set_compressed_coordinates(group, point, x, + y_bit, ctx); +} #ifndef OPENSSL_NO_EC2M -int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point, - const BIGNUM *x, int y_bit, BN_CTX *ctx) - { - if (group->meth->point_set_compressed_coordinates == 0 - && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) - { - ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } - if (group->meth != point->meth) - { - ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS); - return 0; - } - if(group->meth->flags & EC_FLAGS_DEFAULT_OCT) - { - if (group->meth->field_type == NID_X9_62_prime_field) - return ec_GFp_simple_set_compressed_coordinates( - group, point, x, y_bit, ctx); - else - return ec_GF2m_simple_set_compressed_coordinates( - group, point, x, y_bit, ctx); - } - return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx); - } +int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, + EC_POINT *point, const BIGNUM *x, + int y_bit, BN_CTX *ctx) +{ + if (group->meth->point_set_compressed_coordinates == 0 + && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) { + ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + if (group->meth != point->meth) { + ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, + EC_R_INCOMPATIBLE_OBJECTS); + return 0; + } + if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) { + if (group->meth->field_type == NID_X9_62_prime_field) + return ec_GFp_simple_set_compressed_coordinates(group, point, x, + y_bit, ctx); + else + return ec_GF2m_simple_set_compressed_coordinates(group, point, x, + y_bit, ctx); + } + return group->meth->point_set_compressed_coordinates(group, point, x, + y_bit, ctx); +} #endif -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 - && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) - { - 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; - } - if(group->meth->flags & EC_FLAGS_DEFAULT_OCT) - { - if (group->meth->field_type == NID_X9_62_prime_field) - return ec_GFp_simple_point2oct(group, point, - form, buf, len, ctx); - else +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 + && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) { + 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; + } + if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) { + if (group->meth->field_type == NID_X9_62_prime_field) + return ec_GFp_simple_point2oct(group, point, form, buf, len, ctx); + else #ifdef OPENSSL_NO_EC2M - { - ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_GF2M_NOT_SUPPORTED); - return 0; - } + { + ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_GF2M_NOT_SUPPORTED); + return 0; + } #else - return ec_GF2m_simple_point2oct(group, point, - form, buf, len, ctx); + return ec_GF2m_simple_point2oct(group, point, + form, buf, len, ctx); #endif - } - - return group->meth->point2oct(group, point, form, buf, len, ctx); - } + } + 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 - && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) - { - 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; - } - if(group->meth->flags & EC_FLAGS_DEFAULT_OCT) - { - if (group->meth->field_type == NID_X9_62_prime_field) - return ec_GFp_simple_oct2point(group, point, - buf, len, ctx); - else + const unsigned char *buf, size_t len, BN_CTX *ctx) +{ + if (group->meth->oct2point == 0 + && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) { + 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; + } + if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) { + if (group->meth->field_type == NID_X9_62_prime_field) + return ec_GFp_simple_oct2point(group, point, buf, len, ctx); + else #ifdef OPENSSL_NO_EC2M - { - ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_GF2M_NOT_SUPPORTED); - return 0; - } + { + ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_GF2M_NOT_SUPPORTED); + return 0; + } #else - return ec_GF2m_simple_oct2point(group, point, - buf, len, ctx); + return ec_GF2m_simple_oct2point(group, point, buf, len, ctx); #endif - } - return group->meth->oct2point(group, point, buf, len, ctx); - } - + } + return group->meth->oct2point(group, point, buf, len, ctx); +} diff --git a/openssl/crypto/ec/ec_pmeth.c b/openssl/crypto/ec/ec_pmeth.c index b62b532cf..c189d3ffb 100644 --- a/openssl/crypto/ec/ec_pmeth.c +++ b/openssl/crypto/ec/ec_pmeth.c @@ -1,5 +1,6 @@ -/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL - * project 2006. +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2006. */ /* ==================================================================== * Copyright (c) 2006 The OpenSSL Project. All rights reserved. @@ -9,7 +10,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -66,282 +67,266 @@ /* EC pkey context structure */ -typedef struct - { - /* Key and paramgen group */ - EC_GROUP *gen_group; - /* message digest */ - const EVP_MD *md; - } EC_PKEY_CTX; +typedef struct { + /* Key and paramgen group */ + EC_GROUP *gen_group; + /* message digest */ + const EVP_MD *md; +} EC_PKEY_CTX; static int pkey_ec_init(EVP_PKEY_CTX *ctx) - { - EC_PKEY_CTX *dctx; - dctx = OPENSSL_malloc(sizeof(EC_PKEY_CTX)); - if (!dctx) - return 0; - dctx->gen_group = NULL; - dctx->md = NULL; +{ + EC_PKEY_CTX *dctx; + dctx = OPENSSL_malloc(sizeof(EC_PKEY_CTX)); + if (!dctx) + return 0; + dctx->gen_group = NULL; + dctx->md = NULL; - ctx->data = dctx; + ctx->data = dctx; - return 1; - } + return 1; +} static int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) - { - EC_PKEY_CTX *dctx, *sctx; - if (!pkey_ec_init(dst)) - return 0; - sctx = src->data; - dctx = dst->data; - if (sctx->gen_group) - { - dctx->gen_group = EC_GROUP_dup(sctx->gen_group); - if (!dctx->gen_group) - return 0; - } - dctx->md = sctx->md; - return 1; - } +{ + EC_PKEY_CTX *dctx, *sctx; + if (!pkey_ec_init(dst)) + return 0; + sctx = src->data; + dctx = dst->data; + if (sctx->gen_group) { + dctx->gen_group = EC_GROUP_dup(sctx->gen_group); + if (!dctx->gen_group) + return 0; + } + dctx->md = sctx->md; + return 1; +} static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx) - { - EC_PKEY_CTX *dctx = ctx->data; - if (dctx) - { - if (dctx->gen_group) - EC_GROUP_free(dctx->gen_group); - OPENSSL_free(dctx); - } - } +{ + EC_PKEY_CTX *dctx = ctx->data; + if (dctx) { + if (dctx->gen_group) + EC_GROUP_free(dctx->gen_group); + OPENSSL_free(dctx); + } +} static int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, - const unsigned char *tbs, size_t tbslen) - { - int ret, type; - unsigned int sltmp; - EC_PKEY_CTX *dctx = ctx->data; - EC_KEY *ec = ctx->pkey->pkey.ec; - - if (!sig) - { - *siglen = ECDSA_size(ec); - return 1; - } - else if(*siglen < (size_t)ECDSA_size(ec)) - { - ECerr(EC_F_PKEY_EC_SIGN, EC_R_BUFFER_TOO_SMALL); - return 0; - } - - if (dctx->md) - type = EVP_MD_type(dctx->md); - else - type = NID_sha1; - - - ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec); - - if (ret <= 0) - return ret; - *siglen = (size_t)sltmp; - return 1; - } + const unsigned char *tbs, size_t tbslen) +{ + int ret, type; + unsigned int sltmp; + EC_PKEY_CTX *dctx = ctx->data; + EC_KEY *ec = ctx->pkey->pkey.ec; + + if (!sig) { + *siglen = ECDSA_size(ec); + return 1; + } else if (*siglen < (size_t)ECDSA_size(ec)) { + ECerr(EC_F_PKEY_EC_SIGN, EC_R_BUFFER_TOO_SMALL); + return 0; + } + + if (dctx->md) + type = EVP_MD_type(dctx->md); + else + type = NID_sha1; + + ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec); + + if (ret <= 0) + return ret; + *siglen = (size_t)sltmp; + return 1; +} static int pkey_ec_verify(EVP_PKEY_CTX *ctx, - const unsigned char *sig, size_t siglen, - const unsigned char *tbs, size_t tbslen) - { - int ret, type; - EC_PKEY_CTX *dctx = ctx->data; - EC_KEY *ec = ctx->pkey->pkey.ec; + const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen) +{ + int ret, type; + EC_PKEY_CTX *dctx = ctx->data; + EC_KEY *ec = ctx->pkey->pkey.ec; - if (dctx->md) - type = EVP_MD_type(dctx->md); - else - type = NID_sha1; + if (dctx->md) + type = EVP_MD_type(dctx->md); + else + type = NID_sha1; - ret = ECDSA_verify(type, tbs, tbslen, sig, siglen, ec); + ret = ECDSA_verify(type, tbs, tbslen, sig, siglen, ec); - return ret; - } + return ret; +} #ifndef OPENSSL_NO_ECDH -static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen) - { - int ret; - size_t outlen; - const EC_POINT *pubkey = NULL; - if (!ctx->pkey || !ctx->peerkey) - { - ECerr(EC_F_PKEY_EC_DERIVE, EC_R_KEYS_NOT_SET); - return 0; - } - - if (!key) - { - const EC_GROUP *group; - group = EC_KEY_get0_group(ctx->pkey->pkey.ec); - *keylen = (EC_GROUP_get_degree(group) + 7)/8; - return 1; - } - - pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec); - - /* NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is - * not an error, the result is truncated. - */ - - outlen = *keylen; - - ret = ECDH_compute_key(key, outlen, pubkey, ctx->pkey->pkey.ec, 0); - if (ret < 0) - return ret; - *keylen = ret; - return 1; - } +static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, + size_t *keylen) +{ + int ret; + size_t outlen; + const EC_POINT *pubkey = NULL; + if (!ctx->pkey || !ctx->peerkey) { + ECerr(EC_F_PKEY_EC_DERIVE, EC_R_KEYS_NOT_SET); + return 0; + } + + if (!key) { + const EC_GROUP *group; + group = EC_KEY_get0_group(ctx->pkey->pkey.ec); + *keylen = (EC_GROUP_get_degree(group) + 7) / 8; + return 1; + } + + pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec); + + /* + * NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is not + * an error, the result is truncated. + */ + + outlen = *keylen; + + ret = ECDH_compute_key(key, outlen, pubkey, ctx->pkey->pkey.ec, 0); + if (ret < 0) + return ret; + *keylen = ret; + return 1; +} #endif static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) - { - EC_PKEY_CTX *dctx = ctx->data; - EC_GROUP *group; - switch (type) - { - case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: - group = EC_GROUP_new_by_curve_name(p1); - if (group == NULL) - { - ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_CURVE); - return 0; - } - if (dctx->gen_group) - EC_GROUP_free(dctx->gen_group); - dctx->gen_group = group; - return 1; - - case EVP_PKEY_CTRL_MD: - if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 && - EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 && - EVP_MD_type((const EVP_MD *)p2) != NID_sha224 && - EVP_MD_type((const EVP_MD *)p2) != NID_sha256 && - EVP_MD_type((const EVP_MD *)p2) != NID_sha384 && - EVP_MD_type((const EVP_MD *)p2) != NID_sha512) - { - ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE); - return 0; - } - dctx->md = p2; - return 1; - - case EVP_PKEY_CTRL_PEER_KEY: - /* Default behaviour is OK */ - case EVP_PKEY_CTRL_DIGESTINIT: - case EVP_PKEY_CTRL_PKCS7_SIGN: - case EVP_PKEY_CTRL_CMS_SIGN: - return 1; - - default: - return -2; - - } - } - +{ + EC_PKEY_CTX *dctx = ctx->data; + EC_GROUP *group; + switch (type) { + case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: + group = EC_GROUP_new_by_curve_name(p1); + if (group == NULL) { + ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_CURVE); + return 0; + } + if (dctx->gen_group) + EC_GROUP_free(dctx->gen_group); + dctx->gen_group = group; + return 1; + + case EVP_PKEY_CTRL_MD: + if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 && + EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha224 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha256 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha384 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha512) { + ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE); + return 0; + } + dctx->md = p2; + return 1; + + case EVP_PKEY_CTRL_PEER_KEY: + /* Default behaviour is OK */ + case EVP_PKEY_CTRL_DIGESTINIT: + case EVP_PKEY_CTRL_PKCS7_SIGN: + case EVP_PKEY_CTRL_CMS_SIGN: + return 1; + + default: + return -2; + + } +} + static int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx, - const char *type, const char *value) - { - if (!strcmp(type, "ec_paramgen_curve")) - { - int nid; - nid = OBJ_sn2nid(value); - if (nid == NID_undef) - nid = OBJ_ln2nid(value); - if (nid == NID_undef) - { - ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_CURVE); - return 0; - } - return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); - } - return -2; - } + const char *type, const char *value) +{ + if (!strcmp(type, "ec_paramgen_curve")) { + int nid; + nid = OBJ_sn2nid(value); + if (nid == NID_undef) + nid = OBJ_ln2nid(value); + if (nid == NID_undef) { + ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_CURVE); + return 0; + } + return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); + } + return -2; +} static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) - { - EC_KEY *ec = NULL; - EC_PKEY_CTX *dctx = ctx->data; - int ret = 0; - if (dctx->gen_group == NULL) - { - ECerr(EC_F_PKEY_EC_PARAMGEN, EC_R_NO_PARAMETERS_SET); - return 0; - } - ec = EC_KEY_new(); - if (!ec) - return 0; - ret = EC_KEY_set_group(ec, dctx->gen_group); - if (ret) - EVP_PKEY_assign_EC_KEY(pkey, ec); - else - EC_KEY_free(ec); - return ret; - } +{ + EC_KEY *ec = NULL; + EC_PKEY_CTX *dctx = ctx->data; + int ret = 0; + if (dctx->gen_group == NULL) { + ECerr(EC_F_PKEY_EC_PARAMGEN, EC_R_NO_PARAMETERS_SET); + return 0; + } + ec = EC_KEY_new(); + if (!ec) + return 0; + ret = EC_KEY_set_group(ec, dctx->gen_group); + if (ret) + EVP_PKEY_assign_EC_KEY(pkey, ec); + else + EC_KEY_free(ec); + return ret; +} static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) - { - EC_KEY *ec = NULL; - if (ctx->pkey == NULL) - { - ECerr(EC_F_PKEY_EC_KEYGEN, EC_R_NO_PARAMETERS_SET); - return 0; - } - ec = EC_KEY_new(); - if (!ec) - return 0; - EVP_PKEY_assign_EC_KEY(pkey, ec); - /* Note: if error return, pkey is freed by parent routine */ - if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) - return 0; - return EC_KEY_generate_key(pkey->pkey.ec); - } - -const EVP_PKEY_METHOD ec_pkey_meth = - { - EVP_PKEY_EC, - 0, - pkey_ec_init, - pkey_ec_copy, - pkey_ec_cleanup, - - 0, - pkey_ec_paramgen, - - 0, - pkey_ec_keygen, - - 0, - pkey_ec_sign, - - 0, - pkey_ec_verify, - - 0,0, - - 0,0,0,0, - - 0,0, - - 0,0, - - 0, +{ + EC_KEY *ec = NULL; + if (ctx->pkey == NULL) { + ECerr(EC_F_PKEY_EC_KEYGEN, EC_R_NO_PARAMETERS_SET); + return 0; + } + ec = EC_KEY_new(); + if (!ec) + return 0; + EVP_PKEY_assign_EC_KEY(pkey, ec); + /* Note: if error return, pkey is freed by parent routine */ + if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) + return 0; + return EC_KEY_generate_key(pkey->pkey.ec); +} + +const EVP_PKEY_METHOD ec_pkey_meth = { + EVP_PKEY_EC, + 0, + pkey_ec_init, + pkey_ec_copy, + pkey_ec_cleanup, + + 0, + pkey_ec_paramgen, + + 0, + pkey_ec_keygen, + + 0, + pkey_ec_sign, + + 0, + pkey_ec_verify, + + 0, 0, + + 0, 0, 0, 0, + + 0, 0, + + 0, 0, + + 0, #ifndef OPENSSL_NO_ECDH - pkey_ec_derive, + pkey_ec_derive, #else - 0, + 0, #endif - pkey_ec_ctrl, - pkey_ec_ctrl_str - - }; + pkey_ec_ctrl, + pkey_ec_ctrl_str +}; diff --git a/openssl/crypto/ec/ec_print.c b/openssl/crypto/ec/ec_print.c index f7c8a303a..96b294d87 100644 --- a/openssl/crypto/ec/ec_print.c +++ b/openssl/crypto/ec/ec_print.c @@ -7,7 +7,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -56,140 +56,124 @@ #include <openssl/crypto.h> #include "ec_lcl.h" -BIGNUM *EC_POINT_point2bn(const EC_GROUP *group, - const EC_POINT *point, +BIGNUM *EC_POINT_point2bn(const EC_GROUP *group, + const EC_POINT *point, point_conversion_form_t form, - BIGNUM *ret, - BN_CTX *ctx) - { - size_t buf_len=0; - unsigned char *buf; + BIGNUM *ret, BN_CTX *ctx) +{ + size_t buf_len = 0; + unsigned char *buf; - buf_len = EC_POINT_point2oct(group, point, form, - NULL, 0, ctx); - if (buf_len == 0) - return NULL; + buf_len = EC_POINT_point2oct(group, point, form, NULL, 0, ctx); + if (buf_len == 0) + return NULL; - if ((buf = OPENSSL_malloc(buf_len)) == NULL) - return NULL; + if ((buf = OPENSSL_malloc(buf_len)) == NULL) + return NULL; - if (!EC_POINT_point2oct(group, point, form, buf, buf_len, ctx)) - { - OPENSSL_free(buf); - return NULL; - } + if (!EC_POINT_point2oct(group, point, form, buf, buf_len, ctx)) { + OPENSSL_free(buf); + return NULL; + } - ret = BN_bin2bn(buf, buf_len, ret); + ret = BN_bin2bn(buf, buf_len, ret); - OPENSSL_free(buf); + OPENSSL_free(buf); - return ret; + return ret; } EC_POINT *EC_POINT_bn2point(const EC_GROUP *group, - const BIGNUM *bn, - EC_POINT *point, - BN_CTX *ctx) - { - size_t buf_len=0; - unsigned char *buf; - EC_POINT *ret; - - if ((buf_len = BN_num_bytes(bn)) == 0) return NULL; - buf = OPENSSL_malloc(buf_len); - if (buf == NULL) - return NULL; - - if (!BN_bn2bin(bn, buf)) - { - OPENSSL_free(buf); - return NULL; - } - - if (point == NULL) - { - if ((ret = EC_POINT_new(group)) == NULL) - { - OPENSSL_free(buf); - return NULL; - } - } - else - ret = point; - - if (!EC_POINT_oct2point(group, ret, buf, buf_len, ctx)) - { - if (point == NULL) - EC_POINT_clear_free(ret); - OPENSSL_free(buf); - return NULL; - } - - OPENSSL_free(buf); - return ret; - } + const BIGNUM *bn, EC_POINT *point, BN_CTX *ctx) +{ + size_t buf_len = 0; + unsigned char *buf; + EC_POINT *ret; + + if ((buf_len = BN_num_bytes(bn)) == 0) + return NULL; + buf = OPENSSL_malloc(buf_len); + if (buf == NULL) + return NULL; + + if (!BN_bn2bin(bn, buf)) { + OPENSSL_free(buf); + return NULL; + } + + if (point == NULL) { + if ((ret = EC_POINT_new(group)) == NULL) { + OPENSSL_free(buf); + return NULL; + } + } else + ret = point; + + if (!EC_POINT_oct2point(group, ret, buf, buf_len, ctx)) { + if (point == NULL) + EC_POINT_clear_free(ret); + OPENSSL_free(buf); + return NULL; + } + + OPENSSL_free(buf); + return ret; +} static const char *HEX_DIGITS = "0123456789ABCDEF"; /* the return value must be freed (using OPENSSL_free()) */ char *EC_POINT_point2hex(const EC_GROUP *group, const EC_POINT *point, - point_conversion_form_t form, - BN_CTX *ctx) - { - char *ret, *p; - size_t buf_len=0,i; - unsigned char *buf, *pbuf; - - buf_len = EC_POINT_point2oct(group, point, form, - NULL, 0, ctx); - if (buf_len == 0) - return NULL; - - if ((buf = OPENSSL_malloc(buf_len)) == NULL) - return NULL; - - if (!EC_POINT_point2oct(group, point, form, buf, buf_len, ctx)) - { - OPENSSL_free(buf); - return NULL; - } - - ret = (char *)OPENSSL_malloc(buf_len*2+2); - if (ret == NULL) - { - OPENSSL_free(buf); - return NULL; - } - p = ret; - pbuf = buf; - for (i=buf_len; i > 0; i--) - { - int v = (int) *(pbuf++); - *(p++)=HEX_DIGITS[v>>4]; - *(p++)=HEX_DIGITS[v&0x0F]; - } - *p='\0'; - - OPENSSL_free(buf); - - return ret; - } + point_conversion_form_t form, BN_CTX *ctx) +{ + char *ret, *p; + size_t buf_len = 0, i; + unsigned char *buf, *pbuf; + + buf_len = EC_POINT_point2oct(group, point, form, NULL, 0, ctx); + if (buf_len == 0) + return NULL; + + if ((buf = OPENSSL_malloc(buf_len)) == NULL) + return NULL; + + if (!EC_POINT_point2oct(group, point, form, buf, buf_len, ctx)) { + OPENSSL_free(buf); + return NULL; + } + + ret = (char *)OPENSSL_malloc(buf_len * 2 + 2); + if (ret == NULL) { + OPENSSL_free(buf); + return NULL; + } + p = ret; + pbuf = buf; + for (i = buf_len; i > 0; i--) { + int v = (int)*(pbuf++); + *(p++) = HEX_DIGITS[v >> 4]; + *(p++) = HEX_DIGITS[v & 0x0F]; + } + *p = '\0'; + + OPENSSL_free(buf); + + return ret; +} EC_POINT *EC_POINT_hex2point(const EC_GROUP *group, - const char *buf, - EC_POINT *point, - BN_CTX *ctx) - { - EC_POINT *ret=NULL; - BIGNUM *tmp_bn=NULL; + const char *buf, EC_POINT *point, BN_CTX *ctx) +{ + EC_POINT *ret = NULL; + BIGNUM *tmp_bn = NULL; - if (!BN_hex2bn(&tmp_bn, buf)) - return NULL; + if (!BN_hex2bn(&tmp_bn, buf)) + return NULL; - ret = EC_POINT_bn2point(group, tmp_bn, point, ctx); + ret = EC_POINT_bn2point(group, tmp_bn, point, ctx); - BN_clear_free(tmp_bn); + BN_clear_free(tmp_bn); - return ret; - } + return ret; +} diff --git a/openssl/crypto/ec/eck_prn.c b/openssl/crypto/ec/eck_prn.c index 06de8f395..a911a0ac4 100644 --- a/openssl/crypto/ec/eck_prn.c +++ b/openssl/crypto/ec/eck_prn.c @@ -10,7 +10,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -57,7 +57,7 @@ */ /* ==================================================================== * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. - * Portions originally developed by SUN MICROSYSTEMS, INC., and + * Portions originally developed by SUN MICROSYSTEMS, INC., and * contributed to the OpenSSL project. */ @@ -69,324 +69,299 @@ #ifndef OPENSSL_NO_FP_API int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off) - { - BIO *b; - int ret; - - if ((b=BIO_new(BIO_s_file())) == NULL) - { - ECerr(EC_F_ECPKPARAMETERS_PRINT_FP,ERR_R_BUF_LIB); - return(0); - } - BIO_set_fp(b, fp, BIO_NOCLOSE); - ret = ECPKParameters_print(b, x, off); - BIO_free(b); - return(ret); - } +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + ECerr(EC_F_ECPKPARAMETERS_PRINT_FP, ERR_R_BUF_LIB); + return (0); + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = ECPKParameters_print(b, x, off); + BIO_free(b); + return (ret); +} int EC_KEY_print_fp(FILE *fp, const EC_KEY *x, int off) - { - BIO *b; - int ret; - - if ((b=BIO_new(BIO_s_file())) == NULL) - { - ECerr(EC_F_EC_KEY_PRINT_FP, ERR_R_BIO_LIB); - return(0); - } - BIO_set_fp(b, fp, BIO_NOCLOSE); - ret = EC_KEY_print(b, x, off); - BIO_free(b); - return(ret); - } +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + ECerr(EC_F_EC_KEY_PRINT_FP, ERR_R_BIO_LIB); + return (0); + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = EC_KEY_print(b, x, off); + BIO_free(b); + return (ret); +} int ECParameters_print_fp(FILE *fp, const EC_KEY *x) - { - BIO *b; - int ret; - - if ((b=BIO_new(BIO_s_file())) == NULL) - { - ECerr(EC_F_ECPARAMETERS_PRINT_FP, ERR_R_BIO_LIB); - return(0); - } - BIO_set_fp(b, fp, BIO_NOCLOSE); - ret = ECParameters_print(b, x); - BIO_free(b); - return(ret); - } +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + ECerr(EC_F_ECPARAMETERS_PRINT_FP, ERR_R_BIO_LIB); + return (0); + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = ECParameters_print(b, x); + BIO_free(b); + return (ret); +} #endif int EC_KEY_print(BIO *bp, const EC_KEY *x, int off) - { - EVP_PKEY *pk; - int ret; - pk = EVP_PKEY_new(); - if (!pk || !EVP_PKEY_set1_EC_KEY(pk, (EC_KEY *)x)) - return 0; - ret = EVP_PKEY_print_private(bp, pk, off, NULL); - EVP_PKEY_free(pk); - return ret; - } +{ + EVP_PKEY *pk; + int ret; + pk = EVP_PKEY_new(); + if (!pk || !EVP_PKEY_set1_EC_KEY(pk, (EC_KEY *)x)) + return 0; + ret = EVP_PKEY_print_private(bp, pk, off, NULL); + EVP_PKEY_free(pk); + return ret; +} int ECParameters_print(BIO *bp, const EC_KEY *x) - { - EVP_PKEY *pk; - int ret; - pk = EVP_PKEY_new(); - if (!pk || !EVP_PKEY_set1_EC_KEY(pk, (EC_KEY *)x)) - return 0; - ret = EVP_PKEY_print_params(bp, pk, 4, NULL); - EVP_PKEY_free(pk); - return ret; - } +{ + EVP_PKEY *pk; + int ret; + pk = EVP_PKEY_new(); + if (!pk || !EVP_PKEY_set1_EC_KEY(pk, (EC_KEY *)x)) + return 0; + ret = EVP_PKEY_print_params(bp, pk, 4, NULL); + EVP_PKEY_free(pk); + return ret; +} static int print_bin(BIO *fp, const char *str, const unsigned char *num, - size_t len, int off); + size_t len, int off); int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off) - { - unsigned char *buffer=NULL; - size_t buf_len=0, i; - int ret=0, reason=ERR_R_BIO_LIB; - BN_CTX *ctx=NULL; - const EC_POINT *point=NULL; - BIGNUM *p=NULL, *a=NULL, *b=NULL, *gen=NULL, - *order=NULL, *cofactor=NULL; - const unsigned char *seed; - size_t seed_len=0; - - static const char *gen_compressed = "Generator (compressed):"; - static const char *gen_uncompressed = "Generator (uncompressed):"; - static const char *gen_hybrid = "Generator (hybrid):"; - - if (!x) - { - reason = ERR_R_PASSED_NULL_PARAMETER; - goto err; - } - - ctx = BN_CTX_new(); - if (ctx == NULL) - { - reason = ERR_R_MALLOC_FAILURE; - goto err; - } - - if (EC_GROUP_get_asn1_flag(x)) - { - /* the curve parameter are given by an asn1 OID */ - int nid; - - if (!BIO_indent(bp, off, 128)) - goto err; - - nid = EC_GROUP_get_curve_name(x); - if (nid == 0) - goto err; - - if (BIO_printf(bp, "ASN1 OID: %s", OBJ_nid2sn(nid)) <= 0) - goto err; - if (BIO_printf(bp, "\n") <= 0) - goto err; - } - else - { - /* explicit parameters */ - int is_char_two = 0; - point_conversion_form_t form; - int tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(x)); - - if (tmp_nid == NID_X9_62_characteristic_two_field) - is_char_two = 1; - - if ((p = BN_new()) == NULL || (a = BN_new()) == NULL || - (b = BN_new()) == NULL || (order = BN_new()) == NULL || - (cofactor = BN_new()) == NULL) - { - reason = ERR_R_MALLOC_FAILURE; - goto err; - } +{ + unsigned char *buffer = NULL; + size_t buf_len = 0, i; + int ret = 0, reason = ERR_R_BIO_LIB; + BN_CTX *ctx = NULL; + const EC_POINT *point = NULL; + BIGNUM *p = NULL, *a = NULL, *b = NULL, *gen = NULL, + *order = NULL, *cofactor = NULL; + const unsigned char *seed; + size_t seed_len = 0; + + static const char *gen_compressed = "Generator (compressed):"; + static const char *gen_uncompressed = "Generator (uncompressed):"; + static const char *gen_hybrid = "Generator (hybrid):"; + + if (!x) { + reason = ERR_R_PASSED_NULL_PARAMETER; + goto err; + } + + ctx = BN_CTX_new(); + if (ctx == NULL) { + reason = ERR_R_MALLOC_FAILURE; + goto err; + } + + if (EC_GROUP_get_asn1_flag(x)) { + /* the curve parameter are given by an asn1 OID */ + int nid; + + if (!BIO_indent(bp, off, 128)) + goto err; + + nid = EC_GROUP_get_curve_name(x); + if (nid == 0) + goto err; + + if (BIO_printf(bp, "ASN1 OID: %s", OBJ_nid2sn(nid)) <= 0) + goto err; + if (BIO_printf(bp, "\n") <= 0) + goto err; + } else { + /* explicit parameters */ + int is_char_two = 0; + point_conversion_form_t form; + int tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(x)); + + if (tmp_nid == NID_X9_62_characteristic_two_field) + is_char_two = 1; + + if ((p = BN_new()) == NULL || (a = BN_new()) == NULL || + (b = BN_new()) == NULL || (order = BN_new()) == NULL || + (cofactor = BN_new()) == NULL) { + reason = ERR_R_MALLOC_FAILURE; + goto err; + } #ifndef OPENSSL_NO_EC2M - if (is_char_two) - { - if (!EC_GROUP_get_curve_GF2m(x, p, a, b, ctx)) - { - reason = ERR_R_EC_LIB; - goto err; - } - } - else /* prime field */ + if (is_char_two) { + if (!EC_GROUP_get_curve_GF2m(x, p, a, b, ctx)) { + reason = ERR_R_EC_LIB; + goto err; + } + } else /* prime field */ #endif - { - if (!EC_GROUP_get_curve_GFp(x, p, a, b, ctx)) - { - reason = ERR_R_EC_LIB; - goto err; - } - } - - if ((point = EC_GROUP_get0_generator(x)) == NULL) - { - reason = ERR_R_EC_LIB; - goto err; - } - if (!EC_GROUP_get_order(x, order, NULL) || - !EC_GROUP_get_cofactor(x, cofactor, NULL)) - { - reason = ERR_R_EC_LIB; - goto err; - } - - form = EC_GROUP_get_point_conversion_form(x); - - if ((gen = EC_POINT_point2bn(x, point, - form, NULL, ctx)) == NULL) - { - reason = ERR_R_EC_LIB; - goto err; - } - - buf_len = (size_t)BN_num_bytes(p); - if (buf_len < (i = (size_t)BN_num_bytes(a))) - buf_len = i; - if (buf_len < (i = (size_t)BN_num_bytes(b))) - buf_len = i; - if (buf_len < (i = (size_t)BN_num_bytes(gen))) - buf_len = i; - if (buf_len < (i = (size_t)BN_num_bytes(order))) - buf_len = i; - if (buf_len < (i = (size_t)BN_num_bytes(cofactor))) - buf_len = i; - - if ((seed = EC_GROUP_get0_seed(x)) != NULL) - seed_len = EC_GROUP_get_seed_len(x); - - buf_len += 10; - if ((buffer = OPENSSL_malloc(buf_len)) == NULL) - { - reason = ERR_R_MALLOC_FAILURE; - goto err; - } - - if (!BIO_indent(bp, off, 128)) - goto err; - - /* print the 'short name' of the field type */ - if (BIO_printf(bp, "Field Type: %s\n", OBJ_nid2sn(tmp_nid)) - <= 0) - goto err; - - if (is_char_two) - { - /* print the 'short name' of the base type OID */ - int basis_type = EC_GROUP_get_basis_type(x); - if (basis_type == 0) - goto err; - - if (!BIO_indent(bp, off, 128)) - goto err; - - if (BIO_printf(bp, "Basis Type: %s\n", - OBJ_nid2sn(basis_type)) <= 0) - goto err; - - /* print the polynomial */ - if ((p != NULL) && !ASN1_bn_print(bp, "Polynomial:", p, buffer, - off)) - goto err; - } - else - { - if ((p != NULL) && !ASN1_bn_print(bp, "Prime:", p, buffer,off)) - goto err; - } - if ((a != NULL) && !ASN1_bn_print(bp, "A: ", a, buffer, off)) - goto err; - if ((b != NULL) && !ASN1_bn_print(bp, "B: ", b, buffer, off)) - goto err; - if (form == POINT_CONVERSION_COMPRESSED) - { - if ((gen != NULL) && !ASN1_bn_print(bp, gen_compressed, gen, - buffer, off)) - goto err; - } - else if (form == POINT_CONVERSION_UNCOMPRESSED) - { - if ((gen != NULL) && !ASN1_bn_print(bp, gen_uncompressed, gen, - buffer, off)) - goto err; - } - else /* form == POINT_CONVERSION_HYBRID */ - { - if ((gen != NULL) && !ASN1_bn_print(bp, gen_hybrid, gen, - buffer, off)) - goto err; - } - if ((order != NULL) && !ASN1_bn_print(bp, "Order: ", order, - buffer, off)) goto err; - if ((cofactor != NULL) && !ASN1_bn_print(bp, "Cofactor: ", cofactor, - buffer, off)) goto err; - if (seed && !print_bin(bp, "Seed:", seed, seed_len, off)) - goto err; - } - ret=1; -err: - if (!ret) - ECerr(EC_F_ECPKPARAMETERS_PRINT, reason); - if (p) - BN_free(p); - if (a) - BN_free(a); - if (b) - BN_free(b); - if (gen) - BN_free(gen); - if (order) - BN_free(order); - if (cofactor) - BN_free(cofactor); - if (ctx) - BN_CTX_free(ctx); - if (buffer != NULL) - OPENSSL_free(buffer); - return(ret); - } + { + if (!EC_GROUP_get_curve_GFp(x, p, a, b, ctx)) { + reason = ERR_R_EC_LIB; + goto err; + } + } + + if ((point = EC_GROUP_get0_generator(x)) == NULL) { + reason = ERR_R_EC_LIB; + goto err; + } + if (!EC_GROUP_get_order(x, order, NULL) || + !EC_GROUP_get_cofactor(x, cofactor, NULL)) { + reason = ERR_R_EC_LIB; + goto err; + } + + form = EC_GROUP_get_point_conversion_form(x); + + if ((gen = EC_POINT_point2bn(x, point, form, NULL, ctx)) == NULL) { + reason = ERR_R_EC_LIB; + goto err; + } + + buf_len = (size_t)BN_num_bytes(p); + if (buf_len < (i = (size_t)BN_num_bytes(a))) + buf_len = i; + if (buf_len < (i = (size_t)BN_num_bytes(b))) + buf_len = i; + if (buf_len < (i = (size_t)BN_num_bytes(gen))) + buf_len = i; + if (buf_len < (i = (size_t)BN_num_bytes(order))) + buf_len = i; + if (buf_len < (i = (size_t)BN_num_bytes(cofactor))) + buf_len = i; + + if ((seed = EC_GROUP_get0_seed(x)) != NULL) + seed_len = EC_GROUP_get_seed_len(x); + + buf_len += 10; + if ((buffer = OPENSSL_malloc(buf_len)) == NULL) { + reason = ERR_R_MALLOC_FAILURE; + goto err; + } + + if (!BIO_indent(bp, off, 128)) + goto err; + + /* print the 'short name' of the field type */ + if (BIO_printf(bp, "Field Type: %s\n", OBJ_nid2sn(tmp_nid)) + <= 0) + goto err; + + if (is_char_two) { + /* print the 'short name' of the base type OID */ + int basis_type = EC_GROUP_get_basis_type(x); + if (basis_type == 0) + goto err; + + if (!BIO_indent(bp, off, 128)) + goto err; + + if (BIO_printf(bp, "Basis Type: %s\n", + OBJ_nid2sn(basis_type)) <= 0) + goto err; + + /* print the polynomial */ + if ((p != NULL) && !ASN1_bn_print(bp, "Polynomial:", p, buffer, + off)) + goto err; + } else { + if ((p != NULL) && !ASN1_bn_print(bp, "Prime:", p, buffer, off)) + goto err; + } + if ((a != NULL) && !ASN1_bn_print(bp, "A: ", a, buffer, off)) + goto err; + if ((b != NULL) && !ASN1_bn_print(bp, "B: ", b, buffer, off)) + goto err; + if (form == POINT_CONVERSION_COMPRESSED) { + if ((gen != NULL) && !ASN1_bn_print(bp, gen_compressed, gen, + buffer, off)) + goto err; + } else if (form == POINT_CONVERSION_UNCOMPRESSED) { + if ((gen != NULL) && !ASN1_bn_print(bp, gen_uncompressed, gen, + buffer, off)) + goto err; + } else { /* form == POINT_CONVERSION_HYBRID */ + + if ((gen != NULL) && !ASN1_bn_print(bp, gen_hybrid, gen, + buffer, off)) + goto err; + } + if ((order != NULL) && !ASN1_bn_print(bp, "Order: ", order, + buffer, off)) + goto err; + if ((cofactor != NULL) && !ASN1_bn_print(bp, "Cofactor: ", cofactor, + buffer, off)) + goto err; + if (seed && !print_bin(bp, "Seed:", seed, seed_len, off)) + goto err; + } + ret = 1; + err: + if (!ret) + ECerr(EC_F_ECPKPARAMETERS_PRINT, reason); + if (p) + BN_free(p); + if (a) + BN_free(a); + if (b) + BN_free(b); + if (gen) + BN_free(gen); + if (order) + BN_free(order); + if (cofactor) + BN_free(cofactor); + if (ctx) + BN_CTX_free(ctx); + if (buffer != NULL) + OPENSSL_free(buffer); + return (ret); +} static int print_bin(BIO *fp, const char *name, const unsigned char *buf, - size_t len, int off) - { - size_t i; - char str[128]; - - if (buf == NULL) - return 1; - if (off) - { - if (off > 128) - off=128; - memset(str,' ',off); - if (BIO_write(fp, str, off) <= 0) - return 0; - } - - if (BIO_printf(fp,"%s", name) <= 0) - return 0; - - for (i=0; i<len; i++) - { - if ((i%15) == 0) - { - str[0]='\n'; - memset(&(str[1]),' ',off+4); - if (BIO_write(fp, str, off+1+4) <= 0) - return 0; - } - if (BIO_printf(fp,"%02x%s",buf[i],((i+1) == len)?"":":") <= 0) - return 0; - } - if (BIO_write(fp,"\n",1) <= 0) - return 0; - - return 1; - } + size_t len, int off) +{ + size_t i; + char str[128]; + + if (buf == NULL) + return 1; + if (off) { + if (off > 128) + off = 128; + memset(str, ' ', off); + if (BIO_write(fp, str, off) <= 0) + return 0; + } + + if (BIO_printf(fp, "%s", name) <= 0) + return 0; + + for (i = 0; i < len; i++) { + if ((i % 15) == 0) { + str[0] = '\n'; + memset(&(str[1]), ' ', off + 4); + if (BIO_write(fp, str, off + 1 + 4) <= 0) + return 0; + } + if (BIO_printf(fp, "%02x%s", buf[i], ((i + 1) == len) ? "" : ":") <= + 0) + return 0; + } + if (BIO_write(fp, "\n", 1) <= 0) + return 0; + + return 1; +} diff --git a/openssl/crypto/ec/ecp_mont.c b/openssl/crypto/ec/ecp_mont.c index 3c5ec1965..b2de7faea 100644 --- a/openssl/crypto/ec/ecp_mont.c +++ b/openssl/crypto/ec/ecp_mont.c @@ -10,7 +10,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -64,260 +64,245 @@ #include <openssl/err.h> #ifdef OPENSSL_FIPS -#include <openssl/fips.h> +# include <openssl/fips.h> #endif #include "ec_lcl.h" - const EC_METHOD *EC_GFp_mont_method(void) - { - static const EC_METHOD ret = { - EC_FLAGS_DEFAULT_OCT, - NID_X9_62_prime_field, - ec_GFp_mont_group_init, - ec_GFp_mont_group_finish, - ec_GFp_mont_group_clear_finish, - ec_GFp_mont_group_copy, - ec_GFp_mont_group_set_curve, - ec_GFp_simple_group_get_curve, - ec_GFp_simple_group_get_degree, - ec_GFp_simple_group_check_discriminant, - ec_GFp_simple_point_init, - ec_GFp_simple_point_finish, - ec_GFp_simple_point_clear_finish, - ec_GFp_simple_point_copy, - ec_GFp_simple_point_set_to_infinity, - ec_GFp_simple_set_Jprojective_coordinates_GFp, - ec_GFp_simple_get_Jprojective_coordinates_GFp, - ec_GFp_simple_point_set_affine_coordinates, - ec_GFp_simple_point_get_affine_coordinates, - 0,0,0, - ec_GFp_simple_add, - ec_GFp_simple_dbl, - ec_GFp_simple_invert, - 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_mont_field_mul, - ec_GFp_mont_field_sqr, - 0 /* field_div */, - ec_GFp_mont_field_encode, - ec_GFp_mont_field_decode, - ec_GFp_mont_field_set_to_one }; +{ + static const EC_METHOD ret = { + EC_FLAGS_DEFAULT_OCT, + NID_X9_62_prime_field, + ec_GFp_mont_group_init, + ec_GFp_mont_group_finish, + ec_GFp_mont_group_clear_finish, + ec_GFp_mont_group_copy, + ec_GFp_mont_group_set_curve, + ec_GFp_simple_group_get_curve, + ec_GFp_simple_group_get_degree, + ec_GFp_simple_group_check_discriminant, + ec_GFp_simple_point_init, + ec_GFp_simple_point_finish, + ec_GFp_simple_point_clear_finish, + ec_GFp_simple_point_copy, + ec_GFp_simple_point_set_to_infinity, + ec_GFp_simple_set_Jprojective_coordinates_GFp, + ec_GFp_simple_get_Jprojective_coordinates_GFp, + ec_GFp_simple_point_set_affine_coordinates, + ec_GFp_simple_point_get_affine_coordinates, + 0, 0, 0, + ec_GFp_simple_add, + ec_GFp_simple_dbl, + ec_GFp_simple_invert, + 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_mont_field_mul, + ec_GFp_mont_field_sqr, + 0 /* field_div */ , + ec_GFp_mont_field_encode, + ec_GFp_mont_field_decode, + ec_GFp_mont_field_set_to_one + }; #ifdef OPENSSL_FIPS - if (FIPS_mode()) - return fips_ec_gfp_mont_method(); + if (FIPS_mode()) + return fips_ec_gfp_mont_method(); #endif - return &ret; - } - + return &ret; +} int ec_GFp_mont_group_init(EC_GROUP *group) - { - int ok; - - ok = ec_GFp_simple_group_init(group); - group->field_data1 = NULL; - group->field_data2 = NULL; - return ok; - } +{ + int ok; + ok = ec_GFp_simple_group_init(group); + group->field_data1 = NULL; + group->field_data2 = NULL; + return ok; +} void ec_GFp_mont_group_finish(EC_GROUP *group) - { - if (group->field_data1 != NULL) - { - BN_MONT_CTX_free(group->field_data1); - group->field_data1 = NULL; - } - if (group->field_data2 != NULL) - { - BN_free(group->field_data2); - group->field_data2 = NULL; - } - ec_GFp_simple_group_finish(group); - } - +{ + if (group->field_data1 != NULL) { + BN_MONT_CTX_free(group->field_data1); + group->field_data1 = NULL; + } + if (group->field_data2 != NULL) { + BN_free(group->field_data2); + group->field_data2 = NULL; + } + ec_GFp_simple_group_finish(group); +} void ec_GFp_mont_group_clear_finish(EC_GROUP *group) - { - if (group->field_data1 != NULL) - { - BN_MONT_CTX_free(group->field_data1); - group->field_data1 = NULL; - } - if (group->field_data2 != NULL) - { - BN_clear_free(group->field_data2); - group->field_data2 = NULL; - } - ec_GFp_simple_group_clear_finish(group); - } - +{ + if (group->field_data1 != NULL) { + BN_MONT_CTX_free(group->field_data1); + group->field_data1 = NULL; + } + if (group->field_data2 != NULL) { + BN_clear_free(group->field_data2); + group->field_data2 = NULL; + } + ec_GFp_simple_group_clear_finish(group); +} int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src) - { - if (dest->field_data1 != NULL) - { - BN_MONT_CTX_free(dest->field_data1); - dest->field_data1 = NULL; - } - if (dest->field_data2 != NULL) - { - BN_clear_free(dest->field_data2); - dest->field_data2 = NULL; - } - - if (!ec_GFp_simple_group_copy(dest, src)) return 0; - - if (src->field_data1 != NULL) - { - dest->field_data1 = BN_MONT_CTX_new(); - if (dest->field_data1 == NULL) return 0; - if (!BN_MONT_CTX_copy(dest->field_data1, src->field_data1)) goto err; - } - if (src->field_data2 != NULL) - { - dest->field_data2 = BN_dup(src->field_data2); - if (dest->field_data2 == NULL) goto err; - } - - return 1; +{ + if (dest->field_data1 != NULL) { + BN_MONT_CTX_free(dest->field_data1); + dest->field_data1 = NULL; + } + if (dest->field_data2 != NULL) { + BN_clear_free(dest->field_data2); + dest->field_data2 = NULL; + } + + if (!ec_GFp_simple_group_copy(dest, src)) + return 0; + + if (src->field_data1 != NULL) { + dest->field_data1 = BN_MONT_CTX_new(); + if (dest->field_data1 == NULL) + return 0; + if (!BN_MONT_CTX_copy(dest->field_data1, src->field_data1)) + goto err; + } + if (src->field_data2 != NULL) { + dest->field_data2 = BN_dup(src->field_data2); + if (dest->field_data2 == NULL) + goto err; + } + + return 1; err: - if (dest->field_data1 != NULL) - { - BN_MONT_CTX_free(dest->field_data1); - dest->field_data1 = NULL; - } - return 0; - } - - -int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) - { - BN_CTX *new_ctx = NULL; - BN_MONT_CTX *mont = NULL; - BIGNUM *one = NULL; - int ret = 0; - - if (group->field_data1 != NULL) - { - BN_MONT_CTX_free(group->field_data1); - group->field_data1 = NULL; - } - if (group->field_data2 != NULL) - { - BN_free(group->field_data2); - group->field_data2 = NULL; - } - - if (ctx == NULL) - { - ctx = new_ctx = BN_CTX_new(); - if (ctx == NULL) - return 0; - } - - mont = BN_MONT_CTX_new(); - if (mont == NULL) goto err; - if (!BN_MONT_CTX_set(mont, p, ctx)) - { - ECerr(EC_F_EC_GFP_MONT_GROUP_SET_CURVE, ERR_R_BN_LIB); - goto err; - } - one = BN_new(); - if (one == NULL) goto err; - if (!BN_to_montgomery(one, BN_value_one(), mont, ctx)) goto err; - - group->field_data1 = mont; - mont = NULL; - group->field_data2 = one; - one = NULL; - - ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); - - if (!ret) - { - BN_MONT_CTX_free(group->field_data1); - group->field_data1 = NULL; - BN_free(group->field_data2); - group->field_data2 = NULL; - } + if (dest->field_data1 != NULL) { + BN_MONT_CTX_free(dest->field_data1); + dest->field_data1 = NULL; + } + return 0; +} + +int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) +{ + BN_CTX *new_ctx = NULL; + BN_MONT_CTX *mont = NULL; + BIGNUM *one = NULL; + int ret = 0; + + if (group->field_data1 != NULL) { + BN_MONT_CTX_free(group->field_data1); + group->field_data1 = NULL; + } + if (group->field_data2 != NULL) { + BN_free(group->field_data2); + group->field_data2 = NULL; + } + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + mont = BN_MONT_CTX_new(); + if (mont == NULL) + goto err; + if (!BN_MONT_CTX_set(mont, p, ctx)) { + ECerr(EC_F_EC_GFP_MONT_GROUP_SET_CURVE, ERR_R_BN_LIB); + goto err; + } + one = BN_new(); + if (one == NULL) + goto err; + if (!BN_to_montgomery(one, BN_value_one(), mont, ctx)) + goto err; + + group->field_data1 = mont; + mont = NULL; + group->field_data2 = one; + one = NULL; + + ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); + + if (!ret) { + BN_MONT_CTX_free(group->field_data1); + group->field_data1 = NULL; + BN_free(group->field_data2); + group->field_data2 = NULL; + } err: - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - if (mont != NULL) - BN_MONT_CTX_free(mont); - return ret; - } - - -int ec_GFp_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) - { - if (group->field_data1 == NULL) - { - ECerr(EC_F_EC_GFP_MONT_FIELD_MUL, EC_R_NOT_INITIALIZED); - return 0; - } - - return BN_mod_mul_montgomery(r, a, b, group->field_data1, ctx); - } - - -int ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) - { - if (group->field_data1 == NULL) - { - ECerr(EC_F_EC_GFP_MONT_FIELD_SQR, EC_R_NOT_INITIALIZED); - return 0; - } - - return BN_mod_mul_montgomery(r, a, a, group->field_data1, ctx); - } - - -int ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) - { - if (group->field_data1 == NULL) - { - ECerr(EC_F_EC_GFP_MONT_FIELD_ENCODE, EC_R_NOT_INITIALIZED); - return 0; - } - - return BN_to_montgomery(r, a, (BN_MONT_CTX *)group->field_data1, ctx); - } - - -int ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) - { - if (group->field_data1 == NULL) - { - ECerr(EC_F_EC_GFP_MONT_FIELD_DECODE, EC_R_NOT_INITIALIZED); - return 0; - } - - return BN_from_montgomery(r, a, group->field_data1, ctx); - } - - -int ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r, BN_CTX *ctx) - { - if (group->field_data2 == NULL) - { - ECerr(EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE, EC_R_NOT_INITIALIZED); - return 0; - } - - if (!BN_copy(r, group->field_data2)) return 0; - return 1; - } + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + if (mont != NULL) + BN_MONT_CTX_free(mont); + return ret; +} + +int ec_GFp_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx) +{ + if (group->field_data1 == NULL) { + ECerr(EC_F_EC_GFP_MONT_FIELD_MUL, EC_R_NOT_INITIALIZED); + return 0; + } + + return BN_mod_mul_montgomery(r, a, b, group->field_data1, ctx); +} + +int ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + BN_CTX *ctx) +{ + if (group->field_data1 == NULL) { + ECerr(EC_F_EC_GFP_MONT_FIELD_SQR, EC_R_NOT_INITIALIZED); + return 0; + } + + return BN_mod_mul_montgomery(r, a, a, group->field_data1, ctx); +} + +int ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r, + const BIGNUM *a, BN_CTX *ctx) +{ + if (group->field_data1 == NULL) { + ECerr(EC_F_EC_GFP_MONT_FIELD_ENCODE, EC_R_NOT_INITIALIZED); + return 0; + } + + return BN_to_montgomery(r, a, (BN_MONT_CTX *)group->field_data1, ctx); +} + +int ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, + const BIGNUM *a, BN_CTX *ctx) +{ + if (group->field_data1 == NULL) { + ECerr(EC_F_EC_GFP_MONT_FIELD_DECODE, EC_R_NOT_INITIALIZED); + return 0; + } + + return BN_from_montgomery(r, a, group->field_data1, ctx); +} + +int ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r, + BN_CTX *ctx) +{ + if (group->field_data2 == NULL) { + ECerr(EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE, EC_R_NOT_INITIALIZED); + return 0; + } + + if (!BN_copy(r, group->field_data2)) + return 0; + return 1; +} diff --git a/openssl/crypto/ec/ecp_nist.c b/openssl/crypto/ec/ecp_nist.c index db3b99e06..3944e2493 100644 --- a/openssl/crypto/ec/ecp_nist.c +++ b/openssl/crypto/ec/ecp_nist.c @@ -10,7 +10,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -68,151 +68,153 @@ #include "ec_lcl.h" #ifdef OPENSSL_FIPS -#include <openssl/fips.h> +# include <openssl/fips.h> #endif const EC_METHOD *EC_GFp_nist_method(void) - { - static const EC_METHOD ret = { - EC_FLAGS_DEFAULT_OCT, - NID_X9_62_prime_field, - ec_GFp_simple_group_init, - ec_GFp_simple_group_finish, - ec_GFp_simple_group_clear_finish, - ec_GFp_nist_group_copy, - ec_GFp_nist_group_set_curve, - ec_GFp_simple_group_get_curve, - ec_GFp_simple_group_get_degree, - ec_GFp_simple_group_check_discriminant, - ec_GFp_simple_point_init, - ec_GFp_simple_point_finish, - ec_GFp_simple_point_clear_finish, - ec_GFp_simple_point_copy, - ec_GFp_simple_point_set_to_infinity, - ec_GFp_simple_set_Jprojective_coordinates_GFp, - ec_GFp_simple_get_Jprojective_coordinates_GFp, - ec_GFp_simple_point_set_affine_coordinates, - ec_GFp_simple_point_get_affine_coordinates, - 0,0,0, - ec_GFp_simple_add, - ec_GFp_simple_dbl, - ec_GFp_simple_invert, - 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_nist_field_mul, - ec_GFp_nist_field_sqr, - 0 /* field_div */, - 0 /* field_encode */, - 0 /* field_decode */, - 0 /* field_set_to_one */ }; +{ + static const EC_METHOD ret = { + EC_FLAGS_DEFAULT_OCT, + NID_X9_62_prime_field, + ec_GFp_simple_group_init, + ec_GFp_simple_group_finish, + ec_GFp_simple_group_clear_finish, + ec_GFp_nist_group_copy, + ec_GFp_nist_group_set_curve, + ec_GFp_simple_group_get_curve, + ec_GFp_simple_group_get_degree, + ec_GFp_simple_group_check_discriminant, + ec_GFp_simple_point_init, + ec_GFp_simple_point_finish, + ec_GFp_simple_point_clear_finish, + ec_GFp_simple_point_copy, + ec_GFp_simple_point_set_to_infinity, + ec_GFp_simple_set_Jprojective_coordinates_GFp, + ec_GFp_simple_get_Jprojective_coordinates_GFp, + ec_GFp_simple_point_set_affine_coordinates, + ec_GFp_simple_point_get_affine_coordinates, + 0, 0, 0, + ec_GFp_simple_add, + ec_GFp_simple_dbl, + ec_GFp_simple_invert, + 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_nist_field_mul, + ec_GFp_nist_field_sqr, + 0 /* field_div */ , + 0 /* field_encode */ , + 0 /* field_decode */ , + 0 /* field_set_to_one */ + }; #ifdef OPENSSL_FIPS - if (FIPS_mode()) - return fips_ec_gfp_nist_method(); + if (FIPS_mode()) + return fips_ec_gfp_nist_method(); #endif - return &ret; - } + return &ret; +} int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src) - { - dest->field_mod_func = src->field_mod_func; +{ + dest->field_mod_func = src->field_mod_func; - return ec_GFp_simple_group_copy(dest, src); - } + return ec_GFp_simple_group_copy(dest, src); +} int ec_GFp_nist_group_set_curve(EC_GROUP *group, const BIGNUM *p, - const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) - { - int ret = 0; - BN_CTX *new_ctx = NULL; - BIGNUM *tmp_bn; - - if (ctx == NULL) - if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0; - - BN_CTX_start(ctx); - if ((tmp_bn = BN_CTX_get(ctx)) == NULL) goto err; - - if (BN_ucmp(BN_get0_nist_prime_192(), p) == 0) - group->field_mod_func = BN_nist_mod_192; - else if (BN_ucmp(BN_get0_nist_prime_224(), p) == 0) - group->field_mod_func = BN_nist_mod_224; - else if (BN_ucmp(BN_get0_nist_prime_256(), p) == 0) - group->field_mod_func = BN_nist_mod_256; - else if (BN_ucmp(BN_get0_nist_prime_384(), p) == 0) - group->field_mod_func = BN_nist_mod_384; - else if (BN_ucmp(BN_get0_nist_prime_521(), p) == 0) - group->field_mod_func = BN_nist_mod_521; - else - { - ECerr(EC_F_EC_GFP_NIST_GROUP_SET_CURVE, EC_R_NOT_A_NIST_PRIME); - goto err; - } - - ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); + const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) +{ + int ret = 0; + BN_CTX *new_ctx = NULL; + BIGNUM *tmp_bn; + + if (ctx == NULL) + if ((ctx = new_ctx = BN_CTX_new()) == NULL) + return 0; + + BN_CTX_start(ctx); + if ((tmp_bn = BN_CTX_get(ctx)) == NULL) + goto err; + + if (BN_ucmp(BN_get0_nist_prime_192(), p) == 0) + group->field_mod_func = BN_nist_mod_192; + else if (BN_ucmp(BN_get0_nist_prime_224(), p) == 0) + group->field_mod_func = BN_nist_mod_224; + else if (BN_ucmp(BN_get0_nist_prime_256(), p) == 0) + group->field_mod_func = BN_nist_mod_256; + else if (BN_ucmp(BN_get0_nist_prime_384(), p) == 0) + group->field_mod_func = BN_nist_mod_384; + else if (BN_ucmp(BN_get0_nist_prime_521(), p) == 0) + group->field_mod_func = BN_nist_mod_521; + else { + ECerr(EC_F_EC_GFP_NIST_GROUP_SET_CURVE, EC_R_NOT_A_NIST_PRIME); + goto err; + } + + ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); err: - BN_CTX_end(ctx); - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - return ret; - } - + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; +} int ec_GFp_nist_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, - const BIGNUM *b, BN_CTX *ctx) - { - int ret=0; - BN_CTX *ctx_new=NULL; - - if (!group || !r || !a || !b) - { - ECerr(EC_F_EC_GFP_NIST_FIELD_MUL, ERR_R_PASSED_NULL_PARAMETER); - goto err; - } - if (!ctx) - if ((ctx_new = ctx = BN_CTX_new()) == NULL) goto err; - - if (!BN_mul(r, a, b, ctx)) goto err; - if (!group->field_mod_func(r, r, &group->field, ctx)) - goto err; - - ret=1; -err: - if (ctx_new) - BN_CTX_free(ctx_new); - return ret; - } - + const BIGNUM *b, BN_CTX *ctx) +{ + int ret = 0; + BN_CTX *ctx_new = NULL; + + if (!group || !r || !a || !b) { + ECerr(EC_F_EC_GFP_NIST_FIELD_MUL, ERR_R_PASSED_NULL_PARAMETER); + goto err; + } + if (!ctx) + if ((ctx_new = ctx = BN_CTX_new()) == NULL) + goto err; + + if (!BN_mul(r, a, b, ctx)) + goto err; + if (!group->field_mod_func(r, r, &group->field, ctx)) + goto err; + + ret = 1; + err: + if (ctx_new) + BN_CTX_free(ctx_new); + return ret; +} int ec_GFp_nist_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, - BN_CTX *ctx) - { - int ret=0; - BN_CTX *ctx_new=NULL; - - if (!group || !r || !a) - { - ECerr(EC_F_EC_GFP_NIST_FIELD_SQR, EC_R_PASSED_NULL_PARAMETER); - goto err; - } - if (!ctx) - if ((ctx_new = ctx = BN_CTX_new()) == NULL) goto err; - - if (!BN_sqr(r, a, ctx)) goto err; - if (!group->field_mod_func(r, r, &group->field, ctx)) - goto err; - - ret=1; -err: - if (ctx_new) - BN_CTX_free(ctx_new); - return ret; - } + BN_CTX *ctx) +{ + int ret = 0; + BN_CTX *ctx_new = NULL; + + if (!group || !r || !a) { + ECerr(EC_F_EC_GFP_NIST_FIELD_SQR, EC_R_PASSED_NULL_PARAMETER); + goto err; + } + if (!ctx) + if ((ctx_new = ctx = BN_CTX_new()) == NULL) + goto err; + + if (!BN_sqr(r, a, ctx)) + goto err; + if (!group->field_mod_func(r, r, &group->field, ctx)) + goto err; + + ret = 1; + err: + if (ctx_new) + BN_CTX_free(ctx_new); + return ret; +} diff --git a/openssl/crypto/ec/ecp_nistp224.c b/openssl/crypto/ec/ecp_nistp224.c index b5ff56c25..ed09f97ad 100644 --- a/openssl/crypto/ec/ecp_nistp224.c +++ b/openssl/crypto/ec/ecp_nistp224.c @@ -28,30 +28,31 @@ #include <openssl/opensslconf.h> #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 -#ifndef OPENSSL_SYS_VMS -#include <stdint.h> -#else -#include <inttypes.h> -#endif +# ifndef OPENSSL_SYS_VMS +# include <stdint.h> +# else +# include <inttypes.h> +# endif -#include <string.h> -#include <openssl/err.h> -#include "ec_lcl.h" +# include <string.h> +# include <openssl/err.h> +# include "ec_lcl.h" -#if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +# if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) /* even with gcc, the typedef won't work for 32-bit platforms */ - typedef __uint128_t uint128_t; /* nonstandard; implemented by gcc on 64-bit platforms */ -#else - #error "Need GCC 3.1 or later to define type uint128_t" -#endif +typedef __uint128_t uint128_t; /* nonstandard; implemented by gcc on 64-bit + * platforms */ +# else +# error "Need GCC 3.1 or later to define type uint128_t" +# endif typedef uint8_t u8; typedef uint64_t u64; typedef int64_t s64; - /******************************************************************************/ -/* INTERNAL REPRESENTATION OF FIELD ELEMENTS +/*- + * INTERNAL REPRESENTATION OF FIELD ELEMENTS * * Field elements are represented as a_0 + 2^56*a_1 + 2^112*a_2 + 2^168*a_3 * using 64-bit coefficients called 'limbs', @@ -75,31 +76,33 @@ typedef uint128_t widelimb; typedef limb felem[4]; typedef widelimb widefelem[7]; -/* Field element represented as a byte arrary. - * 28*8 = 224 bits is also the group order size for the elliptic curve, - * and we also use this type for scalars for point multiplication. - */ +/* + * Field element represented as a byte arrary. 28*8 = 224 bits is also the + * group order size for the elliptic curve, and we also use this type for + * scalars for point multiplication. + */ typedef u8 felem_bytearray[28]; static const felem_bytearray nistp224_curve_params[5] = { - {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, - {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE}, - {0xB4,0x05,0x0A,0x85,0x0C,0x04,0xB3,0xAB,0xF5,0x41, /* b */ - 0x32,0x56,0x50,0x44,0xB0,0xB7,0xD7,0xBF,0xD8,0xBA, - 0x27,0x0B,0x39,0x43,0x23,0x55,0xFF,0xB4}, - {0xB7,0x0E,0x0C,0xBD,0x6B,0xB4,0xBF,0x7F,0x32,0x13, /* x */ - 0x90,0xB9,0x4A,0x03,0xC1,0xD3,0x56,0xC2,0x11,0x22, - 0x34,0x32,0x80,0xD6,0x11,0x5C,0x1D,0x21}, - {0xbd,0x37,0x63,0x88,0xb5,0xf7,0x23,0xfb,0x4c,0x22, /* y */ - 0xdf,0xe6,0xcd,0x43,0x75,0xa0,0x5a,0x07,0x47,0x64, - 0x44,0xd5,0x81,0x99,0x85,0x00,0x7e,0x34} + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* p */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* a */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE}, + {0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, /* b */ + 0x32, 0x56, 0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, + 0x27, 0x0B, 0x39, 0x43, 0x23, 0x55, 0xFF, 0xB4}, + {0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, /* x */ + 0x90, 0xB9, 0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, + 0x34, 0x32, 0x80, 0xD6, 0x11, 0x5C, 0x1D, 0x21}, + {0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, /* y */ + 0xdf, 0xe6, 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, + 0x44, 0xd5, 0x81, 0x99, 0x85, 0x00, 0x7e, 0x34} }; -/* Precomputed multiples of the standard generator +/*- + * Precomputed multiples of the standard generator * Points are given in coordinates (X, Y, Z) where Z normally is 1 * (0 for the point at infinity). * For each field element, slice a_0 is word 0, etc. @@ -129,222 +132,253 @@ static const felem_bytearray nistp224_curve_params[5] = { * locations when doing simple scalar multiplies against the base point, * and then another four locations using the second 16 elements. */ -static const felem gmul[2][16][3] = -{{{{0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}}, - {{0x3280d6115c1d21, 0xc1d356c2112234, 0x7f321390b94a03, 0xb70e0cbd6bb4bf}, - {0xd5819985007e34, 0x75a05a07476444, 0xfb4c22dfe6cd43, 0xbd376388b5f723}, - {1, 0, 0, 0}}, - {{0xfd9675666ebbe9, 0xbca7664d40ce5e, 0x2242df8d8a2a43, 0x1f49bbb0f99bc5}, - {0x29e0b892dc9c43, 0xece8608436e662, 0xdc858f185310d0, 0x9812dd4eb8d321}, - {1, 0, 0, 0}}, - {{0x6d3e678d5d8eb8, 0x559eed1cb362f1, 0x16e9a3bbce8a3f, 0xeedcccd8c2a748}, - {0xf19f90ed50266d, 0xabf2b4bf65f9df, 0x313865468fafec, 0x5cb379ba910a17}, - {1, 0, 0, 0}}, - {{0x0641966cab26e3, 0x91fb2991fab0a0, 0xefec27a4e13a0b, 0x0499aa8a5f8ebe}, - {0x7510407766af5d, 0x84d929610d5450, 0x81d77aae82f706, 0x6916f6d4338c5b}, - {1, 0, 0, 0}}, - {{0xea95ac3b1f15c6, 0x086000905e82d4, 0xdd323ae4d1c8b1, 0x932b56be7685a3}, - {0x9ef93dea25dbbf, 0x41665960f390f0, 0xfdec76dbe2a8a7, 0x523e80f019062a}, - {1, 0, 0, 0}}, - {{0x822fdd26732c73, 0xa01c83531b5d0f, 0x363f37347c1ba4, 0xc391b45c84725c}, - {0xbbd5e1b2d6ad24, 0xddfbcde19dfaec, 0xc393da7e222a7f, 0x1efb7890ede244}, - {1, 0, 0, 0}}, - {{0x4c9e90ca217da1, 0xd11beca79159bb, 0xff8d33c2c98b7c, 0x2610b39409f849}, - {0x44d1352ac64da0, 0xcdbb7b2c46b4fb, 0x966c079b753c89, 0xfe67e4e820b112}, - {1, 0, 0, 0}}, - {{0xe28cae2df5312d, 0xc71b61d16f5c6e, 0x79b7619a3e7c4c, 0x05c73240899b47}, - {0x9f7f6382c73e3a, 0x18615165c56bda, 0x641fab2116fd56, 0x72855882b08394}, - {1, 0, 0, 0}}, - {{0x0469182f161c09, 0x74a98ca8d00fb5, 0xb89da93489a3e0, 0x41c98768fb0c1d}, - {0xe5ea05fb32da81, 0x3dce9ffbca6855, 0x1cfe2d3fbf59e6, 0x0e5e03408738a7}, - {1, 0, 0, 0}}, - {{0xdab22b2333e87f, 0x4430137a5dd2f6, 0xe03ab9f738beb8, 0xcb0c5d0dc34f24}, - {0x764a7df0c8fda5, 0x185ba5c3fa2044, 0x9281d688bcbe50, 0xc40331df893881}, - {1, 0, 0, 0}}, - {{0xb89530796f0f60, 0xade92bd26909a3, 0x1a0c83fb4884da, 0x1765bf22a5a984}, - {0x772a9ee75db09e, 0x23bc6c67cec16f, 0x4c1edba8b14e2f, 0xe2a215d9611369}, - {1, 0, 0, 0}}, - {{0x571e509fb5efb3, 0xade88696410552, 0xc8ae85fada74fe, 0x6c7e4be83bbde3}, - {0xff9f51160f4652, 0xb47ce2495a6539, 0xa2946c53b582f4, 0x286d2db3ee9a60}, - {1, 0, 0, 0}}, - {{0x40bbd5081a44af, 0x0995183b13926c, 0xbcefba6f47f6d0, 0x215619e9cc0057}, - {0x8bc94d3b0df45e, 0xf11c54a3694f6f, 0x8631b93cdfe8b5, 0xe7e3f4b0982db9}, - {1, 0, 0, 0}}, - {{0xb17048ab3e1c7b, 0xac38f36ff8a1d8, 0x1c29819435d2c6, 0xc813132f4c07e9}, - {0x2891425503b11f, 0x08781030579fea, 0xf5426ba5cc9674, 0x1e28ebf18562bc}, - {1, 0, 0, 0}}, - {{0x9f31997cc864eb, 0x06cd91d28b5e4c, 0xff17036691a973, 0xf1aef351497c58}, - {0xdd1f2d600564ff, 0xdead073b1402db, 0x74a684435bd693, 0xeea7471f962558}, - {1, 0, 0, 0}}}, - {{{0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}}, - {{0x9665266dddf554, 0x9613d78b60ef2d, 0xce27a34cdba417, 0xd35ab74d6afc31}, - {0x85ccdd22deb15e, 0x2137e5783a6aab, 0xa141cffd8c93c6, 0x355a1830e90f2d}, - {1, 0, 0, 0}}, - {{0x1a494eadaade65, 0xd6da4da77fe53c, 0xe7992996abec86, 0x65c3553c6090e3}, - {0xfa610b1fb09346, 0xf1c6540b8a4aaf, 0xc51a13ccd3cbab, 0x02995b1b18c28a}, - {1, 0, 0, 0}}, - {{0x7874568e7295ef, 0x86b419fbe38d04, 0xdc0690a7550d9a, 0xd3966a44beac33}, - {0x2b7280ec29132f, 0xbeaa3b6a032df3, 0xdc7dd88ae41200, 0xd25e2513e3a100}, - {1, 0, 0, 0}}, - {{0x924857eb2efafd, 0xac2bce41223190, 0x8edaa1445553fc, 0x825800fd3562d5}, - {0x8d79148ea96621, 0x23a01c3dd9ed8d, 0xaf8b219f9416b5, 0xd8db0cc277daea}, - {1, 0, 0, 0}}, - {{0x76a9c3b1a700f0, 0xe9acd29bc7e691, 0x69212d1a6b0327, 0x6322e97fe154be}, - {0x469fc5465d62aa, 0x8d41ed18883b05, 0x1f8eae66c52b88, 0xe4fcbe9325be51}, - {1, 0, 0, 0}}, - {{0x825fdf583cac16, 0x020b857c7b023a, 0x683c17744b0165, 0x14ffd0a2daf2f1}, - {0x323b36184218f9, 0x4944ec4e3b47d4, 0xc15b3080841acf, 0x0bced4b01a28bb}, - {1, 0, 0, 0}}, - {{0x92ac22230df5c4, 0x52f33b4063eda8, 0xcb3f19870c0c93, 0x40064f2ba65233}, - {0xfe16f0924f8992, 0x012da25af5b517, 0x1a57bb24f723a6, 0x06f8bc76760def}, - {1, 0, 0, 0}}, - {{0x4a7084f7817cb9, 0xbcab0738ee9a78, 0x3ec11e11d9c326, 0xdc0fe90e0f1aae}, - {0xcf639ea5f98390, 0x5c350aa22ffb74, 0x9afae98a4047b7, 0x956ec2d617fc45}, - {1, 0, 0, 0}}, - {{0x4306d648c1be6a, 0x9247cd8bc9a462, 0xf5595e377d2f2e, 0xbd1c3caff1a52e}, - {0x045e14472409d0, 0x29f3e17078f773, 0x745a602b2d4f7d, 0x191837685cdfbb}, - {1, 0, 0, 0}}, - {{0x5b6ee254a8cb79, 0x4953433f5e7026, 0xe21faeb1d1def4, 0xc4c225785c09de}, - {0x307ce7bba1e518, 0x31b125b1036db8, 0x47e91868839e8f, 0xc765866e33b9f3}, - {1, 0, 0, 0}}, - {{0x3bfece24f96906, 0x4794da641e5093, 0xde5df64f95db26, 0x297ecd89714b05}, - {0x701bd3ebb2c3aa, 0x7073b4f53cb1d5, 0x13c5665658af16, 0x9895089d66fe58}, - {1, 0, 0, 0}}, - {{0x0fef05f78c4790, 0x2d773633b05d2e, 0x94229c3a951c94, 0xbbbd70df4911bb}, - {0xb2c6963d2c1168, 0x105f47a72b0d73, 0x9fdf6111614080, 0x7b7e94b39e67b0}, - {1, 0, 0, 0}}, - {{0xad1a7d6efbe2b3, 0xf012482c0da69d, 0x6b3bdf12438345, 0x40d7558d7aa4d9}, - {0x8a09fffb5c6d3d, 0x9a356e5d9ffd38, 0x5973f15f4f9b1c, 0xdcd5f59f63c3ea}, - {1, 0, 0, 0}}, - {{0xacf39f4c5ca7ab, 0x4c8071cc5fd737, 0xc64e3602cd1184, 0x0acd4644c9abba}, - {0x6c011a36d8bf6e, 0xfecd87ba24e32a, 0x19f6f56574fad8, 0x050b204ced9405}, - {1, 0, 0, 0}}, - {{0xed4f1cae7d9a96, 0x5ceef7ad94c40a, 0x778e4a3bf3ef9b, 0x7405783dc3b55e}, - {0x32477c61b6e8c6, 0xb46a97570f018b, 0x91176d0a7e95d1, 0x3df90fbc4c7d0e}, - {1, 0, 0, 0}}}}; +static const felem gmul[2][16][3] = { {{{0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}}, + {{0x3280d6115c1d21, 0xc1d356c2112234, + 0x7f321390b94a03, 0xb70e0cbd6bb4bf}, + {0xd5819985007e34, 0x75a05a07476444, + 0xfb4c22dfe6cd43, 0xbd376388b5f723}, + {1, 0, 0, 0}}, + {{0xfd9675666ebbe9, 0xbca7664d40ce5e, + 0x2242df8d8a2a43, 0x1f49bbb0f99bc5}, + {0x29e0b892dc9c43, 0xece8608436e662, + 0xdc858f185310d0, 0x9812dd4eb8d321}, + {1, 0, 0, 0}}, + {{0x6d3e678d5d8eb8, 0x559eed1cb362f1, + 0x16e9a3bbce8a3f, 0xeedcccd8c2a748}, + {0xf19f90ed50266d, 0xabf2b4bf65f9df, + 0x313865468fafec, 0x5cb379ba910a17}, + {1, 0, 0, 0}}, + {{0x0641966cab26e3, 0x91fb2991fab0a0, + 0xefec27a4e13a0b, 0x0499aa8a5f8ebe}, + {0x7510407766af5d, 0x84d929610d5450, + 0x81d77aae82f706, 0x6916f6d4338c5b}, + {1, 0, 0, 0}}, + {{0xea95ac3b1f15c6, 0x086000905e82d4, + 0xdd323ae4d1c8b1, 0x932b56be7685a3}, + {0x9ef93dea25dbbf, 0x41665960f390f0, + 0xfdec76dbe2a8a7, 0x523e80f019062a}, + {1, 0, 0, 0}}, + {{0x822fdd26732c73, 0xa01c83531b5d0f, + 0x363f37347c1ba4, 0xc391b45c84725c}, + {0xbbd5e1b2d6ad24, 0xddfbcde19dfaec, + 0xc393da7e222a7f, 0x1efb7890ede244}, + {1, 0, 0, 0}}, + {{0x4c9e90ca217da1, 0xd11beca79159bb, + 0xff8d33c2c98b7c, 0x2610b39409f849}, + {0x44d1352ac64da0, 0xcdbb7b2c46b4fb, + 0x966c079b753c89, 0xfe67e4e820b112}, + {1, 0, 0, 0}}, + {{0xe28cae2df5312d, 0xc71b61d16f5c6e, + 0x79b7619a3e7c4c, 0x05c73240899b47}, + {0x9f7f6382c73e3a, 0x18615165c56bda, + 0x641fab2116fd56, 0x72855882b08394}, + {1, 0, 0, 0}}, + {{0x0469182f161c09, 0x74a98ca8d00fb5, + 0xb89da93489a3e0, 0x41c98768fb0c1d}, + {0xe5ea05fb32da81, 0x3dce9ffbca6855, + 0x1cfe2d3fbf59e6, 0x0e5e03408738a7}, + {1, 0, 0, 0}}, + {{0xdab22b2333e87f, 0x4430137a5dd2f6, + 0xe03ab9f738beb8, 0xcb0c5d0dc34f24}, + {0x764a7df0c8fda5, 0x185ba5c3fa2044, + 0x9281d688bcbe50, 0xc40331df893881}, + {1, 0, 0, 0}}, + {{0xb89530796f0f60, 0xade92bd26909a3, + 0x1a0c83fb4884da, 0x1765bf22a5a984}, + {0x772a9ee75db09e, 0x23bc6c67cec16f, + 0x4c1edba8b14e2f, 0xe2a215d9611369}, + {1, 0, 0, 0}}, + {{0x571e509fb5efb3, 0xade88696410552, + 0xc8ae85fada74fe, 0x6c7e4be83bbde3}, + {0xff9f51160f4652, 0xb47ce2495a6539, + 0xa2946c53b582f4, 0x286d2db3ee9a60}, + {1, 0, 0, 0}}, + {{0x40bbd5081a44af, 0x0995183b13926c, + 0xbcefba6f47f6d0, 0x215619e9cc0057}, + {0x8bc94d3b0df45e, 0xf11c54a3694f6f, + 0x8631b93cdfe8b5, 0xe7e3f4b0982db9}, + {1, 0, 0, 0}}, + {{0xb17048ab3e1c7b, 0xac38f36ff8a1d8, + 0x1c29819435d2c6, 0xc813132f4c07e9}, + {0x2891425503b11f, 0x08781030579fea, + 0xf5426ba5cc9674, 0x1e28ebf18562bc}, + {1, 0, 0, 0}}, + {{0x9f31997cc864eb, 0x06cd91d28b5e4c, + 0xff17036691a973, 0xf1aef351497c58}, + {0xdd1f2d600564ff, 0xdead073b1402db, + 0x74a684435bd693, 0xeea7471f962558}, + {1, 0, 0, 0}}}, +{{{0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}}, + {{0x9665266dddf554, 0x9613d78b60ef2d, 0xce27a34cdba417, 0xd35ab74d6afc31}, + {0x85ccdd22deb15e, 0x2137e5783a6aab, 0xa141cffd8c93c6, 0x355a1830e90f2d}, + {1, 0, 0, 0}}, + {{0x1a494eadaade65, 0xd6da4da77fe53c, 0xe7992996abec86, 0x65c3553c6090e3}, + {0xfa610b1fb09346, 0xf1c6540b8a4aaf, 0xc51a13ccd3cbab, 0x02995b1b18c28a}, + {1, 0, 0, 0}}, + {{0x7874568e7295ef, 0x86b419fbe38d04, 0xdc0690a7550d9a, 0xd3966a44beac33}, + {0x2b7280ec29132f, 0xbeaa3b6a032df3, 0xdc7dd88ae41200, 0xd25e2513e3a100}, + {1, 0, 0, 0}}, + {{0x924857eb2efafd, 0xac2bce41223190, 0x8edaa1445553fc, 0x825800fd3562d5}, + {0x8d79148ea96621, 0x23a01c3dd9ed8d, 0xaf8b219f9416b5, 0xd8db0cc277daea}, + {1, 0, 0, 0}}, + {{0x76a9c3b1a700f0, 0xe9acd29bc7e691, 0x69212d1a6b0327, 0x6322e97fe154be}, + {0x469fc5465d62aa, 0x8d41ed18883b05, 0x1f8eae66c52b88, 0xe4fcbe9325be51}, + {1, 0, 0, 0}}, + {{0x825fdf583cac16, 0x020b857c7b023a, 0x683c17744b0165, 0x14ffd0a2daf2f1}, + {0x323b36184218f9, 0x4944ec4e3b47d4, 0xc15b3080841acf, 0x0bced4b01a28bb}, + {1, 0, 0, 0}}, + {{0x92ac22230df5c4, 0x52f33b4063eda8, 0xcb3f19870c0c93, 0x40064f2ba65233}, + {0xfe16f0924f8992, 0x012da25af5b517, 0x1a57bb24f723a6, 0x06f8bc76760def}, + {1, 0, 0, 0}}, + {{0x4a7084f7817cb9, 0xbcab0738ee9a78, 0x3ec11e11d9c326, 0xdc0fe90e0f1aae}, + {0xcf639ea5f98390, 0x5c350aa22ffb74, 0x9afae98a4047b7, 0x956ec2d617fc45}, + {1, 0, 0, 0}}, + {{0x4306d648c1be6a, 0x9247cd8bc9a462, 0xf5595e377d2f2e, 0xbd1c3caff1a52e}, + {0x045e14472409d0, 0x29f3e17078f773, 0x745a602b2d4f7d, 0x191837685cdfbb}, + {1, 0, 0, 0}}, + {{0x5b6ee254a8cb79, 0x4953433f5e7026, 0xe21faeb1d1def4, 0xc4c225785c09de}, + {0x307ce7bba1e518, 0x31b125b1036db8, 0x47e91868839e8f, 0xc765866e33b9f3}, + {1, 0, 0, 0}}, + {{0x3bfece24f96906, 0x4794da641e5093, 0xde5df64f95db26, 0x297ecd89714b05}, + {0x701bd3ebb2c3aa, 0x7073b4f53cb1d5, 0x13c5665658af16, 0x9895089d66fe58}, + {1, 0, 0, 0}}, + {{0x0fef05f78c4790, 0x2d773633b05d2e, 0x94229c3a951c94, 0xbbbd70df4911bb}, + {0xb2c6963d2c1168, 0x105f47a72b0d73, 0x9fdf6111614080, 0x7b7e94b39e67b0}, + {1, 0, 0, 0}}, + {{0xad1a7d6efbe2b3, 0xf012482c0da69d, 0x6b3bdf12438345, 0x40d7558d7aa4d9}, + {0x8a09fffb5c6d3d, 0x9a356e5d9ffd38, 0x5973f15f4f9b1c, 0xdcd5f59f63c3ea}, + {1, 0, 0, 0}}, + {{0xacf39f4c5ca7ab, 0x4c8071cc5fd737, 0xc64e3602cd1184, 0x0acd4644c9abba}, + {0x6c011a36d8bf6e, 0xfecd87ba24e32a, 0x19f6f56574fad8, 0x050b204ced9405}, + {1, 0, 0, 0}}, + {{0xed4f1cae7d9a96, 0x5ceef7ad94c40a, 0x778e4a3bf3ef9b, 0x7405783dc3b55e}, + {0x32477c61b6e8c6, 0xb46a97570f018b, 0x91176d0a7e95d1, 0x3df90fbc4c7d0e}, + {1, 0, 0, 0}}} +}; /* Precomputation for the group generator. */ typedef struct { - felem g_pre_comp[2][16][3]; - int references; + felem g_pre_comp[2][16][3]; + int references; } NISTP224_PRE_COMP; const EC_METHOD *EC_GFp_nistp224_method(void) - { - static const EC_METHOD ret = { - EC_FLAGS_DEFAULT_OCT, - NID_X9_62_prime_field, - ec_GFp_nistp224_group_init, - ec_GFp_simple_group_finish, - ec_GFp_simple_group_clear_finish, - ec_GFp_nist_group_copy, - ec_GFp_nistp224_group_set_curve, - ec_GFp_simple_group_get_curve, - ec_GFp_simple_group_get_degree, - ec_GFp_simple_group_check_discriminant, - ec_GFp_simple_point_init, - ec_GFp_simple_point_finish, - ec_GFp_simple_point_clear_finish, - ec_GFp_simple_point_copy, - ec_GFp_simple_point_set_to_infinity, - ec_GFp_simple_set_Jprojective_coordinates_GFp, - ec_GFp_simple_get_Jprojective_coordinates_GFp, - ec_GFp_simple_point_set_affine_coordinates, - ec_GFp_nistp224_point_get_affine_coordinates, - 0 /* point_set_compressed_coordinates */, - 0 /* point2oct */, - 0 /* oct2point */, - ec_GFp_simple_add, - ec_GFp_simple_dbl, - ec_GFp_simple_invert, - 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, - ec_GFp_nistp224_points_mul, - ec_GFp_nistp224_precompute_mult, - ec_GFp_nistp224_have_precompute_mult, - ec_GFp_nist_field_mul, - ec_GFp_nist_field_sqr, - 0 /* field_div */, - 0 /* field_encode */, - 0 /* field_decode */, - 0 /* field_set_to_one */ }; - - return &ret; - } - -/* Helper functions to convert field elements to/from internal representation */ +{ + static const EC_METHOD ret = { + EC_FLAGS_DEFAULT_OCT, + NID_X9_62_prime_field, + ec_GFp_nistp224_group_init, + ec_GFp_simple_group_finish, + ec_GFp_simple_group_clear_finish, + ec_GFp_nist_group_copy, + ec_GFp_nistp224_group_set_curve, + ec_GFp_simple_group_get_curve, + ec_GFp_simple_group_get_degree, + ec_GFp_simple_group_check_discriminant, + ec_GFp_simple_point_init, + ec_GFp_simple_point_finish, + ec_GFp_simple_point_clear_finish, + ec_GFp_simple_point_copy, + ec_GFp_simple_point_set_to_infinity, + ec_GFp_simple_set_Jprojective_coordinates_GFp, + ec_GFp_simple_get_Jprojective_coordinates_GFp, + ec_GFp_simple_point_set_affine_coordinates, + ec_GFp_nistp224_point_get_affine_coordinates, + 0 /* point_set_compressed_coordinates */ , + 0 /* point2oct */ , + 0 /* oct2point */ , + ec_GFp_simple_add, + ec_GFp_simple_dbl, + ec_GFp_simple_invert, + 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, + ec_GFp_nistp224_points_mul, + ec_GFp_nistp224_precompute_mult, + ec_GFp_nistp224_have_precompute_mult, + ec_GFp_nist_field_mul, + ec_GFp_nist_field_sqr, + 0 /* field_div */ , + 0 /* field_encode */ , + 0 /* field_decode */ , + 0 /* field_set_to_one */ + }; + + return &ret; +} + +/* + * Helper functions to convert field elements to/from internal representation + */ static void bin28_to_felem(felem out, const u8 in[28]) - { - out[0] = *((const uint64_t *)(in)) & 0x00ffffffffffffff; - out[1] = (*((const uint64_t *)(in+7))) & 0x00ffffffffffffff; - out[2] = (*((const uint64_t *)(in+14))) & 0x00ffffffffffffff; - out[3] = (*((const uint64_t *)(in+21))) & 0x00ffffffffffffff; - } +{ + out[0] = *((const uint64_t *)(in)) & 0x00ffffffffffffff; + out[1] = (*((const uint64_t *)(in + 7))) & 0x00ffffffffffffff; + out[2] = (*((const uint64_t *)(in + 14))) & 0x00ffffffffffffff; + out[3] = (*((const uint64_t *)(in+20))) >> 8; +} static void felem_to_bin28(u8 out[28], const felem in) - { - unsigned i; - for (i = 0; i < 7; ++i) - { - out[i] = in[0]>>(8*i); - out[i+7] = in[1]>>(8*i); - out[i+14] = in[2]>>(8*i); - out[i+21] = in[3]>>(8*i); - } - } +{ + unsigned i; + for (i = 0; i < 7; ++i) { + out[i] = in[0] >> (8 * i); + out[i + 7] = in[1] >> (8 * i); + out[i + 14] = in[2] >> (8 * i); + out[i + 21] = in[3] >> (8 * i); + } +} /* To preserve endianness when using BN_bn2bin and BN_bin2bn */ static void flip_endian(u8 *out, const u8 *in, unsigned len) - { - unsigned i; - for (i = 0; i < len; ++i) - out[i] = in[len-1-i]; - } +{ + unsigned i; + for (i = 0; i < len; ++i) + out[i] = in[len - 1 - i]; +} /* From OpenSSL BIGNUM to internal representation */ static int BN_to_felem(felem out, const BIGNUM *bn) - { - felem_bytearray b_in; - felem_bytearray b_out; - unsigned num_bytes; - - /* BN_bn2bin eats leading zeroes */ - memset(b_out, 0, sizeof b_out); - num_bytes = BN_num_bytes(bn); - if (num_bytes > sizeof b_out) - { - ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); - return 0; - } - if (BN_is_negative(bn)) - { - ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); - return 0; - } - num_bytes = BN_bn2bin(bn, b_in); - flip_endian(b_out, b_in, num_bytes); - bin28_to_felem(out, b_out); - return 1; - } +{ + felem_bytearray b_in; + felem_bytearray b_out; + unsigned num_bytes; + + /* BN_bn2bin eats leading zeroes */ + memset(b_out, 0, sizeof b_out); + num_bytes = BN_num_bytes(bn); + if (num_bytes > sizeof b_out) { + ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); + return 0; + } + if (BN_is_negative(bn)) { + ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); + return 0; + } + num_bytes = BN_bn2bin(bn, b_in); + flip_endian(b_out, b_in, num_bytes); + bin28_to_felem(out, b_out); + return 1; +} /* From internal representation to OpenSSL BIGNUM */ static BIGNUM *felem_to_BN(BIGNUM *out, const felem in) - { - felem_bytearray b_in, b_out; - felem_to_bin28(b_in, in); - flip_endian(b_out, b_in, sizeof b_out); - return BN_bin2bn(b_out, sizeof b_out, out); - } +{ + felem_bytearray b_in, b_out; + felem_to_bin28(b_in, in); + flip_endian(b_out, b_in, sizeof b_out); + return BN_bin2bn(b_out, sizeof b_out, out); +} /******************************************************************************/ -/* FIELD OPERATIONS +/*- + * FIELD OPERATIONS * * Field operations, using the internal representation of field elements. * NB! These operations are specific to our point multiplication and cannot be @@ -354,402 +388,441 @@ static BIGNUM *felem_to_BN(BIGNUM *out, const felem in) */ static void felem_one(felem out) - { - out[0] = 1; - out[1] = 0; - out[2] = 0; - out[3] = 0; - } +{ + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 0; +} static void felem_assign(felem out, const felem in) - { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - } +{ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; +} /* Sum two field elements: out += in */ static void felem_sum(felem out, const felem in) - { - out[0] += in[0]; - out[1] += in[1]; - out[2] += in[2]; - out[3] += in[3]; - } +{ + out[0] += in[0]; + out[1] += in[1]; + out[2] += in[2]; + out[3] += in[3]; +} /* Get negative value: out = -in */ /* Assumes in[i] < 2^57 */ static void felem_neg(felem out, const felem in) - { - static const limb two58p2 = (((limb) 1) << 58) + (((limb) 1) << 2); - static const limb two58m2 = (((limb) 1) << 58) - (((limb) 1) << 2); - static const limb two58m42m2 = (((limb) 1) << 58) - - (((limb) 1) << 42) - (((limb) 1) << 2); - - /* Set to 0 mod 2^224-2^96+1 to ensure out > in */ - out[0] = two58p2 - in[0]; - out[1] = two58m42m2 - in[1]; - out[2] = two58m2 - in[2]; - out[3] = two58m2 - in[3]; - } +{ + static const limb two58p2 = (((limb) 1) << 58) + (((limb) 1) << 2); + static const limb two58m2 = (((limb) 1) << 58) - (((limb) 1) << 2); + static const limb two58m42m2 = (((limb) 1) << 58) - + (((limb) 1) << 42) - (((limb) 1) << 2); + + /* Set to 0 mod 2^224-2^96+1 to ensure out > in */ + out[0] = two58p2 - in[0]; + out[1] = two58m42m2 - in[1]; + out[2] = two58m2 - in[2]; + out[3] = two58m2 - in[3]; +} /* Subtract field elements: out -= in */ /* Assumes in[i] < 2^57 */ static void felem_diff(felem out, const felem in) - { - static const limb two58p2 = (((limb) 1) << 58) + (((limb) 1) << 2); - static const limb two58m2 = (((limb) 1) << 58) - (((limb) 1) << 2); - static const limb two58m42m2 = (((limb) 1) << 58) - - (((limb) 1) << 42) - (((limb) 1) << 2); - - /* Add 0 mod 2^224-2^96+1 to ensure out > in */ - out[0] += two58p2; - out[1] += two58m42m2; - out[2] += two58m2; - out[3] += two58m2; - - out[0] -= in[0]; - out[1] -= in[1]; - out[2] -= in[2]; - out[3] -= in[3]; - } +{ + static const limb two58p2 = (((limb) 1) << 58) + (((limb) 1) << 2); + static const limb two58m2 = (((limb) 1) << 58) - (((limb) 1) << 2); + static const limb two58m42m2 = (((limb) 1) << 58) - + (((limb) 1) << 42) - (((limb) 1) << 2); + + /* Add 0 mod 2^224-2^96+1 to ensure out > in */ + out[0] += two58p2; + out[1] += two58m42m2; + out[2] += two58m2; + out[3] += two58m2; + + out[0] -= in[0]; + out[1] -= in[1]; + out[2] -= in[2]; + out[3] -= in[3]; +} /* Subtract in unreduced 128-bit mode: out -= in */ /* Assumes in[i] < 2^119 */ static void widefelem_diff(widefelem out, const widefelem in) - { - static const widelimb two120 = ((widelimb) 1) << 120; - static const widelimb two120m64 = (((widelimb) 1) << 120) - - (((widelimb) 1) << 64); - static const widelimb two120m104m64 = (((widelimb) 1) << 120) - - (((widelimb) 1) << 104) - (((widelimb) 1) << 64); - - /* Add 0 mod 2^224-2^96+1 to ensure out > in */ - out[0] += two120; - out[1] += two120m64; - out[2] += two120m64; - out[3] += two120; - out[4] += two120m104m64; - out[5] += two120m64; - out[6] += two120m64; - - out[0] -= in[0]; - out[1] -= in[1]; - out[2] -= in[2]; - out[3] -= in[3]; - out[4] -= in[4]; - out[5] -= in[5]; - out[6] -= in[6]; - } +{ + static const widelimb two120 = ((widelimb) 1) << 120; + static const widelimb two120m64 = (((widelimb) 1) << 120) - + (((widelimb) 1) << 64); + static const widelimb two120m104m64 = (((widelimb) 1) << 120) - + (((widelimb) 1) << 104) - (((widelimb) 1) << 64); + + /* Add 0 mod 2^224-2^96+1 to ensure out > in */ + out[0] += two120; + out[1] += two120m64; + out[2] += two120m64; + out[3] += two120; + out[4] += two120m104m64; + out[5] += two120m64; + out[6] += two120m64; + + out[0] -= in[0]; + out[1] -= in[1]; + out[2] -= in[2]; + out[3] -= in[3]; + out[4] -= in[4]; + out[5] -= in[5]; + out[6] -= in[6]; +} /* Subtract in mixed mode: out128 -= in64 */ /* in[i] < 2^63 */ static void felem_diff_128_64(widefelem out, const felem in) - { - static const widelimb two64p8 = (((widelimb) 1) << 64) + - (((widelimb) 1) << 8); - static const widelimb two64m8 = (((widelimb) 1) << 64) - - (((widelimb) 1) << 8); - static const widelimb two64m48m8 = (((widelimb) 1) << 64) - - (((widelimb) 1) << 48) - (((widelimb) 1) << 8); - - /* Add 0 mod 2^224-2^96+1 to ensure out > in */ - out[0] += two64p8; - out[1] += two64m48m8; - out[2] += two64m8; - out[3] += two64m8; - - out[0] -= in[0]; - out[1] -= in[1]; - out[2] -= in[2]; - out[3] -= in[3]; - } - -/* Multiply a field element by a scalar: out = out * scalar - * The scalars we actually use are small, so results fit without overflow */ +{ + static const widelimb two64p8 = (((widelimb) 1) << 64) + + (((widelimb) 1) << 8); + static const widelimb two64m8 = (((widelimb) 1) << 64) - + (((widelimb) 1) << 8); + static const widelimb two64m48m8 = (((widelimb) 1) << 64) - + (((widelimb) 1) << 48) - (((widelimb) 1) << 8); + + /* Add 0 mod 2^224-2^96+1 to ensure out > in */ + out[0] += two64p8; + out[1] += two64m48m8; + out[2] += two64m8; + out[3] += two64m8; + + out[0] -= in[0]; + out[1] -= in[1]; + out[2] -= in[2]; + out[3] -= in[3]; +} + +/* + * Multiply a field element by a scalar: out = out * scalar The scalars we + * actually use are small, so results fit without overflow + */ static void felem_scalar(felem out, const limb scalar) - { - out[0] *= scalar; - out[1] *= scalar; - out[2] *= scalar; - out[3] *= scalar; - } - -/* Multiply an unreduced field element by a scalar: out = out * scalar - * The scalars we actually use are small, so results fit without overflow */ +{ + out[0] *= scalar; + out[1] *= scalar; + out[2] *= scalar; + out[3] *= scalar; +} + +/* + * Multiply an unreduced field element by a scalar: out = out * scalar The + * scalars we actually use are small, so results fit without overflow + */ static void widefelem_scalar(widefelem out, const widelimb scalar) - { - out[0] *= scalar; - out[1] *= scalar; - out[2] *= scalar; - out[3] *= scalar; - out[4] *= scalar; - out[5] *= scalar; - out[6] *= scalar; - } +{ + out[0] *= scalar; + out[1] *= scalar; + out[2] *= scalar; + out[3] *= scalar; + out[4] *= scalar; + out[5] *= scalar; + out[6] *= scalar; +} /* Square a field element: out = in^2 */ static void felem_square(widefelem out, const felem in) - { - limb tmp0, tmp1, tmp2; - tmp0 = 2 * in[0]; tmp1 = 2 * in[1]; tmp2 = 2 * in[2]; - out[0] = ((widelimb) in[0]) * in[0]; - out[1] = ((widelimb) in[0]) * tmp1; - out[2] = ((widelimb) in[0]) * tmp2 + ((widelimb) in[1]) * in[1]; - out[3] = ((widelimb) in[3]) * tmp0 + - ((widelimb) in[1]) * tmp2; - out[4] = ((widelimb) in[3]) * tmp1 + ((widelimb) in[2]) * in[2]; - out[5] = ((widelimb) in[3]) * tmp2; - out[6] = ((widelimb) in[3]) * in[3]; - } +{ + limb tmp0, tmp1, tmp2; + tmp0 = 2 * in[0]; + tmp1 = 2 * in[1]; + tmp2 = 2 * in[2]; + out[0] = ((widelimb) in[0]) * in[0]; + out[1] = ((widelimb) in[0]) * tmp1; + out[2] = ((widelimb) in[0]) * tmp2 + ((widelimb) in[1]) * in[1]; + out[3] = ((widelimb) in[3]) * tmp0 + ((widelimb) in[1]) * tmp2; + out[4] = ((widelimb) in[3]) * tmp1 + ((widelimb) in[2]) * in[2]; + out[5] = ((widelimb) in[3]) * tmp2; + out[6] = ((widelimb) in[3]) * in[3]; +} /* Multiply two field elements: out = in1 * in2 */ static void felem_mul(widefelem out, const felem in1, const felem in2) - { - out[0] = ((widelimb) in1[0]) * in2[0]; - out[1] = ((widelimb) in1[0]) * in2[1] + ((widelimb) in1[1]) * in2[0]; - out[2] = ((widelimb) in1[0]) * in2[2] + ((widelimb) in1[1]) * in2[1] + - ((widelimb) in1[2]) * in2[0]; - out[3] = ((widelimb) in1[0]) * in2[3] + ((widelimb) in1[1]) * in2[2] + - ((widelimb) in1[2]) * in2[1] + ((widelimb) in1[3]) * in2[0]; - out[4] = ((widelimb) in1[1]) * in2[3] + ((widelimb) in1[2]) * in2[2] + - ((widelimb) in1[3]) * in2[1]; - out[5] = ((widelimb) in1[2]) * in2[3] + ((widelimb) in1[3]) * in2[2]; - out[6] = ((widelimb) in1[3]) * in2[3]; - } - -/* Reduce seven 128-bit coefficients to four 64-bit coefficients. +{ + out[0] = ((widelimb) in1[0]) * in2[0]; + out[1] = ((widelimb) in1[0]) * in2[1] + ((widelimb) in1[1]) * in2[0]; + out[2] = ((widelimb) in1[0]) * in2[2] + ((widelimb) in1[1]) * in2[1] + + ((widelimb) in1[2]) * in2[0]; + out[3] = ((widelimb) in1[0]) * in2[3] + ((widelimb) in1[1]) * in2[2] + + ((widelimb) in1[2]) * in2[1] + ((widelimb) in1[3]) * in2[0]; + out[4] = ((widelimb) in1[1]) * in2[3] + ((widelimb) in1[2]) * in2[2] + + ((widelimb) in1[3]) * in2[1]; + out[5] = ((widelimb) in1[2]) * in2[3] + ((widelimb) in1[3]) * in2[2]; + out[6] = ((widelimb) in1[3]) * in2[3]; +} + +/*- + * Reduce seven 128-bit coefficients to four 64-bit coefficients. * Requires in[i] < 2^126, * ensures out[0] < 2^56, out[1] < 2^56, out[2] < 2^56, out[3] <= 2^56 + 2^16 */ static void felem_reduce(felem out, const widefelem in) - { - static const widelimb two127p15 = (((widelimb) 1) << 127) + - (((widelimb) 1) << 15); - static const widelimb two127m71 = (((widelimb) 1) << 127) - - (((widelimb) 1) << 71); - static const widelimb two127m71m55 = (((widelimb) 1) << 127) - - (((widelimb) 1) << 71) - (((widelimb) 1) << 55); - widelimb output[5]; - - /* Add 0 mod 2^224-2^96+1 to ensure all differences are positive */ - output[0] = in[0] + two127p15; - output[1] = in[1] + two127m71m55; - output[2] = in[2] + two127m71; - output[3] = in[3]; - output[4] = in[4]; - - /* Eliminate in[4], in[5], in[6] */ - output[4] += in[6] >> 16; - output[3] += (in[6] & 0xffff) << 40; - output[2] -= in[6]; - - output[3] += in[5] >> 16; - output[2] += (in[5] & 0xffff) << 40; - output[1] -= in[5]; - - output[2] += output[4] >> 16; - output[1] += (output[4] & 0xffff) << 40; - output[0] -= output[4]; - - /* Carry 2 -> 3 -> 4 */ - output[3] += output[2] >> 56; - output[2] &= 0x00ffffffffffffff; - - output[4] = output[3] >> 56; - output[3] &= 0x00ffffffffffffff; - - /* Now output[2] < 2^56, output[3] < 2^56, output[4] < 2^72 */ - - /* Eliminate output[4] */ - output[2] += output[4] >> 16; - /* output[2] < 2^56 + 2^56 = 2^57 */ - output[1] += (output[4] & 0xffff) << 40; - output[0] -= output[4]; - - /* Carry 0 -> 1 -> 2 -> 3 */ - output[1] += output[0] >> 56; - out[0] = output[0] & 0x00ffffffffffffff; - - output[2] += output[1] >> 56; - /* output[2] < 2^57 + 2^72 */ - out[1] = output[1] & 0x00ffffffffffffff; - output[3] += output[2] >> 56; - /* output[3] <= 2^56 + 2^16 */ - out[2] = output[2] & 0x00ffffffffffffff; - - /* out[0] < 2^56, out[1] < 2^56, out[2] < 2^56, - * out[3] <= 2^56 + 2^16 (due to final carry), - * so out < 2*p */ - out[3] = output[3]; - } +{ + static const widelimb two127p15 = (((widelimb) 1) << 127) + + (((widelimb) 1) << 15); + static const widelimb two127m71 = (((widelimb) 1) << 127) - + (((widelimb) 1) << 71); + static const widelimb two127m71m55 = (((widelimb) 1) << 127) - + (((widelimb) 1) << 71) - (((widelimb) 1) << 55); + widelimb output[5]; + + /* Add 0 mod 2^224-2^96+1 to ensure all differences are positive */ + output[0] = in[0] + two127p15; + output[1] = in[1] + two127m71m55; + output[2] = in[2] + two127m71; + output[3] = in[3]; + output[4] = in[4]; + + /* Eliminate in[4], in[5], in[6] */ + output[4] += in[6] >> 16; + output[3] += (in[6] & 0xffff) << 40; + output[2] -= in[6]; + + output[3] += in[5] >> 16; + output[2] += (in[5] & 0xffff) << 40; + output[1] -= in[5]; + + output[2] += output[4] >> 16; + output[1] += (output[4] & 0xffff) << 40; + output[0] -= output[4]; + + /* Carry 2 -> 3 -> 4 */ + output[3] += output[2] >> 56; + output[2] &= 0x00ffffffffffffff; + + output[4] = output[3] >> 56; + output[3] &= 0x00ffffffffffffff; + + /* Now output[2] < 2^56, output[3] < 2^56, output[4] < 2^72 */ + + /* Eliminate output[4] */ + output[2] += output[4] >> 16; + /* output[2] < 2^56 + 2^56 = 2^57 */ + output[1] += (output[4] & 0xffff) << 40; + output[0] -= output[4]; + + /* Carry 0 -> 1 -> 2 -> 3 */ + output[1] += output[0] >> 56; + out[0] = output[0] & 0x00ffffffffffffff; + + output[2] += output[1] >> 56; + /* output[2] < 2^57 + 2^72 */ + out[1] = output[1] & 0x00ffffffffffffff; + output[3] += output[2] >> 56; + /* output[3] <= 2^56 + 2^16 */ + out[2] = output[2] & 0x00ffffffffffffff; + + /*- + * out[0] < 2^56, out[1] < 2^56, out[2] < 2^56, + * out[3] <= 2^56 + 2^16 (due to final carry), + * so out < 2*p + */ + out[3] = output[3]; +} static void felem_square_reduce(felem out, const felem in) - { - widefelem tmp; - felem_square(tmp, in); - felem_reduce(out, tmp); - } +{ + widefelem tmp; + felem_square(tmp, in); + felem_reduce(out, tmp); +} static void felem_mul_reduce(felem out, const felem in1, const felem in2) - { - widefelem tmp; - felem_mul(tmp, in1, in2); - felem_reduce(out, tmp); - } - -/* Reduce to unique minimal representation. - * Requires 0 <= in < 2*p (always call felem_reduce first) */ +{ + widefelem tmp; + felem_mul(tmp, in1, in2); + felem_reduce(out, tmp); +} + +/* + * Reduce to unique minimal representation. Requires 0 <= in < 2*p (always + * call felem_reduce first) + */ static void felem_contract(felem out, const felem in) - { - static const int64_t two56 = ((limb) 1) << 56; - /* 0 <= in < 2*p, p = 2^224 - 2^96 + 1 */ - /* if in > p , reduce in = in - 2^224 + 2^96 - 1 */ - int64_t tmp[4], a; - tmp[0] = in[0]; - tmp[1] = in[1]; - tmp[2] = in[2]; - tmp[3] = in[3]; - /* Case 1: a = 1 iff in >= 2^224 */ - a = (in[3] >> 56); - tmp[0] -= a; - tmp[1] += a << 40; - tmp[3] &= 0x00ffffffffffffff; - /* Case 2: a = 0 iff p <= in < 2^224, i.e., - * the high 128 bits are all 1 and the lower part is non-zero */ - a = ((in[3] & in[2] & (in[1] | 0x000000ffffffffff)) + 1) | - (((int64_t)(in[0] + (in[1] & 0x000000ffffffffff)) - 1) >> 63); - a &= 0x00ffffffffffffff; - /* turn a into an all-one mask (if a = 0) or an all-zero mask */ - a = (a - 1) >> 63; - /* subtract 2^224 - 2^96 + 1 if a is all-one*/ - tmp[3] &= a ^ 0xffffffffffffffff; - tmp[2] &= a ^ 0xffffffffffffffff; - tmp[1] &= (a ^ 0xffffffffffffffff) | 0x000000ffffffffff; - tmp[0] -= 1 & a; - - /* eliminate negative coefficients: if tmp[0] is negative, tmp[1] must - * be non-zero, so we only need one step */ - a = tmp[0] >> 63; - tmp[0] += two56 & a; - tmp[1] -= 1 & a; - - /* carry 1 -> 2 -> 3 */ - tmp[2] += tmp[1] >> 56; - tmp[1] &= 0x00ffffffffffffff; - - tmp[3] += tmp[2] >> 56; - tmp[2] &= 0x00ffffffffffffff; - - /* Now 0 <= out < p */ - out[0] = tmp[0]; - out[1] = tmp[1]; - out[2] = tmp[2]; - out[3] = tmp[3]; - } - -/* Zero-check: returns 1 if input is 0, and 0 otherwise. - * We know that field elements are reduced to in < 2^225, - * so we only need to check three cases: 0, 2^224 - 2^96 + 1, - * and 2^225 - 2^97 + 2 */ +{ + static const int64_t two56 = ((limb) 1) << 56; + /* 0 <= in < 2*p, p = 2^224 - 2^96 + 1 */ + /* if in > p , reduce in = in - 2^224 + 2^96 - 1 */ + int64_t tmp[4], a; + tmp[0] = in[0]; + tmp[1] = in[1]; + tmp[2] = in[2]; + tmp[3] = in[3]; + /* Case 1: a = 1 iff in >= 2^224 */ + a = (in[3] >> 56); + tmp[0] -= a; + tmp[1] += a << 40; + tmp[3] &= 0x00ffffffffffffff; + /* + * Case 2: a = 0 iff p <= in < 2^224, i.e., the high 128 bits are all 1 + * and the lower part is non-zero + */ + a = ((in[3] & in[2] & (in[1] | 0x000000ffffffffff)) + 1) | + (((int64_t) (in[0] + (in[1] & 0x000000ffffffffff)) - 1) >> 63); + a &= 0x00ffffffffffffff; + /* turn a into an all-one mask (if a = 0) or an all-zero mask */ + a = (a - 1) >> 63; + /* subtract 2^224 - 2^96 + 1 if a is all-one */ + tmp[3] &= a ^ 0xffffffffffffffff; + tmp[2] &= a ^ 0xffffffffffffffff; + tmp[1] &= (a ^ 0xffffffffffffffff) | 0x000000ffffffffff; + tmp[0] -= 1 & a; + + /* + * eliminate negative coefficients: if tmp[0] is negative, tmp[1] must be + * non-zero, so we only need one step + */ + a = tmp[0] >> 63; + tmp[0] += two56 & a; + tmp[1] -= 1 & a; + + /* carry 1 -> 2 -> 3 */ + tmp[2] += tmp[1] >> 56; + tmp[1] &= 0x00ffffffffffffff; + + tmp[3] += tmp[2] >> 56; + tmp[2] &= 0x00ffffffffffffff; + + /* Now 0 <= out < p */ + out[0] = tmp[0]; + out[1] = tmp[1]; + out[2] = tmp[2]; + out[3] = tmp[3]; +} + +/* + * Zero-check: returns 1 if input is 0, and 0 otherwise. We know that field + * elements are reduced to in < 2^225, so we only need to check three cases: + * 0, 2^224 - 2^96 + 1, and 2^225 - 2^97 + 2 + */ static limb felem_is_zero(const felem in) - { - limb zero, two224m96p1, two225m97p2; - - zero = in[0] | in[1] | in[2] | in[3]; - zero = (((int64_t)(zero) - 1) >> 63) & 1; - two224m96p1 = (in[0] ^ 1) | (in[1] ^ 0x00ffff0000000000) - | (in[2] ^ 0x00ffffffffffffff) | (in[3] ^ 0x00ffffffffffffff); - two224m96p1 = (((int64_t)(two224m96p1) - 1) >> 63) & 1; - two225m97p2 = (in[0] ^ 2) | (in[1] ^ 0x00fffe0000000000) - | (in[2] ^ 0x00ffffffffffffff) | (in[3] ^ 0x01ffffffffffffff); - two225m97p2 = (((int64_t)(two225m97p2) - 1) >> 63) & 1; - return (zero | two224m96p1 | two225m97p2); - } +{ + limb zero, two224m96p1, two225m97p2; + + zero = in[0] | in[1] | in[2] | in[3]; + zero = (((int64_t) (zero) - 1) >> 63) & 1; + two224m96p1 = (in[0] ^ 1) | (in[1] ^ 0x00ffff0000000000) + | (in[2] ^ 0x00ffffffffffffff) | (in[3] ^ 0x00ffffffffffffff); + two224m96p1 = (((int64_t) (two224m96p1) - 1) >> 63) & 1; + two225m97p2 = (in[0] ^ 2) | (in[1] ^ 0x00fffe0000000000) + | (in[2] ^ 0x00ffffffffffffff) | (in[3] ^ 0x01ffffffffffffff); + two225m97p2 = (((int64_t) (two225m97p2) - 1) >> 63) & 1; + return (zero | two224m96p1 | two225m97p2); +} static limb felem_is_zero_int(const felem in) - { - return (int) (felem_is_zero(in) & ((limb)1)); - } +{ + return (int)(felem_is_zero(in) & ((limb) 1)); +} /* Invert a field element */ /* Computation chain copied from djb's code */ static void felem_inv(felem out, const felem in) - { - felem ftmp, ftmp2, ftmp3, ftmp4; - widefelem tmp; - unsigned i; - - felem_square(tmp, in); felem_reduce(ftmp, tmp); /* 2 */ - felem_mul(tmp, in, ftmp); felem_reduce(ftmp, tmp); /* 2^2 - 1 */ - felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^3 - 2 */ - felem_mul(tmp, in, ftmp); felem_reduce(ftmp, tmp); /* 2^3 - 1 */ - felem_square(tmp, ftmp); felem_reduce(ftmp2, tmp); /* 2^4 - 2 */ - felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp); /* 2^5 - 4 */ - felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp); /* 2^6 - 8 */ - felem_mul(tmp, ftmp2, ftmp); felem_reduce(ftmp, tmp); /* 2^6 - 1 */ - felem_square(tmp, ftmp); felem_reduce(ftmp2, tmp); /* 2^7 - 2 */ - for (i = 0; i < 5; ++i) /* 2^12 - 2^6 */ - { - felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp); - } - felem_mul(tmp, ftmp2, ftmp); felem_reduce(ftmp2, tmp); /* 2^12 - 1 */ - felem_square(tmp, ftmp2); felem_reduce(ftmp3, tmp); /* 2^13 - 2 */ - for (i = 0; i < 11; ++i) /* 2^24 - 2^12 */ - { - felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); - } - felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp2, tmp); /* 2^24 - 1 */ - felem_square(tmp, ftmp2); felem_reduce(ftmp3, tmp); /* 2^25 - 2 */ - for (i = 0; i < 23; ++i) /* 2^48 - 2^24 */ - { - felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); - } - felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^48 - 1 */ - felem_square(tmp, ftmp3); felem_reduce(ftmp4, tmp); /* 2^49 - 2 */ - for (i = 0; i < 47; ++i) /* 2^96 - 2^48 */ - { - felem_square(tmp, ftmp4); felem_reduce(ftmp4, tmp); - } - felem_mul(tmp, ftmp3, ftmp4); felem_reduce(ftmp3, tmp); /* 2^96 - 1 */ - felem_square(tmp, ftmp3); felem_reduce(ftmp4, tmp); /* 2^97 - 2 */ - for (i = 0; i < 23; ++i) /* 2^120 - 2^24 */ - { - felem_square(tmp, ftmp4); felem_reduce(ftmp4, tmp); - } - felem_mul(tmp, ftmp2, ftmp4); felem_reduce(ftmp2, tmp); /* 2^120 - 1 */ - for (i = 0; i < 6; ++i) /* 2^126 - 2^6 */ - { - felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp); - } - felem_mul(tmp, ftmp2, ftmp); felem_reduce(ftmp, tmp); /* 2^126 - 1 */ - felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^127 - 2 */ - felem_mul(tmp, ftmp, in); felem_reduce(ftmp, tmp); /* 2^127 - 1 */ - for (i = 0; i < 97; ++i) /* 2^224 - 2^97 */ - { - felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); - } - felem_mul(tmp, ftmp, ftmp3); felem_reduce(out, tmp); /* 2^224 - 2^96 - 1 */ - } - -/* Copy in constant time: - * if icopy == 1, copy in to out, - * if icopy == 0, copy out to itself. */ -static void -copy_conditional(felem out, const felem in, limb icopy) - { - unsigned i; - /* icopy is a (64-bit) 0 or 1, so copy is either all-zero or all-one */ - const limb copy = -icopy; - for (i = 0; i < 4; ++i) - { - const limb tmp = copy & (in[i] ^ out[i]); - out[i] ^= tmp; - } - } +{ + felem ftmp, ftmp2, ftmp3, ftmp4; + widefelem tmp; + unsigned i; + + felem_square(tmp, in); + felem_reduce(ftmp, tmp); /* 2 */ + felem_mul(tmp, in, ftmp); + felem_reduce(ftmp, tmp); /* 2^2 - 1 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^3 - 2 */ + felem_mul(tmp, in, ftmp); + felem_reduce(ftmp, tmp); /* 2^3 - 1 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp2, tmp); /* 2^4 - 2 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^5 - 4 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^6 - 8 */ + felem_mul(tmp, ftmp2, ftmp); + felem_reduce(ftmp, tmp); /* 2^6 - 1 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp2, tmp); /* 2^7 - 2 */ + for (i = 0; i < 5; ++i) { /* 2^12 - 2^6 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); + } + felem_mul(tmp, ftmp2, ftmp); + felem_reduce(ftmp2, tmp); /* 2^12 - 1 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^13 - 2 */ + for (i = 0; i < 11; ++i) { /* 2^24 - 2^12 */ + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); + } + felem_mul(tmp, ftmp3, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^24 - 1 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^25 - 2 */ + for (i = 0; i < 23; ++i) { /* 2^48 - 2^24 */ + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); + } + felem_mul(tmp, ftmp3, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^48 - 1 */ + felem_square(tmp, ftmp3); + felem_reduce(ftmp4, tmp); /* 2^49 - 2 */ + for (i = 0; i < 47; ++i) { /* 2^96 - 2^48 */ + felem_square(tmp, ftmp4); + felem_reduce(ftmp4, tmp); + } + felem_mul(tmp, ftmp3, ftmp4); + felem_reduce(ftmp3, tmp); /* 2^96 - 1 */ + felem_square(tmp, ftmp3); + felem_reduce(ftmp4, tmp); /* 2^97 - 2 */ + for (i = 0; i < 23; ++i) { /* 2^120 - 2^24 */ + felem_square(tmp, ftmp4); + felem_reduce(ftmp4, tmp); + } + felem_mul(tmp, ftmp2, ftmp4); + felem_reduce(ftmp2, tmp); /* 2^120 - 1 */ + for (i = 0; i < 6; ++i) { /* 2^126 - 2^6 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); + } + felem_mul(tmp, ftmp2, ftmp); + felem_reduce(ftmp, tmp); /* 2^126 - 1 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^127 - 2 */ + felem_mul(tmp, ftmp, in); + felem_reduce(ftmp, tmp); /* 2^127 - 1 */ + for (i = 0; i < 97; ++i) { /* 2^224 - 2^97 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + } + felem_mul(tmp, ftmp, ftmp3); + felem_reduce(out, tmp); /* 2^224 - 2^96 - 1 */ +} + +/* + * Copy in constant time: if icopy == 1, copy in to out, if icopy == 0, copy + * out to itself. + */ +static void copy_conditional(felem out, const felem in, limb icopy) +{ + unsigned i; + /* + * icopy is a (64-bit) 0 or 1, so copy is either all-zero or all-one + */ + const limb copy = -icopy; + for (i = 0; i < 4; ++i) { + const limb tmp = copy & (in[i] ^ out[i]); + out[i] ^= tmp; + } +} /******************************************************************************/ -/* ELLIPTIC CURVE POINT OPERATIONS +/*- + * ELLIPTIC CURVE POINT OPERATIONS * * Points are represented in Jacobian projective coordinates: * (X, Y, Z) corresponds to the affine point (X/Z^2, Y/Z^3), @@ -757,85 +830,88 @@ copy_conditional(felem out, const felem in, limb icopy) * */ -/* Double an elliptic curve point: +/*- + * Double an elliptic curve point: * (X', Y', Z') = 2 * (X, Y, Z), where * X' = (3 * (X - Z^2) * (X + Z^2))^2 - 8 * X * Y^2 * Y' = 3 * (X - Z^2) * (X + Z^2) * (4 * X * Y^2 - X') - 8 * Y^2 * Z' = (Y + Z)^2 - Y^2 - Z^2 = 2 * Y * Z * Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed, - * while x_out == y_in is not (maybe this works, but it's not tested). */ + * while x_out == y_in is not (maybe this works, but it's not tested). + */ static void point_double(felem x_out, felem y_out, felem z_out, const felem x_in, const felem y_in, const felem z_in) - { - widefelem tmp, tmp2; - felem delta, gamma, beta, alpha, ftmp, ftmp2; - - felem_assign(ftmp, x_in); - felem_assign(ftmp2, x_in); - - /* delta = z^2 */ - felem_square(tmp, z_in); - felem_reduce(delta, tmp); - - /* gamma = y^2 */ - felem_square(tmp, y_in); - felem_reduce(gamma, tmp); - - /* beta = x*gamma */ - felem_mul(tmp, x_in, gamma); - felem_reduce(beta, tmp); - - /* alpha = 3*(x-delta)*(x+delta) */ - felem_diff(ftmp, delta); - /* ftmp[i] < 2^57 + 2^58 + 2 < 2^59 */ - felem_sum(ftmp2, delta); - /* ftmp2[i] < 2^57 + 2^57 = 2^58 */ - felem_scalar(ftmp2, 3); - /* ftmp2[i] < 3 * 2^58 < 2^60 */ - felem_mul(tmp, ftmp, ftmp2); - /* tmp[i] < 2^60 * 2^59 * 4 = 2^121 */ - felem_reduce(alpha, tmp); - - /* x' = alpha^2 - 8*beta */ - felem_square(tmp, alpha); - /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */ - felem_assign(ftmp, beta); - felem_scalar(ftmp, 8); - /* ftmp[i] < 8 * 2^57 = 2^60 */ - felem_diff_128_64(tmp, ftmp); - /* tmp[i] < 2^116 + 2^64 + 8 < 2^117 */ - felem_reduce(x_out, tmp); - - /* z' = (y + z)^2 - gamma - delta */ - felem_sum(delta, gamma); - /* delta[i] < 2^57 + 2^57 = 2^58 */ - felem_assign(ftmp, y_in); - felem_sum(ftmp, z_in); - /* ftmp[i] < 2^57 + 2^57 = 2^58 */ - felem_square(tmp, ftmp); - /* tmp[i] < 4 * 2^58 * 2^58 = 2^118 */ - felem_diff_128_64(tmp, delta); - /* tmp[i] < 2^118 + 2^64 + 8 < 2^119 */ - felem_reduce(z_out, tmp); - - /* y' = alpha*(4*beta - x') - 8*gamma^2 */ - felem_scalar(beta, 4); - /* beta[i] < 4 * 2^57 = 2^59 */ - felem_diff(beta, x_out); - /* beta[i] < 2^59 + 2^58 + 2 < 2^60 */ - felem_mul(tmp, alpha, beta); - /* tmp[i] < 4 * 2^57 * 2^60 = 2^119 */ - felem_square(tmp2, gamma); - /* tmp2[i] < 4 * 2^57 * 2^57 = 2^116 */ - widefelem_scalar(tmp2, 8); - /* tmp2[i] < 8 * 2^116 = 2^119 */ - widefelem_diff(tmp, tmp2); - /* tmp[i] < 2^119 + 2^120 < 2^121 */ - felem_reduce(y_out, tmp); - } - -/* Add two elliptic curve points: +{ + widefelem tmp, tmp2; + felem delta, gamma, beta, alpha, ftmp, ftmp2; + + felem_assign(ftmp, x_in); + felem_assign(ftmp2, x_in); + + /* delta = z^2 */ + felem_square(tmp, z_in); + felem_reduce(delta, tmp); + + /* gamma = y^2 */ + felem_square(tmp, y_in); + felem_reduce(gamma, tmp); + + /* beta = x*gamma */ + felem_mul(tmp, x_in, gamma); + felem_reduce(beta, tmp); + + /* alpha = 3*(x-delta)*(x+delta) */ + felem_diff(ftmp, delta); + /* ftmp[i] < 2^57 + 2^58 + 2 < 2^59 */ + felem_sum(ftmp2, delta); + /* ftmp2[i] < 2^57 + 2^57 = 2^58 */ + felem_scalar(ftmp2, 3); + /* ftmp2[i] < 3 * 2^58 < 2^60 */ + felem_mul(tmp, ftmp, ftmp2); + /* tmp[i] < 2^60 * 2^59 * 4 = 2^121 */ + felem_reduce(alpha, tmp); + + /* x' = alpha^2 - 8*beta */ + felem_square(tmp, alpha); + /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */ + felem_assign(ftmp, beta); + felem_scalar(ftmp, 8); + /* ftmp[i] < 8 * 2^57 = 2^60 */ + felem_diff_128_64(tmp, ftmp); + /* tmp[i] < 2^116 + 2^64 + 8 < 2^117 */ + felem_reduce(x_out, tmp); + + /* z' = (y + z)^2 - gamma - delta */ + felem_sum(delta, gamma); + /* delta[i] < 2^57 + 2^57 = 2^58 */ + felem_assign(ftmp, y_in); + felem_sum(ftmp, z_in); + /* ftmp[i] < 2^57 + 2^57 = 2^58 */ + felem_square(tmp, ftmp); + /* tmp[i] < 4 * 2^58 * 2^58 = 2^118 */ + felem_diff_128_64(tmp, delta); + /* tmp[i] < 2^118 + 2^64 + 8 < 2^119 */ + felem_reduce(z_out, tmp); + + /* y' = alpha*(4*beta - x') - 8*gamma^2 */ + felem_scalar(beta, 4); + /* beta[i] < 4 * 2^57 = 2^59 */ + felem_diff(beta, x_out); + /* beta[i] < 2^59 + 2^58 + 2 < 2^60 */ + felem_mul(tmp, alpha, beta); + /* tmp[i] < 4 * 2^57 * 2^60 = 2^119 */ + felem_square(tmp2, gamma); + /* tmp2[i] < 4 * 2^57 * 2^57 = 2^116 */ + widefelem_scalar(tmp2, 8); + /* tmp2[i] < 8 * 2^116 = 2^119 */ + widefelem_diff(tmp, tmp2); + /* tmp[i] < 2^119 + 2^120 < 2^121 */ + felem_reduce(y_out, tmp); +} + +/*- + * Add two elliptic curve points: * (X_1, Y_1, Z_1) + (X_2, Y_2, Z_2) = (X_3, Y_3, Z_3), where * X_3 = (Z_1^3 * Y_2 - Z_2^3 * Y_1)^2 - (Z_1^2 * X_2 - Z_2^2 * X_1)^3 - * 2 * Z_2^2 * X_1 * (Z_1^2 * X_2 - Z_2^2 * X_1)^2 @@ -846,813 +922,848 @@ point_double(felem x_out, felem y_out, felem z_out, * This runs faster if 'mixed' is set, which requires Z_2 = 1 or Z_2 = 0. */ -/* This function is not entirely constant-time: - * it includes a branch for checking whether the two input points are equal, - * (while not equal to the point at infinity). - * This case never happens during single point multiplication, - * so there is no timing leak for ECDH or ECDSA signing. */ +/* + * This function is not entirely constant-time: it includes a branch for + * checking whether the two input points are equal, (while not equal to the + * point at infinity). This case never happens during single point + * multiplication, so there is no timing leak for ECDH or ECDSA signing. + */ static void point_add(felem x3, felem y3, felem z3, - const felem x1, const felem y1, const felem z1, - const int mixed, const felem x2, const felem y2, const felem z2) - { - felem ftmp, ftmp2, ftmp3, ftmp4, ftmp5, x_out, y_out, z_out; - widefelem tmp, tmp2; - limb z1_is_zero, z2_is_zero, x_equal, y_equal; - - if (!mixed) - { - /* ftmp2 = z2^2 */ - felem_square(tmp, z2); - felem_reduce(ftmp2, tmp); - - /* ftmp4 = z2^3 */ - felem_mul(tmp, ftmp2, z2); - felem_reduce(ftmp4, tmp); - - /* ftmp4 = z2^3*y1 */ - felem_mul(tmp2, ftmp4, y1); - felem_reduce(ftmp4, tmp2); - - /* ftmp2 = z2^2*x1 */ - felem_mul(tmp2, ftmp2, x1); - felem_reduce(ftmp2, tmp2); - } - else - { - /* We'll assume z2 = 1 (special case z2 = 0 is handled later) */ - - /* ftmp4 = z2^3*y1 */ - felem_assign(ftmp4, y1); - - /* ftmp2 = z2^2*x1 */ - felem_assign(ftmp2, x1); - } - - /* ftmp = z1^2 */ - felem_square(tmp, z1); - felem_reduce(ftmp, tmp); - - /* ftmp3 = z1^3 */ - felem_mul(tmp, ftmp, z1); - felem_reduce(ftmp3, tmp); - - /* tmp = z1^3*y2 */ - felem_mul(tmp, ftmp3, y2); - /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */ - - /* ftmp3 = z1^3*y2 - z2^3*y1 */ - felem_diff_128_64(tmp, ftmp4); - /* tmp[i] < 2^116 + 2^64 + 8 < 2^117 */ - felem_reduce(ftmp3, tmp); - - /* tmp = z1^2*x2 */ - felem_mul(tmp, ftmp, x2); - /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */ - - /* ftmp = z1^2*x2 - z2^2*x1 */ - felem_diff_128_64(tmp, ftmp2); - /* tmp[i] < 2^116 + 2^64 + 8 < 2^117 */ - felem_reduce(ftmp, tmp); - - /* the formulae are incorrect if the points are equal - * so we check for this and do doubling if this happens */ - x_equal = felem_is_zero(ftmp); - y_equal = felem_is_zero(ftmp3); - z1_is_zero = felem_is_zero(z1); - z2_is_zero = felem_is_zero(z2); - /* In affine coordinates, (X_1, Y_1) == (X_2, Y_2) */ - if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) - { - point_double(x3, y3, z3, x1, y1, z1); - return; - } - - /* ftmp5 = z1*z2 */ - if (!mixed) - { - felem_mul(tmp, z1, z2); - felem_reduce(ftmp5, tmp); - } - else - { - /* special case z2 = 0 is handled later */ - felem_assign(ftmp5, z1); - } - - /* z_out = (z1^2*x2 - z2^2*x1)*(z1*z2) */ - felem_mul(tmp, ftmp, ftmp5); - felem_reduce(z_out, tmp); - - /* ftmp = (z1^2*x2 - z2^2*x1)^2 */ - felem_assign(ftmp5, ftmp); - felem_square(tmp, ftmp); - felem_reduce(ftmp, tmp); - - /* ftmp5 = (z1^2*x2 - z2^2*x1)^3 */ - felem_mul(tmp, ftmp, ftmp5); - felem_reduce(ftmp5, tmp); - - /* ftmp2 = z2^2*x1*(z1^2*x2 - z2^2*x1)^2 */ - felem_mul(tmp, ftmp2, ftmp); - felem_reduce(ftmp2, tmp); - - /* tmp = z2^3*y1*(z1^2*x2 - z2^2*x1)^3 */ - felem_mul(tmp, ftmp4, ftmp5); - /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */ - - /* tmp2 = (z1^3*y2 - z2^3*y1)^2 */ - felem_square(tmp2, ftmp3); - /* tmp2[i] < 4 * 2^57 * 2^57 < 2^116 */ - - /* tmp2 = (z1^3*y2 - z2^3*y1)^2 - (z1^2*x2 - z2^2*x1)^3 */ - felem_diff_128_64(tmp2, ftmp5); - /* tmp2[i] < 2^116 + 2^64 + 8 < 2^117 */ - - /* ftmp5 = 2*z2^2*x1*(z1^2*x2 - z2^2*x1)^2 */ - felem_assign(ftmp5, ftmp2); - felem_scalar(ftmp5, 2); - /* ftmp5[i] < 2 * 2^57 = 2^58 */ - - /* x_out = (z1^3*y2 - z2^3*y1)^2 - (z1^2*x2 - z2^2*x1)^3 - - 2*z2^2*x1*(z1^2*x2 - z2^2*x1)^2 */ - felem_diff_128_64(tmp2, ftmp5); - /* tmp2[i] < 2^117 + 2^64 + 8 < 2^118 */ - felem_reduce(x_out, tmp2); - - /* ftmp2 = z2^2*x1*(z1^2*x2 - z2^2*x1)^2 - x_out */ - felem_diff(ftmp2, x_out); - /* ftmp2[i] < 2^57 + 2^58 + 2 < 2^59 */ - - /* tmp2 = (z1^3*y2 - z2^3*y1)*(z2^2*x1*(z1^2*x2 - z2^2*x1)^2 - x_out) */ - felem_mul(tmp2, ftmp3, ftmp2); - /* tmp2[i] < 4 * 2^57 * 2^59 = 2^118 */ - - /* y_out = (z1^3*y2 - z2^3*y1)*(z2^2*x1*(z1^2*x2 - z2^2*x1)^2 - x_out) - - z2^3*y1*(z1^2*x2 - z2^2*x1)^3 */ - widefelem_diff(tmp2, tmp); - /* tmp2[i] < 2^118 + 2^120 < 2^121 */ - felem_reduce(y_out, tmp2); - - /* the result (x_out, y_out, z_out) is incorrect if one of the inputs is - * the point at infinity, so we need to check for this separately */ - - /* if point 1 is at infinity, copy point 2 to output, and vice versa */ - copy_conditional(x_out, x2, z1_is_zero); - copy_conditional(x_out, x1, z2_is_zero); - copy_conditional(y_out, y2, z1_is_zero); - copy_conditional(y_out, y1, z2_is_zero); - copy_conditional(z_out, z2, z1_is_zero); - copy_conditional(z_out, z1, z2_is_zero); - felem_assign(x3, x_out); - felem_assign(y3, y_out); - felem_assign(z3, z_out); - } - -/* select_point selects the |idx|th point from a precomputation table and - * copies it to out. */ -static void select_point(const u64 idx, unsigned int size, const felem pre_comp[/*size*/][3], felem out[3]) - { - unsigned i, j; - limb *outlimbs = &out[0][0]; - memset(outlimbs, 0, 3 * sizeof(felem)); - - for (i = 0; i < size; i++) - { - const limb *inlimbs = &pre_comp[i][0][0]; - u64 mask = i ^ idx; - mask |= mask >> 4; - mask |= mask >> 2; - mask |= mask >> 1; - mask &= 1; - mask--; - for (j = 0; j < 4 * 3; j++) - outlimbs[j] |= inlimbs[j] & mask; - } - } + const felem x1, const felem y1, const felem z1, + const int mixed, const felem x2, const felem y2, + const felem z2) +{ + felem ftmp, ftmp2, ftmp3, ftmp4, ftmp5, x_out, y_out, z_out; + widefelem tmp, tmp2; + limb z1_is_zero, z2_is_zero, x_equal, y_equal; + + if (!mixed) { + /* ftmp2 = z2^2 */ + felem_square(tmp, z2); + felem_reduce(ftmp2, tmp); + + /* ftmp4 = z2^3 */ + felem_mul(tmp, ftmp2, z2); + felem_reduce(ftmp4, tmp); + + /* ftmp4 = z2^3*y1 */ + felem_mul(tmp2, ftmp4, y1); + felem_reduce(ftmp4, tmp2); + + /* ftmp2 = z2^2*x1 */ + felem_mul(tmp2, ftmp2, x1); + felem_reduce(ftmp2, tmp2); + } else { + /* + * We'll assume z2 = 1 (special case z2 = 0 is handled later) + */ + + /* ftmp4 = z2^3*y1 */ + felem_assign(ftmp4, y1); + + /* ftmp2 = z2^2*x1 */ + felem_assign(ftmp2, x1); + } + + /* ftmp = z1^2 */ + felem_square(tmp, z1); + felem_reduce(ftmp, tmp); + + /* ftmp3 = z1^3 */ + felem_mul(tmp, ftmp, z1); + felem_reduce(ftmp3, tmp); + + /* tmp = z1^3*y2 */ + felem_mul(tmp, ftmp3, y2); + /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */ + + /* ftmp3 = z1^3*y2 - z2^3*y1 */ + felem_diff_128_64(tmp, ftmp4); + /* tmp[i] < 2^116 + 2^64 + 8 < 2^117 */ + felem_reduce(ftmp3, tmp); + + /* tmp = z1^2*x2 */ + felem_mul(tmp, ftmp, x2); + /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */ + + /* ftmp = z1^2*x2 - z2^2*x1 */ + felem_diff_128_64(tmp, ftmp2); + /* tmp[i] < 2^116 + 2^64 + 8 < 2^117 */ + felem_reduce(ftmp, tmp); + + /* + * the formulae are incorrect if the points are equal so we check for + * this and do doubling if this happens + */ + x_equal = felem_is_zero(ftmp); + y_equal = felem_is_zero(ftmp3); + z1_is_zero = felem_is_zero(z1); + z2_is_zero = felem_is_zero(z2); + /* In affine coordinates, (X_1, Y_1) == (X_2, Y_2) */ + if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) { + point_double(x3, y3, z3, x1, y1, z1); + return; + } + + /* ftmp5 = z1*z2 */ + if (!mixed) { + felem_mul(tmp, z1, z2); + felem_reduce(ftmp5, tmp); + } else { + /* special case z2 = 0 is handled later */ + felem_assign(ftmp5, z1); + } + + /* z_out = (z1^2*x2 - z2^2*x1)*(z1*z2) */ + felem_mul(tmp, ftmp, ftmp5); + felem_reduce(z_out, tmp); + + /* ftmp = (z1^2*x2 - z2^2*x1)^2 */ + felem_assign(ftmp5, ftmp); + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + + /* ftmp5 = (z1^2*x2 - z2^2*x1)^3 */ + felem_mul(tmp, ftmp, ftmp5); + felem_reduce(ftmp5, tmp); + + /* ftmp2 = z2^2*x1*(z1^2*x2 - z2^2*x1)^2 */ + felem_mul(tmp, ftmp2, ftmp); + felem_reduce(ftmp2, tmp); + + /* tmp = z2^3*y1*(z1^2*x2 - z2^2*x1)^3 */ + felem_mul(tmp, ftmp4, ftmp5); + /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */ + + /* tmp2 = (z1^3*y2 - z2^3*y1)^2 */ + felem_square(tmp2, ftmp3); + /* tmp2[i] < 4 * 2^57 * 2^57 < 2^116 */ + + /* tmp2 = (z1^3*y2 - z2^3*y1)^2 - (z1^2*x2 - z2^2*x1)^3 */ + felem_diff_128_64(tmp2, ftmp5); + /* tmp2[i] < 2^116 + 2^64 + 8 < 2^117 */ + + /* ftmp5 = 2*z2^2*x1*(z1^2*x2 - z2^2*x1)^2 */ + felem_assign(ftmp5, ftmp2); + felem_scalar(ftmp5, 2); + /* ftmp5[i] < 2 * 2^57 = 2^58 */ + + /*- + * x_out = (z1^3*y2 - z2^3*y1)^2 - (z1^2*x2 - z2^2*x1)^3 - + * 2*z2^2*x1*(z1^2*x2 - z2^2*x1)^2 + */ + felem_diff_128_64(tmp2, ftmp5); + /* tmp2[i] < 2^117 + 2^64 + 8 < 2^118 */ + felem_reduce(x_out, tmp2); + + /* ftmp2 = z2^2*x1*(z1^2*x2 - z2^2*x1)^2 - x_out */ + felem_diff(ftmp2, x_out); + /* ftmp2[i] < 2^57 + 2^58 + 2 < 2^59 */ + + /* + * tmp2 = (z1^3*y2 - z2^3*y1)*(z2^2*x1*(z1^2*x2 - z2^2*x1)^2 - x_out) + */ + felem_mul(tmp2, ftmp3, ftmp2); + /* tmp2[i] < 4 * 2^57 * 2^59 = 2^118 */ + + /*- + * y_out = (z1^3*y2 - z2^3*y1)*(z2^2*x1*(z1^2*x2 - z2^2*x1)^2 - x_out) - + * z2^3*y1*(z1^2*x2 - z2^2*x1)^3 + */ + widefelem_diff(tmp2, tmp); + /* tmp2[i] < 2^118 + 2^120 < 2^121 */ + felem_reduce(y_out, tmp2); + + /* + * the result (x_out, y_out, z_out) is incorrect if one of the inputs is + * the point at infinity, so we need to check for this separately + */ + + /* + * if point 1 is at infinity, copy point 2 to output, and vice versa + */ + copy_conditional(x_out, x2, z1_is_zero); + copy_conditional(x_out, x1, z2_is_zero); + copy_conditional(y_out, y2, z1_is_zero); + copy_conditional(y_out, y1, z2_is_zero); + copy_conditional(z_out, z2, z1_is_zero); + copy_conditional(z_out, z1, z2_is_zero); + felem_assign(x3, x_out); + felem_assign(y3, y_out); + felem_assign(z3, z_out); +} + +/* + * select_point selects the |idx|th point from a precomputation table and + * copies it to out. + * The pre_comp array argument should be size of |size| argument + */ +static void select_point(const u64 idx, unsigned int size, + const felem pre_comp[][3], felem out[3]) +{ + unsigned i, j; + limb *outlimbs = &out[0][0]; + memset(outlimbs, 0, 3 * sizeof(felem)); + + for (i = 0; i < size; i++) { + const limb *inlimbs = &pre_comp[i][0][0]; + u64 mask = i ^ idx; + mask |= mask >> 4; + mask |= mask >> 2; + mask |= mask >> 1; + mask &= 1; + mask--; + for (j = 0; j < 4 * 3; j++) + outlimbs[j] |= inlimbs[j] & mask; + } +} /* get_bit returns the |i|th bit in |in| */ static char get_bit(const felem_bytearray in, unsigned i) - { - if (i >= 224) - return 0; - return (in[i >> 3] >> (i & 7)) & 1; - } - -/* Interleaved point multiplication using precomputed point multiples: - * The small point multiples 0*P, 1*P, ..., 16*P are in pre_comp[], - * the scalars in scalars[]. If g_scalar is non-NULL, we also add this multiple - * of the generator, using certain (large) precomputed multiples in g_pre_comp. - * Output point (X, Y, Z) is stored in x_out, y_out, z_out */ +{ + if (i >= 224) + return 0; + return (in[i >> 3] >> (i & 7)) & 1; +} + +/* + * Interleaved point multiplication using precomputed point multiples: The + * small point multiples 0*P, 1*P, ..., 16*P are in pre_comp[], the scalars + * in scalars[]. If g_scalar is non-NULL, we also add this multiple of the + * generator, using certain (large) precomputed multiples in g_pre_comp. + * Output point (X, Y, Z) is stored in x_out, y_out, z_out + */ static void batch_mul(felem x_out, felem y_out, felem z_out, - const felem_bytearray scalars[], const unsigned num_points, const u8 *g_scalar, - const int mixed, const felem pre_comp[][17][3], const felem g_pre_comp[2][16][3]) - { - int i, skip; - unsigned num; - unsigned gen_mul = (g_scalar != NULL); - felem nq[3], tmp[4]; - u64 bits; - u8 sign, digit; - - /* set nq to the point at infinity */ - memset(nq, 0, 3 * sizeof(felem)); - - /* Loop over all scalars msb-to-lsb, interleaving additions - * of multiples of the generator (two in each of the last 28 rounds) - * and additions of other points multiples (every 5th round). - */ - skip = 1; /* save two point operations in the first round */ - for (i = (num_points ? 220 : 27); i >= 0; --i) - { - /* double */ - if (!skip) - point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]); - - /* add multiples of the generator */ - if (gen_mul && (i <= 27)) - { - /* first, look 28 bits upwards */ - bits = get_bit(g_scalar, i + 196) << 3; - bits |= get_bit(g_scalar, i + 140) << 2; - bits |= get_bit(g_scalar, i + 84) << 1; - bits |= get_bit(g_scalar, i + 28); - /* select the point to add, in constant time */ - select_point(bits, 16, g_pre_comp[1], tmp); - - if (!skip) - { - point_add(nq[0], nq[1], nq[2], - nq[0], nq[1], nq[2], - 1 /* mixed */, tmp[0], tmp[1], tmp[2]); - } - else - { - memcpy(nq, tmp, 3 * sizeof(felem)); - skip = 0; - } - - /* second, look at the current position */ - bits = get_bit(g_scalar, i + 168) << 3; - bits |= get_bit(g_scalar, i + 112) << 2; - bits |= get_bit(g_scalar, i + 56) << 1; - bits |= get_bit(g_scalar, i); - /* select the point to add, in constant time */ - select_point(bits, 16, g_pre_comp[0], tmp); - point_add(nq[0], nq[1], nq[2], - nq[0], nq[1], nq[2], - 1 /* mixed */, tmp[0], tmp[1], tmp[2]); - } - - /* do other additions every 5 doublings */ - if (num_points && (i % 5 == 0)) - { - /* loop over all scalars */ - for (num = 0; num < num_points; ++num) - { - bits = get_bit(scalars[num], i + 4) << 5; - bits |= get_bit(scalars[num], i + 3) << 4; - bits |= get_bit(scalars[num], i + 2) << 3; - bits |= get_bit(scalars[num], i + 1) << 2; - bits |= get_bit(scalars[num], i) << 1; - bits |= get_bit(scalars[num], i - 1); - ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits); - - /* select the point to add or subtract */ - select_point(digit, 17, pre_comp[num], tmp); - felem_neg(tmp[3], tmp[1]); /* (X, -Y, Z) is the negative point */ - copy_conditional(tmp[1], tmp[3], sign); - - if (!skip) - { - point_add(nq[0], nq[1], nq[2], - nq[0], nq[1], nq[2], - mixed, tmp[0], tmp[1], tmp[2]); - } - else - { - memcpy(nq, tmp, 3 * sizeof(felem)); - skip = 0; - } - } - } - } - felem_assign(x_out, nq[0]); - felem_assign(y_out, nq[1]); - felem_assign(z_out, nq[2]); - } + const felem_bytearray scalars[], + const unsigned num_points, const u8 *g_scalar, + const int mixed, const felem pre_comp[][17][3], + const felem g_pre_comp[2][16][3]) +{ + int i, skip; + unsigned num; + unsigned gen_mul = (g_scalar != NULL); + felem nq[3], tmp[4]; + u64 bits; + u8 sign, digit; + + /* set nq to the point at infinity */ + memset(nq, 0, 3 * sizeof(felem)); + + /* + * Loop over all scalars msb-to-lsb, interleaving additions of multiples + * of the generator (two in each of the last 28 rounds) and additions of + * other points multiples (every 5th round). + */ + skip = 1; /* save two point operations in the first + * round */ + for (i = (num_points ? 220 : 27); i >= 0; --i) { + /* double */ + if (!skip) + point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]); + + /* add multiples of the generator */ + if (gen_mul && (i <= 27)) { + /* first, look 28 bits upwards */ + bits = get_bit(g_scalar, i + 196) << 3; + bits |= get_bit(g_scalar, i + 140) << 2; + bits |= get_bit(g_scalar, i + 84) << 1; + bits |= get_bit(g_scalar, i + 28); + /* select the point to add, in constant time */ + select_point(bits, 16, g_pre_comp[1], tmp); + + if (!skip) { + /* value 1 below is argument for "mixed" */ + point_add(nq[0], nq[1], nq[2], + nq[0], nq[1], nq[2], 1, tmp[0], tmp[1], tmp[2]); + } else { + memcpy(nq, tmp, 3 * sizeof(felem)); + skip = 0; + } + + /* second, look at the current position */ + bits = get_bit(g_scalar, i + 168) << 3; + bits |= get_bit(g_scalar, i + 112) << 2; + bits |= get_bit(g_scalar, i + 56) << 1; + bits |= get_bit(g_scalar, i); + /* select the point to add, in constant time */ + select_point(bits, 16, g_pre_comp[0], tmp); + point_add(nq[0], nq[1], nq[2], + nq[0], nq[1], nq[2], + 1 /* mixed */ , tmp[0], tmp[1], tmp[2]); + } + + /* do other additions every 5 doublings */ + if (num_points && (i % 5 == 0)) { + /* loop over all scalars */ + for (num = 0; num < num_points; ++num) { + bits = get_bit(scalars[num], i + 4) << 5; + bits |= get_bit(scalars[num], i + 3) << 4; + bits |= get_bit(scalars[num], i + 2) << 3; + bits |= get_bit(scalars[num], i + 1) << 2; + bits |= get_bit(scalars[num], i) << 1; + bits |= get_bit(scalars[num], i - 1); + ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits); + + /* select the point to add or subtract */ + select_point(digit, 17, pre_comp[num], tmp); + felem_neg(tmp[3], tmp[1]); /* (X, -Y, Z) is the negative + * point */ + copy_conditional(tmp[1], tmp[3], sign); + + if (!skip) { + point_add(nq[0], nq[1], nq[2], + nq[0], nq[1], nq[2], + mixed, tmp[0], tmp[1], tmp[2]); + } else { + memcpy(nq, tmp, 3 * sizeof(felem)); + skip = 0; + } + } + } + } + felem_assign(x_out, nq[0]); + felem_assign(y_out, nq[1]); + felem_assign(z_out, nq[2]); +} /******************************************************************************/ -/* FUNCTIONS TO MANAGE PRECOMPUTATION +/* + * FUNCTIONS TO MANAGE PRECOMPUTATION */ static NISTP224_PRE_COMP *nistp224_pre_comp_new() - { - NISTP224_PRE_COMP *ret = NULL; - ret = (NISTP224_PRE_COMP *) OPENSSL_malloc(sizeof *ret); - if (!ret) - { - ECerr(EC_F_NISTP224_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); - return ret; - } - memset(ret->g_pre_comp, 0, sizeof(ret->g_pre_comp)); - ret->references = 1; - return ret; - } +{ + NISTP224_PRE_COMP *ret = NULL; + ret = (NISTP224_PRE_COMP *) OPENSSL_malloc(sizeof *ret); + if (!ret) { + ECerr(EC_F_NISTP224_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + return ret; + } + memset(ret->g_pre_comp, 0, sizeof(ret->g_pre_comp)); + ret->references = 1; + return ret; +} static void *nistp224_pre_comp_dup(void *src_) - { - NISTP224_PRE_COMP *src = src_; +{ + NISTP224_PRE_COMP *src = src_; - /* no need to actually copy, these objects never change! */ - CRYPTO_add(&src->references, 1, CRYPTO_LOCK_EC_PRE_COMP); + /* no need to actually copy, these objects never change! */ + CRYPTO_add(&src->references, 1, CRYPTO_LOCK_EC_PRE_COMP); - return src_; - } + return src_; +} static void nistp224_pre_comp_free(void *pre_) - { - int i; - NISTP224_PRE_COMP *pre = pre_; +{ + int i; + NISTP224_PRE_COMP *pre = pre_; - if (!pre) - return; + if (!pre) + return; - i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP); - if (i > 0) - return; + i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP); + if (i > 0) + return; - OPENSSL_free(pre); - } + OPENSSL_free(pre); +} static void nistp224_pre_comp_clear_free(void *pre_) - { - int i; - NISTP224_PRE_COMP *pre = pre_; +{ + int i; + NISTP224_PRE_COMP *pre = pre_; - if (!pre) - return; + if (!pre) + return; - i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP); - if (i > 0) - return; + i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP); + if (i > 0) + return; - OPENSSL_cleanse(pre, sizeof *pre); - OPENSSL_free(pre); - } + OPENSSL_cleanse(pre, sizeof *pre); + OPENSSL_free(pre); +} /******************************************************************************/ -/* OPENSSL EC_METHOD FUNCTIONS +/* + * OPENSSL EC_METHOD FUNCTIONS */ int ec_GFp_nistp224_group_init(EC_GROUP *group) - { - int ret; - ret = ec_GFp_simple_group_init(group); - group->a_is_minus3 = 1; - return ret; - } +{ + int ret; + ret = ec_GFp_simple_group_init(group); + group->a_is_minus3 = 1; + return ret; +} int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p, - const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) - { - int ret = 0; - BN_CTX *new_ctx = NULL; - BIGNUM *curve_p, *curve_a, *curve_b; - - if (ctx == NULL) - if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0; - BN_CTX_start(ctx); - if (((curve_p = BN_CTX_get(ctx)) == NULL) || - ((curve_a = BN_CTX_get(ctx)) == NULL) || - ((curve_b = BN_CTX_get(ctx)) == NULL)) goto err; - BN_bin2bn(nistp224_curve_params[0], sizeof(felem_bytearray), curve_p); - BN_bin2bn(nistp224_curve_params[1], sizeof(felem_bytearray), curve_a); - BN_bin2bn(nistp224_curve_params[2], sizeof(felem_bytearray), curve_b); - if ((BN_cmp(curve_p, p)) || (BN_cmp(curve_a, a)) || - (BN_cmp(curve_b, b))) - { - ECerr(EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE, - EC_R_WRONG_CURVE_PARAMETERS); - goto err; - } - group->field_mod_func = BN_nist_mod_224; - ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); -err: - BN_CTX_end(ctx); - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - return ret; - } - -/* Takes the Jacobian coordinates (X, Y, Z) of a point and returns - * (X', Y') = (X/Z^2, Y/Z^3) */ + const BIGNUM *a, const BIGNUM *b, + BN_CTX *ctx) +{ + int ret = 0; + BN_CTX *new_ctx = NULL; + BIGNUM *curve_p, *curve_a, *curve_b; + + if (ctx == NULL) + if ((ctx = new_ctx = BN_CTX_new()) == NULL) + return 0; + BN_CTX_start(ctx); + if (((curve_p = BN_CTX_get(ctx)) == NULL) || + ((curve_a = BN_CTX_get(ctx)) == NULL) || + ((curve_b = BN_CTX_get(ctx)) == NULL)) + goto err; + BN_bin2bn(nistp224_curve_params[0], sizeof(felem_bytearray), curve_p); + BN_bin2bn(nistp224_curve_params[1], sizeof(felem_bytearray), curve_a); + BN_bin2bn(nistp224_curve_params[2], sizeof(felem_bytearray), curve_b); + if ((BN_cmp(curve_p, p)) || (BN_cmp(curve_a, a)) || (BN_cmp(curve_b, b))) { + ECerr(EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE, + EC_R_WRONG_CURVE_PARAMETERS); + goto err; + } + group->field_mod_func = BN_nist_mod_224; + ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); + err: + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; +} + +/* + * Takes the Jacobian coordinates (X, Y, Z) of a point and returns (X', Y') = + * (X/Z^2, Y/Z^3) + */ int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group, - const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx) - { - felem z1, z2, x_in, y_in, x_out, y_out; - widefelem tmp; - - if (EC_POINT_is_at_infinity(group, point)) - { - ECerr(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES, - EC_R_POINT_AT_INFINITY); - return 0; - } - if ((!BN_to_felem(x_in, &point->X)) || (!BN_to_felem(y_in, &point->Y)) || - (!BN_to_felem(z1, &point->Z))) return 0; - felem_inv(z2, z1); - felem_square(tmp, z2); felem_reduce(z1, tmp); - felem_mul(tmp, x_in, z1); felem_reduce(x_in, tmp); - felem_contract(x_out, x_in); - if (x != NULL) - { - if (!felem_to_BN(x, x_out)) { - ECerr(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES, - ERR_R_BN_LIB); - return 0; - } - } - felem_mul(tmp, z1, z2); felem_reduce(z1, tmp); - felem_mul(tmp, y_in, z1); felem_reduce(y_in, tmp); - felem_contract(y_out, y_in); - if (y != NULL) - { - if (!felem_to_BN(y, y_out)) { - ECerr(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES, - ERR_R_BN_LIB); - return 0; - } - } - return 1; - } - -static void make_points_affine(size_t num, felem points[/*num*/][3], felem tmp_felems[/*num+1*/]) - { - /* Runs in constant time, unless an input is the point at infinity - * (which normally shouldn't happen). */ - ec_GFp_nistp_points_make_affine_internal( - num, - points, - sizeof(felem), - tmp_felems, - (void (*)(void *)) felem_one, - (int (*)(const void *)) felem_is_zero_int, - (void (*)(void *, const void *)) felem_assign, - (void (*)(void *, const void *)) felem_square_reduce, - (void (*)(void *, const void *, const void *)) felem_mul_reduce, - (void (*)(void *, const void *)) felem_inv, - (void (*)(void *, const void *)) felem_contract); - } - -/* Computes scalar*generator + \sum scalars[i]*points[i], ignoring NULL values - * Result is stored in r (r can equal one of the inputs). */ + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx) +{ + felem z1, z2, x_in, y_in, x_out, y_out; + widefelem tmp; + + if (EC_POINT_is_at_infinity(group, point)) { + ECerr(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES, + EC_R_POINT_AT_INFINITY); + return 0; + } + if ((!BN_to_felem(x_in, &point->X)) || (!BN_to_felem(y_in, &point->Y)) || + (!BN_to_felem(z1, &point->Z))) + return 0; + felem_inv(z2, z1); + felem_square(tmp, z2); + felem_reduce(z1, tmp); + felem_mul(tmp, x_in, z1); + felem_reduce(x_in, tmp); + felem_contract(x_out, x_in); + if (x != NULL) { + if (!felem_to_BN(x, x_out)) { + ECerr(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES, + ERR_R_BN_LIB); + return 0; + } + } + felem_mul(tmp, z1, z2); + felem_reduce(z1, tmp); + felem_mul(tmp, y_in, z1); + felem_reduce(y_in, tmp); + felem_contract(y_out, y_in); + if (y != NULL) { + if (!felem_to_BN(y, y_out)) { + ECerr(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES, + ERR_R_BN_LIB); + return 0; + } + } + return 1; +} + +static void make_points_affine(size_t num, felem points[ /* num */ ][3], + felem tmp_felems[ /* num+1 */ ]) +{ + /* + * Runs in constant time, unless an input is the point at infinity (which + * normally shouldn't happen). + */ + ec_GFp_nistp_points_make_affine_internal(num, + points, + sizeof(felem), + tmp_felems, + (void (*)(void *))felem_one, + (int (*)(const void *)) + felem_is_zero_int, + (void (*)(void *, const void *)) + felem_assign, + (void (*)(void *, const void *)) + felem_square_reduce, (void (*) + (void *, + const void + *, + const void + *)) + felem_mul_reduce, + (void (*)(void *, const void *)) + felem_inv, + (void (*)(void *, const void *)) + felem_contract); +} + +/* + * Computes scalar*generator + \sum scalars[i]*points[i], ignoring NULL + * values Result is stored in r (r can equal one of the inputs). + */ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, - const BIGNUM *scalar, size_t num, const EC_POINT *points[], - const BIGNUM *scalars[], BN_CTX *ctx) - { - int ret = 0; - int j; - unsigned i; - int mixed = 0; - BN_CTX *new_ctx = NULL; - BIGNUM *x, *y, *z, *tmp_scalar; - felem_bytearray g_secret; - felem_bytearray *secrets = NULL; - felem (*pre_comp)[17][3] = NULL; - felem *tmp_felems = NULL; - felem_bytearray tmp; - unsigned num_bytes; - int have_pre_comp = 0; - size_t num_points = num; - felem x_in, y_in, z_in, x_out, y_out, z_out; - NISTP224_PRE_COMP *pre = NULL; - const felem (*g_pre_comp)[16][3] = NULL; - EC_POINT *generator = NULL; - const EC_POINT *p = NULL; - const BIGNUM *p_scalar = NULL; - - if (ctx == NULL) - if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0; - BN_CTX_start(ctx); - if (((x = BN_CTX_get(ctx)) == NULL) || - ((y = BN_CTX_get(ctx)) == NULL) || - ((z = BN_CTX_get(ctx)) == NULL) || - ((tmp_scalar = BN_CTX_get(ctx)) == NULL)) - goto err; - - if (scalar != NULL) - { - pre = EC_EX_DATA_get_data(group->extra_data, - nistp224_pre_comp_dup, nistp224_pre_comp_free, - nistp224_pre_comp_clear_free); - if (pre) - /* we have precomputation, try to use it */ - g_pre_comp = (const felem (*)[16][3]) pre->g_pre_comp; - else - /* try to use the standard precomputation */ - g_pre_comp = &gmul[0]; - generator = EC_POINT_new(group); - if (generator == NULL) - goto err; - /* get the generator from precomputation */ - if (!felem_to_BN(x, g_pre_comp[0][1][0]) || - !felem_to_BN(y, g_pre_comp[0][1][1]) || - !felem_to_BN(z, g_pre_comp[0][1][2])) - { - ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB); - goto err; - } - if (!EC_POINT_set_Jprojective_coordinates_GFp(group, - generator, x, y, z, ctx)) - goto err; - if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) - /* precomputation matches generator */ - have_pre_comp = 1; - else - /* we don't have valid precomputation: - * treat the generator as a random point */ - num_points = num_points + 1; - } - - if (num_points > 0) - { - if (num_points >= 3) - { - /* unless we precompute multiples for just one or two points, - * converting those into affine form is time well spent */ - mixed = 1; - } - secrets = OPENSSL_malloc(num_points * sizeof(felem_bytearray)); - pre_comp = OPENSSL_malloc(num_points * 17 * 3 * sizeof(felem)); - if (mixed) - tmp_felems = OPENSSL_malloc((num_points * 17 + 1) * sizeof(felem)); - if ((secrets == NULL) || (pre_comp == NULL) || (mixed && (tmp_felems == NULL))) - { - ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_MALLOC_FAILURE); - goto err; - } - - /* we treat NULL scalars as 0, and NULL points as points at infinity, - * i.e., they contribute nothing to the linear combination */ - memset(secrets, 0, num_points * sizeof(felem_bytearray)); - memset(pre_comp, 0, num_points * 17 * 3 * sizeof(felem)); - for (i = 0; i < num_points; ++i) - { - if (i == num) - /* the generator */ - { - p = EC_GROUP_get0_generator(group); - p_scalar = scalar; - } - else - /* the i^th point */ - { - p = points[i]; - p_scalar = scalars[i]; - } - if ((p_scalar != NULL) && (p != NULL)) - { - /* reduce scalar to 0 <= scalar < 2^224 */ - if ((BN_num_bits(p_scalar) > 224) || (BN_is_negative(p_scalar))) - { - /* this is an unusual input, and we don't guarantee - * constant-timeness */ - if (!BN_nnmod(tmp_scalar, p_scalar, &group->order, ctx)) - { - ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB); - goto err; - } - num_bytes = BN_bn2bin(tmp_scalar, tmp); - } - else - num_bytes = BN_bn2bin(p_scalar, tmp); - flip_endian(secrets[i], tmp, num_bytes); - /* precompute multiples */ - if ((!BN_to_felem(x_out, &p->X)) || - (!BN_to_felem(y_out, &p->Y)) || - (!BN_to_felem(z_out, &p->Z))) goto err; - felem_assign(pre_comp[i][1][0], x_out); - felem_assign(pre_comp[i][1][1], y_out); - felem_assign(pre_comp[i][1][2], z_out); - for (j = 2; j <= 16; ++j) - { - if (j & 1) - { - point_add( - pre_comp[i][j][0], pre_comp[i][j][1], pre_comp[i][j][2], - pre_comp[i][1][0], pre_comp[i][1][1], pre_comp[i][1][2], - 0, pre_comp[i][j-1][0], pre_comp[i][j-1][1], pre_comp[i][j-1][2]); - } - else - { - point_double( - pre_comp[i][j][0], pre_comp[i][j][1], pre_comp[i][j][2], - pre_comp[i][j/2][0], pre_comp[i][j/2][1], pre_comp[i][j/2][2]); - } - } - } - } - if (mixed) - make_points_affine(num_points * 17, pre_comp[0], tmp_felems); - } - - /* the scalar for the generator */ - if ((scalar != NULL) && (have_pre_comp)) - { - memset(g_secret, 0, sizeof g_secret); - /* reduce scalar to 0 <= scalar < 2^224 */ - if ((BN_num_bits(scalar) > 224) || (BN_is_negative(scalar))) - { - /* this is an unusual input, and we don't guarantee - * constant-timeness */ - if (!BN_nnmod(tmp_scalar, scalar, &group->order, ctx)) - { - ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB); - goto err; - } - num_bytes = BN_bn2bin(tmp_scalar, tmp); - } - else - num_bytes = BN_bn2bin(scalar, tmp); - flip_endian(g_secret, tmp, num_bytes); - /* do the multiplication with generator precomputation*/ - batch_mul(x_out, y_out, z_out, - (const felem_bytearray (*)) secrets, num_points, - g_secret, - mixed, (const felem (*)[17][3]) pre_comp, - g_pre_comp); - } - else - /* do the multiplication without generator precomputation */ - batch_mul(x_out, y_out, z_out, - (const felem_bytearray (*)) secrets, num_points, - NULL, mixed, (const felem (*)[17][3]) pre_comp, NULL); - /* reduce the output to its unique minimal representation */ - felem_contract(x_in, x_out); - felem_contract(y_in, y_out); - felem_contract(z_in, z_out); - if ((!felem_to_BN(x, x_in)) || (!felem_to_BN(y, y_in)) || - (!felem_to_BN(z, z_in))) - { - ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB); - goto err; - } - ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx); - -err: - BN_CTX_end(ctx); - if (generator != NULL) - EC_POINT_free(generator); - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - if (secrets != NULL) - OPENSSL_free(secrets); - if (pre_comp != NULL) - OPENSSL_free(pre_comp); - if (tmp_felems != NULL) - OPENSSL_free(tmp_felems); - return ret; - } + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], + const BIGNUM *scalars[], BN_CTX *ctx) +{ + int ret = 0; + int j; + unsigned i; + int mixed = 0; + BN_CTX *new_ctx = NULL; + BIGNUM *x, *y, *z, *tmp_scalar; + felem_bytearray g_secret; + felem_bytearray *secrets = NULL; + felem(*pre_comp)[17][3] = NULL; + felem *tmp_felems = NULL; + felem_bytearray tmp; + unsigned num_bytes; + int have_pre_comp = 0; + size_t num_points = num; + felem x_in, y_in, z_in, x_out, y_out, z_out; + NISTP224_PRE_COMP *pre = NULL; + const felem(*g_pre_comp)[16][3] = NULL; + EC_POINT *generator = NULL; + const EC_POINT *p = NULL; + const BIGNUM *p_scalar = NULL; + + if (ctx == NULL) + if ((ctx = new_ctx = BN_CTX_new()) == NULL) + return 0; + BN_CTX_start(ctx); + if (((x = BN_CTX_get(ctx)) == NULL) || + ((y = BN_CTX_get(ctx)) == NULL) || + ((z = BN_CTX_get(ctx)) == NULL) || + ((tmp_scalar = BN_CTX_get(ctx)) == NULL)) + goto err; + + if (scalar != NULL) { + pre = EC_EX_DATA_get_data(group->extra_data, + nistp224_pre_comp_dup, + nistp224_pre_comp_free, + nistp224_pre_comp_clear_free); + if (pre) + /* we have precomputation, try to use it */ + g_pre_comp = (const felem(*)[16][3])pre->g_pre_comp; + else + /* try to use the standard precomputation */ + g_pre_comp = &gmul[0]; + generator = EC_POINT_new(group); + if (generator == NULL) + goto err; + /* get the generator from precomputation */ + if (!felem_to_BN(x, g_pre_comp[0][1][0]) || + !felem_to_BN(y, g_pre_comp[0][1][1]) || + !felem_to_BN(z, g_pre_comp[0][1][2])) { + ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB); + goto err; + } + if (!EC_POINT_set_Jprojective_coordinates_GFp(group, + generator, x, y, z, + ctx)) + goto err; + if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) + /* precomputation matches generator */ + have_pre_comp = 1; + else + /* + * we don't have valid precomputation: treat the generator as a + * random point + */ + num_points = num_points + 1; + } + + if (num_points > 0) { + if (num_points >= 3) { + /* + * unless we precompute multiples for just one or two points, + * converting those into affine form is time well spent + */ + mixed = 1; + } + secrets = OPENSSL_malloc(num_points * sizeof(felem_bytearray)); + pre_comp = OPENSSL_malloc(num_points * 17 * 3 * sizeof(felem)); + if (mixed) + tmp_felems = + OPENSSL_malloc((num_points * 17 + 1) * sizeof(felem)); + if ((secrets == NULL) || (pre_comp == NULL) + || (mixed && (tmp_felems == NULL))) { + ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* + * we treat NULL scalars as 0, and NULL points as points at infinity, + * i.e., they contribute nothing to the linear combination + */ + memset(secrets, 0, num_points * sizeof(felem_bytearray)); + memset(pre_comp, 0, num_points * 17 * 3 * sizeof(felem)); + for (i = 0; i < num_points; ++i) { + if (i == num) + /* the generator */ + { + p = EC_GROUP_get0_generator(group); + p_scalar = scalar; + } else + /* the i^th point */ + { + p = points[i]; + p_scalar = scalars[i]; + } + if ((p_scalar != NULL) && (p != NULL)) { + /* reduce scalar to 0 <= scalar < 2^224 */ + if ((BN_num_bits(p_scalar) > 224) + || (BN_is_negative(p_scalar))) { + /* + * this is an unusual input, and we don't guarantee + * constant-timeness + */ + if (!BN_nnmod(tmp_scalar, p_scalar, &group->order, ctx)) { + ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB); + goto err; + } + num_bytes = BN_bn2bin(tmp_scalar, tmp); + } else + num_bytes = BN_bn2bin(p_scalar, tmp); + flip_endian(secrets[i], tmp, num_bytes); + /* precompute multiples */ + if ((!BN_to_felem(x_out, &p->X)) || + (!BN_to_felem(y_out, &p->Y)) || + (!BN_to_felem(z_out, &p->Z))) + goto err; + felem_assign(pre_comp[i][1][0], x_out); + felem_assign(pre_comp[i][1][1], y_out); + felem_assign(pre_comp[i][1][2], z_out); + for (j = 2; j <= 16; ++j) { + if (j & 1) { + point_add(pre_comp[i][j][0], pre_comp[i][j][1], + pre_comp[i][j][2], pre_comp[i][1][0], + pre_comp[i][1][1], pre_comp[i][1][2], 0, + pre_comp[i][j - 1][0], + pre_comp[i][j - 1][1], + pre_comp[i][j - 1][2]); + } else { + point_double(pre_comp[i][j][0], pre_comp[i][j][1], + pre_comp[i][j][2], pre_comp[i][j / 2][0], + pre_comp[i][j / 2][1], + pre_comp[i][j / 2][2]); + } + } + } + } + if (mixed) + make_points_affine(num_points * 17, pre_comp[0], tmp_felems); + } + + /* the scalar for the generator */ + if ((scalar != NULL) && (have_pre_comp)) { + memset(g_secret, 0, sizeof g_secret); + /* reduce scalar to 0 <= scalar < 2^224 */ + if ((BN_num_bits(scalar) > 224) || (BN_is_negative(scalar))) { + /* + * this is an unusual input, and we don't guarantee + * constant-timeness + */ + if (!BN_nnmod(tmp_scalar, scalar, &group->order, ctx)) { + ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB); + goto err; + } + num_bytes = BN_bn2bin(tmp_scalar, tmp); + } else + num_bytes = BN_bn2bin(scalar, tmp); + flip_endian(g_secret, tmp, num_bytes); + /* do the multiplication with generator precomputation */ + batch_mul(x_out, y_out, z_out, + (const felem_bytearray(*))secrets, num_points, + g_secret, + mixed, (const felem(*)[17][3])pre_comp, g_pre_comp); + } else + /* do the multiplication without generator precomputation */ + batch_mul(x_out, y_out, z_out, + (const felem_bytearray(*))secrets, num_points, + NULL, mixed, (const felem(*)[17][3])pre_comp, NULL); + /* reduce the output to its unique minimal representation */ + felem_contract(x_in, x_out); + felem_contract(y_in, y_out); + felem_contract(z_in, z_out); + if ((!felem_to_BN(x, x_in)) || (!felem_to_BN(y, y_in)) || + (!felem_to_BN(z, z_in))) { + ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB); + goto err; + } + ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx); + + err: + BN_CTX_end(ctx); + if (generator != NULL) + EC_POINT_free(generator); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + if (secrets != NULL) + OPENSSL_free(secrets); + if (pre_comp != NULL) + OPENSSL_free(pre_comp); + if (tmp_felems != NULL) + OPENSSL_free(tmp_felems); + return ret; +} int ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx) - { - int ret = 0; - NISTP224_PRE_COMP *pre = NULL; - int i, j; - BN_CTX *new_ctx = NULL; - BIGNUM *x, *y; - EC_POINT *generator = NULL; - felem tmp_felems[32]; - - /* throw away old precomputation */ - EC_EX_DATA_free_data(&group->extra_data, nistp224_pre_comp_dup, - nistp224_pre_comp_free, nistp224_pre_comp_clear_free); - if (ctx == NULL) - if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0; - BN_CTX_start(ctx); - if (((x = BN_CTX_get(ctx)) == NULL) || - ((y = BN_CTX_get(ctx)) == NULL)) - goto err; - /* get the generator */ - if (group->generator == NULL) goto err; - generator = EC_POINT_new(group); - if (generator == NULL) - goto err; - BN_bin2bn(nistp224_curve_params[3], sizeof (felem_bytearray), x); - BN_bin2bn(nistp224_curve_params[4], sizeof (felem_bytearray), y); - if (!EC_POINT_set_affine_coordinates_GFp(group, generator, x, y, ctx)) - goto err; - if ((pre = nistp224_pre_comp_new()) == NULL) - goto err; - /* if the generator is the standard one, use built-in precomputation */ - if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) - { - memcpy(pre->g_pre_comp, gmul, sizeof(pre->g_pre_comp)); - ret = 1; - goto err; - } - if ((!BN_to_felem(pre->g_pre_comp[0][1][0], &group->generator->X)) || - (!BN_to_felem(pre->g_pre_comp[0][1][1], &group->generator->Y)) || - (!BN_to_felem(pre->g_pre_comp[0][1][2], &group->generator->Z))) - goto err; - /* compute 2^56*G, 2^112*G, 2^168*G for the first table, - * 2^28*G, 2^84*G, 2^140*G, 2^196*G for the second one - */ - for (i = 1; i <= 8; i <<= 1) - { - point_double( - pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2], - pre->g_pre_comp[0][i][0], pre->g_pre_comp[0][i][1], pre->g_pre_comp[0][i][2]); - for (j = 0; j < 27; ++j) - { - point_double( - pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2], - pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2]); - } - if (i == 8) - break; - point_double( - pre->g_pre_comp[0][2*i][0], pre->g_pre_comp[0][2*i][1], pre->g_pre_comp[0][2*i][2], - pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2]); - for (j = 0; j < 27; ++j) - { - point_double( - pre->g_pre_comp[0][2*i][0], pre->g_pre_comp[0][2*i][1], pre->g_pre_comp[0][2*i][2], - pre->g_pre_comp[0][2*i][0], pre->g_pre_comp[0][2*i][1], pre->g_pre_comp[0][2*i][2]); - } - } - for (i = 0; i < 2; i++) - { - /* g_pre_comp[i][0] is the point at infinity */ - memset(pre->g_pre_comp[i][0], 0, sizeof(pre->g_pre_comp[i][0])); - /* the remaining multiples */ - /* 2^56*G + 2^112*G resp. 2^84*G + 2^140*G */ - point_add( - pre->g_pre_comp[i][6][0], pre->g_pre_comp[i][6][1], - pre->g_pre_comp[i][6][2], pre->g_pre_comp[i][4][0], - pre->g_pre_comp[i][4][1], pre->g_pre_comp[i][4][2], - 0, pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], - pre->g_pre_comp[i][2][2]); - /* 2^56*G + 2^168*G resp. 2^84*G + 2^196*G */ - point_add( - pre->g_pre_comp[i][10][0], pre->g_pre_comp[i][10][1], - pre->g_pre_comp[i][10][2], pre->g_pre_comp[i][8][0], - pre->g_pre_comp[i][8][1], pre->g_pre_comp[i][8][2], - 0, pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], - pre->g_pre_comp[i][2][2]); - /* 2^112*G + 2^168*G resp. 2^140*G + 2^196*G */ - point_add( - pre->g_pre_comp[i][12][0], pre->g_pre_comp[i][12][1], - pre->g_pre_comp[i][12][2], pre->g_pre_comp[i][8][0], - pre->g_pre_comp[i][8][1], pre->g_pre_comp[i][8][2], - 0, pre->g_pre_comp[i][4][0], pre->g_pre_comp[i][4][1], - pre->g_pre_comp[i][4][2]); - /* 2^56*G + 2^112*G + 2^168*G resp. 2^84*G + 2^140*G + 2^196*G */ - point_add( - pre->g_pre_comp[i][14][0], pre->g_pre_comp[i][14][1], - pre->g_pre_comp[i][14][2], pre->g_pre_comp[i][12][0], - pre->g_pre_comp[i][12][1], pre->g_pre_comp[i][12][2], - 0, pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], - pre->g_pre_comp[i][2][2]); - for (j = 1; j < 8; ++j) - { - /* odd multiples: add G resp. 2^28*G */ - point_add( - pre->g_pre_comp[i][2*j+1][0], pre->g_pre_comp[i][2*j+1][1], - pre->g_pre_comp[i][2*j+1][2], pre->g_pre_comp[i][2*j][0], - pre->g_pre_comp[i][2*j][1], pre->g_pre_comp[i][2*j][2], - 0, pre->g_pre_comp[i][1][0], pre->g_pre_comp[i][1][1], - pre->g_pre_comp[i][1][2]); - } - } - make_points_affine(31, &(pre->g_pre_comp[0][1]), tmp_felems); - - if (!EC_EX_DATA_set_data(&group->extra_data, pre, nistp224_pre_comp_dup, - nistp224_pre_comp_free, nistp224_pre_comp_clear_free)) - goto err; - ret = 1; - pre = NULL; +{ + int ret = 0; + NISTP224_PRE_COMP *pre = NULL; + int i, j; + BN_CTX *new_ctx = NULL; + BIGNUM *x, *y; + EC_POINT *generator = NULL; + felem tmp_felems[32]; + + /* throw away old precomputation */ + EC_EX_DATA_free_data(&group->extra_data, nistp224_pre_comp_dup, + nistp224_pre_comp_free, + nistp224_pre_comp_clear_free); + if (ctx == NULL) + if ((ctx = new_ctx = BN_CTX_new()) == NULL) + return 0; + BN_CTX_start(ctx); + if (((x = BN_CTX_get(ctx)) == NULL) || ((y = BN_CTX_get(ctx)) == NULL)) + goto err; + /* get the generator */ + if (group->generator == NULL) + goto err; + generator = EC_POINT_new(group); + if (generator == NULL) + goto err; + BN_bin2bn(nistp224_curve_params[3], sizeof(felem_bytearray), x); + BN_bin2bn(nistp224_curve_params[4], sizeof(felem_bytearray), y); + if (!EC_POINT_set_affine_coordinates_GFp(group, generator, x, y, ctx)) + goto err; + if ((pre = nistp224_pre_comp_new()) == NULL) + goto err; + /* + * if the generator is the standard one, use built-in precomputation + */ + if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) { + memcpy(pre->g_pre_comp, gmul, sizeof(pre->g_pre_comp)); + ret = 1; + goto err; + } + if ((!BN_to_felem(pre->g_pre_comp[0][1][0], &group->generator->X)) || + (!BN_to_felem(pre->g_pre_comp[0][1][1], &group->generator->Y)) || + (!BN_to_felem(pre->g_pre_comp[0][1][2], &group->generator->Z))) + goto err; + /* + * compute 2^56*G, 2^112*G, 2^168*G for the first table, 2^28*G, 2^84*G, + * 2^140*G, 2^196*G for the second one + */ + for (i = 1; i <= 8; i <<= 1) { + point_double(pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], + pre->g_pre_comp[1][i][2], pre->g_pre_comp[0][i][0], + pre->g_pre_comp[0][i][1], pre->g_pre_comp[0][i][2]); + for (j = 0; j < 27; ++j) { + point_double(pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], + pre->g_pre_comp[1][i][2], pre->g_pre_comp[1][i][0], + pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2]); + } + if (i == 8) + break; + point_double(pre->g_pre_comp[0][2 * i][0], + pre->g_pre_comp[0][2 * i][1], + pre->g_pre_comp[0][2 * i][2], pre->g_pre_comp[1][i][0], + pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2]); + for (j = 0; j < 27; ++j) { + point_double(pre->g_pre_comp[0][2 * i][0], + pre->g_pre_comp[0][2 * i][1], + pre->g_pre_comp[0][2 * i][2], + pre->g_pre_comp[0][2 * i][0], + pre->g_pre_comp[0][2 * i][1], + pre->g_pre_comp[0][2 * i][2]); + } + } + for (i = 0; i < 2; i++) { + /* g_pre_comp[i][0] is the point at infinity */ + memset(pre->g_pre_comp[i][0], 0, sizeof(pre->g_pre_comp[i][0])); + /* the remaining multiples */ + /* 2^56*G + 2^112*G resp. 2^84*G + 2^140*G */ + point_add(pre->g_pre_comp[i][6][0], pre->g_pre_comp[i][6][1], + pre->g_pre_comp[i][6][2], pre->g_pre_comp[i][4][0], + pre->g_pre_comp[i][4][1], pre->g_pre_comp[i][4][2], + 0, pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], + pre->g_pre_comp[i][2][2]); + /* 2^56*G + 2^168*G resp. 2^84*G + 2^196*G */ + point_add(pre->g_pre_comp[i][10][0], pre->g_pre_comp[i][10][1], + pre->g_pre_comp[i][10][2], pre->g_pre_comp[i][8][0], + pre->g_pre_comp[i][8][1], pre->g_pre_comp[i][8][2], + 0, pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], + pre->g_pre_comp[i][2][2]); + /* 2^112*G + 2^168*G resp. 2^140*G + 2^196*G */ + point_add(pre->g_pre_comp[i][12][0], pre->g_pre_comp[i][12][1], + pre->g_pre_comp[i][12][2], pre->g_pre_comp[i][8][0], + pre->g_pre_comp[i][8][1], pre->g_pre_comp[i][8][2], + 0, pre->g_pre_comp[i][4][0], pre->g_pre_comp[i][4][1], + pre->g_pre_comp[i][4][2]); + /* + * 2^56*G + 2^112*G + 2^168*G resp. 2^84*G + 2^140*G + 2^196*G + */ + point_add(pre->g_pre_comp[i][14][0], pre->g_pre_comp[i][14][1], + pre->g_pre_comp[i][14][2], pre->g_pre_comp[i][12][0], + pre->g_pre_comp[i][12][1], pre->g_pre_comp[i][12][2], + 0, pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], + pre->g_pre_comp[i][2][2]); + for (j = 1; j < 8; ++j) { + /* odd multiples: add G resp. 2^28*G */ + point_add(pre->g_pre_comp[i][2 * j + 1][0], + pre->g_pre_comp[i][2 * j + 1][1], + pre->g_pre_comp[i][2 * j + 1][2], + pre->g_pre_comp[i][2 * j][0], + pre->g_pre_comp[i][2 * j][1], + pre->g_pre_comp[i][2 * j][2], 0, + pre->g_pre_comp[i][1][0], pre->g_pre_comp[i][1][1], + pre->g_pre_comp[i][1][2]); + } + } + make_points_affine(31, &(pre->g_pre_comp[0][1]), tmp_felems); + + if (!EC_EX_DATA_set_data(&group->extra_data, pre, nistp224_pre_comp_dup, + nistp224_pre_comp_free, + nistp224_pre_comp_clear_free)) + goto err; + ret = 1; + pre = NULL; err: - BN_CTX_end(ctx); - if (generator != NULL) - EC_POINT_free(generator); - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - if (pre) - nistp224_pre_comp_free(pre); - return ret; - } + BN_CTX_end(ctx); + if (generator != NULL) + EC_POINT_free(generator); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + if (pre) + nistp224_pre_comp_free(pre); + return ret; +} int ec_GFp_nistp224_have_precompute_mult(const EC_GROUP *group) - { - if (EC_EX_DATA_get_data(group->extra_data, nistp224_pre_comp_dup, - nistp224_pre_comp_free, nistp224_pre_comp_clear_free) - != NULL) - return 1; - else - return 0; - } +{ + if (EC_EX_DATA_get_data(group->extra_data, nistp224_pre_comp_dup, + nistp224_pre_comp_free, + nistp224_pre_comp_clear_free) + != NULL) + return 1; + else + return 0; +} #else -static void *dummy=&dummy; +static void *dummy = &dummy; #endif diff --git a/openssl/crypto/ec/ecp_nistp256.c b/openssl/crypto/ec/ecp_nistp256.c index b884f73d3..a5887086c 100644 --- a/openssl/crypto/ec/ecp_nistp256.c +++ b/openssl/crypto/ec/ecp_nistp256.c @@ -29,62 +29,67 @@ #include <openssl/opensslconf.h> #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 -#ifndef OPENSSL_SYS_VMS -#include <stdint.h> -#else -#include <inttypes.h> -#endif +# ifndef OPENSSL_SYS_VMS +# include <stdint.h> +# else +# include <inttypes.h> +# endif -#include <string.h> -#include <openssl/err.h> -#include "ec_lcl.h" +# include <string.h> +# include <openssl/err.h> +# include "ec_lcl.h" -#if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +# if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) /* even with gcc, the typedef won't work for 32-bit platforms */ - typedef __uint128_t uint128_t; /* nonstandard; implemented by gcc on 64-bit platforms */ - typedef __int128_t int128_t; -#else - #error "Need GCC 3.1 or later to define type uint128_t" -#endif +typedef __uint128_t uint128_t; /* nonstandard; implemented by gcc on 64-bit + * platforms */ +typedef __int128_t int128_t; +# else +# error "Need GCC 3.1 or later to define type uint128_t" +# endif typedef uint8_t u8; typedef uint32_t u32; typedef uint64_t u64; typedef int64_t s64; -/* The underlying field. - * - * P256 operates over GF(2^256-2^224+2^192+2^96-1). We can serialise an element - * of this field into 32 bytes. We call this an felem_bytearray. */ +/* + * The underlying field. P256 operates over GF(2^256-2^224+2^192+2^96-1). We + * can serialise an element of this field into 32 bytes. We call this an + * felem_bytearray. + */ typedef u8 felem_bytearray[32]; -/* These are the parameters of P256, taken from FIPS 186-3, page 86. These - * values are big-endian. */ +/* + * These are the parameters of P256, taken from FIPS 186-3, page 86. These + * values are big-endian. + */ static const felem_bytearray nistp256_curve_params[5] = { - {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, /* p */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, /* a = -3 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc}, /* b */ - {0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, - 0xb3, 0xeb, 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, - 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 0xb0, 0xf6, - 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b}, - {0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, /* x */ - 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, - 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, - 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96}, - {0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, /* y */ - 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, - 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, - 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5} + {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, /* p */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, /* a = -3 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc}, /* b */ + {0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, + 0xb3, 0xeb, 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, + 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 0xb0, 0xf6, + 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b}, + {0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, /* x */ + 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, + 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, + 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96}, + {0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, /* y */ + 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, + 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, + 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5} }; -/* The representation of field elements. +/*- + * The representation of field elements. * ------------------------------------ * * We represent field elements with either four 128-bit values, eight 128-bit @@ -104,7 +109,7 @@ static const felem_bytearray nistp256_curve_params[5] = { * values are used as intermediate values before multiplication. */ -#define NLIMBS 4 +# define NLIMBS 4 typedef uint128_t limb; typedef limb felem[NLIMBS]; @@ -112,188 +117,199 @@ typedef limb longfelem[NLIMBS * 2]; typedef u64 smallfelem[NLIMBS]; /* This is the value of the prime as four 64-bit words, little-endian. */ -static const u64 kPrime[4] = { 0xfffffffffffffffful, 0xffffffff, 0, 0xffffffff00000001ul }; +static const u64 kPrime[4] = + { 0xfffffffffffffffful, 0xffffffff, 0, 0xffffffff00000001ul }; static const u64 bottom63bits = 0x7ffffffffffffffful; -/* bin32_to_felem takes a little-endian byte array and converts it into felem - * form. This assumes that the CPU is little-endian. */ +/* + * bin32_to_felem takes a little-endian byte array and converts it into felem + * form. This assumes that the CPU is little-endian. + */ static void bin32_to_felem(felem out, const u8 in[32]) - { - out[0] = *((u64*) &in[0]); - out[1] = *((u64*) &in[8]); - out[2] = *((u64*) &in[16]); - out[3] = *((u64*) &in[24]); - } - -/* smallfelem_to_bin32 takes a smallfelem and serialises into a little endian, - * 32 byte array. This assumes that the CPU is little-endian. */ +{ + out[0] = *((u64 *)&in[0]); + out[1] = *((u64 *)&in[8]); + out[2] = *((u64 *)&in[16]); + out[3] = *((u64 *)&in[24]); +} + +/* + * smallfelem_to_bin32 takes a smallfelem and serialises into a little + * endian, 32 byte array. This assumes that the CPU is little-endian. + */ static void smallfelem_to_bin32(u8 out[32], const smallfelem in) - { - *((u64*) &out[0]) = in[0]; - *((u64*) &out[8]) = in[1]; - *((u64*) &out[16]) = in[2]; - *((u64*) &out[24]) = in[3]; - } +{ + *((u64 *)&out[0]) = in[0]; + *((u64 *)&out[8]) = in[1]; + *((u64 *)&out[16]) = in[2]; + *((u64 *)&out[24]) = in[3]; +} /* To preserve endianness when using BN_bn2bin and BN_bin2bn */ static void flip_endian(u8 *out, const u8 *in, unsigned len) - { - unsigned i; - for (i = 0; i < len; ++i) - out[i] = in[len-1-i]; - } +{ + unsigned i; + for (i = 0; i < len; ++i) + out[i] = in[len - 1 - i]; +} /* BN_to_felem converts an OpenSSL BIGNUM into an felem */ static int BN_to_felem(felem out, const BIGNUM *bn) - { - felem_bytearray b_in; - felem_bytearray b_out; - unsigned num_bytes; - - /* BN_bn2bin eats leading zeroes */ - memset(b_out, 0, sizeof b_out); - num_bytes = BN_num_bytes(bn); - if (num_bytes > sizeof b_out) - { - ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); - return 0; - } - if (BN_is_negative(bn)) - { - ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); - return 0; - } - num_bytes = BN_bn2bin(bn, b_in); - flip_endian(b_out, b_in, num_bytes); - bin32_to_felem(out, b_out); - return 1; - } +{ + felem_bytearray b_in; + felem_bytearray b_out; + unsigned num_bytes; + + /* BN_bn2bin eats leading zeroes */ + memset(b_out, 0, sizeof b_out); + num_bytes = BN_num_bytes(bn); + if (num_bytes > sizeof b_out) { + ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); + return 0; + } + if (BN_is_negative(bn)) { + ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); + return 0; + } + num_bytes = BN_bn2bin(bn, b_in); + flip_endian(b_out, b_in, num_bytes); + bin32_to_felem(out, b_out); + return 1; +} /* felem_to_BN converts an felem into an OpenSSL BIGNUM */ static BIGNUM *smallfelem_to_BN(BIGNUM *out, const smallfelem in) - { - felem_bytearray b_in, b_out; - smallfelem_to_bin32(b_in, in); - flip_endian(b_out, b_in, sizeof b_out); - return BN_bin2bn(b_out, sizeof b_out, out); - } - - -/* Field operations - * ---------------- */ +{ + felem_bytearray b_in, b_out; + smallfelem_to_bin32(b_in, in); + flip_endian(b_out, b_in, sizeof b_out); + return BN_bin2bn(b_out, sizeof b_out, out); +} + +/*- + * Field operations + * ---------------- + */ static void smallfelem_one(smallfelem out) - { - out[0] = 1; - out[1] = 0; - out[2] = 0; - out[3] = 0; - } +{ + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 0; +} static void smallfelem_assign(smallfelem out, const smallfelem in) - { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - } +{ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; +} static void felem_assign(felem out, const felem in) - { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - } +{ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; +} /* felem_sum sets out = out + in. */ static void felem_sum(felem out, const felem in) - { - out[0] += in[0]; - out[1] += in[1]; - out[2] += in[2]; - out[3] += in[3]; - } +{ + out[0] += in[0]; + out[1] += in[1]; + out[2] += in[2]; + out[3] += in[3]; +} /* felem_small_sum sets out = out + in. */ static void felem_small_sum(felem out, const smallfelem in) - { - out[0] += in[0]; - out[1] += in[1]; - out[2] += in[2]; - out[3] += in[3]; - } +{ + out[0] += in[0]; + out[1] += in[1]; + out[2] += in[2]; + out[3] += in[3]; +} /* felem_scalar sets out = out * scalar */ static void felem_scalar(felem out, const u64 scalar) - { - out[0] *= scalar; - out[1] *= scalar; - out[2] *= scalar; - out[3] *= scalar; - } +{ + out[0] *= scalar; + out[1] *= scalar; + out[2] *= scalar; + out[3] *= scalar; +} /* longfelem_scalar sets out = out * scalar */ static void longfelem_scalar(longfelem out, const u64 scalar) - { - out[0] *= scalar; - out[1] *= scalar; - out[2] *= scalar; - out[3] *= scalar; - out[4] *= scalar; - out[5] *= scalar; - out[6] *= scalar; - out[7] *= scalar; - } - -#define two105m41m9 (((limb)1) << 105) - (((limb)1) << 41) - (((limb)1) << 9) -#define two105 (((limb)1) << 105) -#define two105m41p9 (((limb)1) << 105) - (((limb)1) << 41) + (((limb)1) << 9) +{ + out[0] *= scalar; + out[1] *= scalar; + out[2] *= scalar; + out[3] *= scalar; + out[4] *= scalar; + out[5] *= scalar; + out[6] *= scalar; + out[7] *= scalar; +} + +# define two105m41m9 (((limb)1) << 105) - (((limb)1) << 41) - (((limb)1) << 9) +# define two105 (((limb)1) << 105) +# define two105m41p9 (((limb)1) << 105) - (((limb)1) << 41) + (((limb)1) << 9) /* zero105 is 0 mod p */ -static const felem zero105 = { two105m41m9, two105, two105m41p9, two105m41p9 }; +static const felem zero105 = + { two105m41m9, two105, two105m41p9, two105m41p9 }; -/* smallfelem_neg sets |out| to |-small| +/*- + * smallfelem_neg sets |out| to |-small| * On exit: * out[i] < out[i] + 2^105 */ static void smallfelem_neg(felem out, const smallfelem small) - { - /* In order to prevent underflow, we subtract from 0 mod p. */ - out[0] = zero105[0] - small[0]; - out[1] = zero105[1] - small[1]; - out[2] = zero105[2] - small[2]; - out[3] = zero105[3] - small[3]; - } - -/* felem_diff subtracts |in| from |out| +{ + /* In order to prevent underflow, we subtract from 0 mod p. */ + out[0] = zero105[0] - small[0]; + out[1] = zero105[1] - small[1]; + out[2] = zero105[2] - small[2]; + out[3] = zero105[3] - small[3]; +} + +/*- + * felem_diff subtracts |in| from |out| * On entry: * in[i] < 2^104 * On exit: * out[i] < out[i] + 2^105 */ static void felem_diff(felem out, const felem in) - { - /* In order to prevent underflow, we add 0 mod p before subtracting. */ - out[0] += zero105[0]; - out[1] += zero105[1]; - out[2] += zero105[2]; - out[3] += zero105[3]; - - out[0] -= in[0]; - out[1] -= in[1]; - out[2] -= in[2]; - out[3] -= in[3]; - } - -#define two107m43m11 (((limb)1) << 107) - (((limb)1) << 43) - (((limb)1) << 11) -#define two107 (((limb)1) << 107) -#define two107m43p11 (((limb)1) << 107) - (((limb)1) << 43) + (((limb)1) << 11) +{ + /* + * In order to prevent underflow, we add 0 mod p before subtracting. + */ + out[0] += zero105[0]; + out[1] += zero105[1]; + out[2] += zero105[2]; + out[3] += zero105[3]; + + out[0] -= in[0]; + out[1] -= in[1]; + out[2] -= in[2]; + out[3] -= in[3]; +} + +# define two107m43m11 (((limb)1) << 107) - (((limb)1) << 43) - (((limb)1) << 11) +# define two107 (((limb)1) << 107) +# define two107m43p11 (((limb)1) << 107) - (((limb)1) << 43) + (((limb)1) << 11) /* zero107 is 0 mod p */ -static const felem zero107 = { two107m43m11, two107, two107m43p11, two107m43p11 }; +static const felem zero107 = + { two107m43m11, two107, two107m43p11, two107m43p11 }; -/* An alternative felem_diff for larger inputs |in| +/*- + * An alternative felem_diff for larger inputs |in| * felem_diff_zero107 subtracts |in| from |out| * On entry: * in[i] < 2^106 @@ -301,63 +317,70 @@ static const felem zero107 = { two107m43m11, two107, two107m43p11, two107m43p11 * out[i] < out[i] + 2^107 */ static void felem_diff_zero107(felem out, const felem in) - { - /* In order to prevent underflow, we add 0 mod p before subtracting. */ - out[0] += zero107[0]; - out[1] += zero107[1]; - out[2] += zero107[2]; - out[3] += zero107[3]; - - out[0] -= in[0]; - out[1] -= in[1]; - out[2] -= in[2]; - out[3] -= in[3]; - } - -/* longfelem_diff subtracts |in| from |out| +{ + /* + * In order to prevent underflow, we add 0 mod p before subtracting. + */ + out[0] += zero107[0]; + out[1] += zero107[1]; + out[2] += zero107[2]; + out[3] += zero107[3]; + + out[0] -= in[0]; + out[1] -= in[1]; + out[2] -= in[2]; + out[3] -= in[3]; +} + +/*- + * longfelem_diff subtracts |in| from |out| * On entry: * in[i] < 7*2^67 * On exit: * out[i] < out[i] + 2^70 + 2^40 */ static void longfelem_diff(longfelem out, const longfelem in) - { - static const limb two70m8p6 = (((limb)1) << 70) - (((limb)1) << 8) + (((limb)1) << 6); - static const limb two70p40 = (((limb)1) << 70) + (((limb)1) << 40); - static const limb two70 = (((limb)1) << 70); - static const limb two70m40m38p6 = (((limb)1) << 70) - (((limb)1) << 40) - (((limb)1) << 38) + (((limb)1) << 6); - static const limb two70m6 = (((limb)1) << 70) - (((limb)1) << 6); - - /* add 0 mod p to avoid underflow */ - out[0] += two70m8p6; - out[1] += two70p40; - out[2] += two70; - out[3] += two70m40m38p6; - out[4] += two70m6; - out[5] += two70m6; - out[6] += two70m6; - out[7] += two70m6; - - /* in[i] < 7*2^67 < 2^70 - 2^40 - 2^38 + 2^6 */ - out[0] -= in[0]; - out[1] -= in[1]; - out[2] -= in[2]; - out[3] -= in[3]; - out[4] -= in[4]; - out[5] -= in[5]; - out[6] -= in[6]; - out[7] -= in[7]; - } - -#define two64m0 (((limb)1) << 64) - 1 -#define two110p32m0 (((limb)1) << 110) + (((limb)1) << 32) - 1 -#define two64m46 (((limb)1) << 64) - (((limb)1) << 46) -#define two64m32 (((limb)1) << 64) - (((limb)1) << 32) +{ + static const limb two70m8p6 = + (((limb) 1) << 70) - (((limb) 1) << 8) + (((limb) 1) << 6); + static const limb two70p40 = (((limb) 1) << 70) + (((limb) 1) << 40); + static const limb two70 = (((limb) 1) << 70); + static const limb two70m40m38p6 = + (((limb) 1) << 70) - (((limb) 1) << 40) - (((limb) 1) << 38) + + (((limb) 1) << 6); + static const limb two70m6 = (((limb) 1) << 70) - (((limb) 1) << 6); + + /* add 0 mod p to avoid underflow */ + out[0] += two70m8p6; + out[1] += two70p40; + out[2] += two70; + out[3] += two70m40m38p6; + out[4] += two70m6; + out[5] += two70m6; + out[6] += two70m6; + out[7] += two70m6; + + /* in[i] < 7*2^67 < 2^70 - 2^40 - 2^38 + 2^6 */ + out[0] -= in[0]; + out[1] -= in[1]; + out[2] -= in[2]; + out[3] -= in[3]; + out[4] -= in[4]; + out[5] -= in[5]; + out[6] -= in[6]; + out[7] -= in[7]; +} + +# define two64m0 (((limb)1) << 64) - 1 +# define two110p32m0 (((limb)1) << 110) + (((limb)1) << 32) - 1 +# define two64m46 (((limb)1) << 64) - (((limb)1) << 46) +# define two64m32 (((limb)1) << 64) - (((limb)1) << 32) /* zero110 is 0 mod p */ static const felem zero110 = { two64m0, two110p32m0, two64m46, two64m32 }; -/* felem_shrink converts an felem into a smallfelem. The result isn't quite +/*- + * felem_shrink converts an felem into a smallfelem. The result isn't quite * minimal as the value may be greater than p. * * On entry: @@ -366,299 +389,309 @@ static const felem zero110 = { two64m0, two110p32m0, two64m46, two64m32 }; * out[i] < 2^64 */ static void felem_shrink(smallfelem out, const felem in) - { - felem tmp; - u64 a, b, mask; - s64 high, low; - static const u64 kPrime3Test = 0x7fffffff00000001ul; /* 2^63 - 2^32 + 1 */ - - /* Carry 2->3 */ - tmp[3] = zero110[3] + in[3] + ((u64) (in[2] >> 64)); - /* tmp[3] < 2^110 */ - - tmp[2] = zero110[2] + (u64) in[2]; - tmp[0] = zero110[0] + in[0]; - tmp[1] = zero110[1] + in[1]; - /* tmp[0] < 2**110, tmp[1] < 2^111, tmp[2] < 2**65 */ - - /* We perform two partial reductions where we eliminate the - * high-word of tmp[3]. We don't update the other words till the end. - */ - a = tmp[3] >> 64; /* a < 2^46 */ - tmp[3] = (u64) tmp[3]; - tmp[3] -= a; - tmp[3] += ((limb)a) << 32; - /* tmp[3] < 2^79 */ - - b = a; - a = tmp[3] >> 64; /* a < 2^15 */ - b += a; /* b < 2^46 + 2^15 < 2^47 */ - tmp[3] = (u64) tmp[3]; - tmp[3] -= a; - tmp[3] += ((limb)a) << 32; - /* tmp[3] < 2^64 + 2^47 */ - - /* This adjusts the other two words to complete the two partial - * reductions. */ - tmp[0] += b; - tmp[1] -= (((limb)b) << 32); - - /* In order to make space in tmp[3] for the carry from 2 -> 3, we - * conditionally subtract kPrime if tmp[3] is large enough. */ - high = tmp[3] >> 64; - /* As tmp[3] < 2^65, high is either 1 or 0 */ - high <<= 63; - high >>= 63; - /* high is: - * all ones if the high word of tmp[3] is 1 - * all zeros if the high word of tmp[3] if 0 */ - low = tmp[3]; - mask = low >> 63; - /* mask is: - * all ones if the MSB of low is 1 - * all zeros if the MSB of low if 0 */ - low &= bottom63bits; - low -= kPrime3Test; - /* if low was greater than kPrime3Test then the MSB is zero */ - low = ~low; - low >>= 63; - /* low is: - * all ones if low was > kPrime3Test - * all zeros if low was <= kPrime3Test */ - mask = (mask & low) | high; - tmp[0] -= mask & kPrime[0]; - tmp[1] -= mask & kPrime[1]; - /* kPrime[2] is zero, so omitted */ - tmp[3] -= mask & kPrime[3]; - /* tmp[3] < 2**64 - 2**32 + 1 */ - - tmp[1] += ((u64) (tmp[0] >> 64)); tmp[0] = (u64) tmp[0]; - tmp[2] += ((u64) (tmp[1] >> 64)); tmp[1] = (u64) tmp[1]; - tmp[3] += ((u64) (tmp[2] >> 64)); tmp[2] = (u64) tmp[2]; - /* tmp[i] < 2^64 */ - - out[0] = tmp[0]; - out[1] = tmp[1]; - out[2] = tmp[2]; - out[3] = tmp[3]; - } +{ + felem tmp; + u64 a, b, mask; + s64 high, low; + static const u64 kPrime3Test = 0x7fffffff00000001ul; /* 2^63 - 2^32 + 1 */ + + /* Carry 2->3 */ + tmp[3] = zero110[3] + in[3] + ((u64)(in[2] >> 64)); + /* tmp[3] < 2^110 */ + + tmp[2] = zero110[2] + (u64)in[2]; + tmp[0] = zero110[0] + in[0]; + tmp[1] = zero110[1] + in[1]; + /* tmp[0] < 2**110, tmp[1] < 2^111, tmp[2] < 2**65 */ + + /* + * We perform two partial reductions where we eliminate the high-word of + * tmp[3]. We don't update the other words till the end. + */ + a = tmp[3] >> 64; /* a < 2^46 */ + tmp[3] = (u64)tmp[3]; + tmp[3] -= a; + tmp[3] += ((limb) a) << 32; + /* tmp[3] < 2^79 */ + + b = a; + a = tmp[3] >> 64; /* a < 2^15 */ + b += a; /* b < 2^46 + 2^15 < 2^47 */ + tmp[3] = (u64)tmp[3]; + tmp[3] -= a; + tmp[3] += ((limb) a) << 32; + /* tmp[3] < 2^64 + 2^47 */ + + /* + * This adjusts the other two words to complete the two partial + * reductions. + */ + tmp[0] += b; + tmp[1] -= (((limb) b) << 32); + + /* + * In order to make space in tmp[3] for the carry from 2 -> 3, we + * conditionally subtract kPrime if tmp[3] is large enough. + */ + high = tmp[3] >> 64; + /* As tmp[3] < 2^65, high is either 1 or 0 */ + high <<= 63; + high >>= 63; + /*- + * high is: + * all ones if the high word of tmp[3] is 1 + * all zeros if the high word of tmp[3] if 0 */ + low = tmp[3]; + mask = low >> 63; + /*- + * mask is: + * all ones if the MSB of low is 1 + * all zeros if the MSB of low if 0 */ + low &= bottom63bits; + low -= kPrime3Test; + /* if low was greater than kPrime3Test then the MSB is zero */ + low = ~low; + low >>= 63; + /*- + * low is: + * all ones if low was > kPrime3Test + * all zeros if low was <= kPrime3Test */ + mask = (mask & low) | high; + tmp[0] -= mask & kPrime[0]; + tmp[1] -= mask & kPrime[1]; + /* kPrime[2] is zero, so omitted */ + tmp[3] -= mask & kPrime[3]; + /* tmp[3] < 2**64 - 2**32 + 1 */ + + tmp[1] += ((u64)(tmp[0] >> 64)); + tmp[0] = (u64)tmp[0]; + tmp[2] += ((u64)(tmp[1] >> 64)); + tmp[1] = (u64)tmp[1]; + tmp[3] += ((u64)(tmp[2] >> 64)); + tmp[2] = (u64)tmp[2]; + /* tmp[i] < 2^64 */ + + out[0] = tmp[0]; + out[1] = tmp[1]; + out[2] = tmp[2]; + out[3] = tmp[3]; +} /* smallfelem_expand converts a smallfelem to an felem */ static void smallfelem_expand(felem out, const smallfelem in) - { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - } - -/* smallfelem_square sets |out| = |small|^2 +{ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; +} + +/*- + * smallfelem_square sets |out| = |small|^2 * On entry: * small[i] < 2^64 * On exit: * out[i] < 7 * 2^64 < 2^67 */ static void smallfelem_square(longfelem out, const smallfelem small) - { - limb a; - u64 high, low; - - a = ((uint128_t) small[0]) * small[0]; - low = a; - high = a >> 64; - out[0] = low; - out[1] = high; - - a = ((uint128_t) small[0]) * small[1]; - low = a; - high = a >> 64; - out[1] += low; - out[1] += low; - out[2] = high; - - a = ((uint128_t) small[0]) * small[2]; - low = a; - high = a >> 64; - out[2] += low; - out[2] *= 2; - out[3] = high; - - a = ((uint128_t) small[0]) * small[3]; - low = a; - high = a >> 64; - out[3] += low; - out[4] = high; - - a = ((uint128_t) small[1]) * small[2]; - low = a; - high = a >> 64; - out[3] += low; - out[3] *= 2; - out[4] += high; - - a = ((uint128_t) small[1]) * small[1]; - low = a; - high = a >> 64; - out[2] += low; - out[3] += high; - - a = ((uint128_t) small[1]) * small[3]; - low = a; - high = a >> 64; - out[4] += low; - out[4] *= 2; - out[5] = high; - - a = ((uint128_t) small[2]) * small[3]; - low = a; - high = a >> 64; - out[5] += low; - out[5] *= 2; - out[6] = high; - out[6] += high; - - a = ((uint128_t) small[2]) * small[2]; - low = a; - high = a >> 64; - out[4] += low; - out[5] += high; - - a = ((uint128_t) small[3]) * small[3]; - low = a; - high = a >> 64; - out[6] += low; - out[7] = high; - } - -/* felem_square sets |out| = |in|^2 +{ + limb a; + u64 high, low; + + a = ((uint128_t) small[0]) * small[0]; + low = a; + high = a >> 64; + out[0] = low; + out[1] = high; + + a = ((uint128_t) small[0]) * small[1]; + low = a; + high = a >> 64; + out[1] += low; + out[1] += low; + out[2] = high; + + a = ((uint128_t) small[0]) * small[2]; + low = a; + high = a >> 64; + out[2] += low; + out[2] *= 2; + out[3] = high; + + a = ((uint128_t) small[0]) * small[3]; + low = a; + high = a >> 64; + out[3] += low; + out[4] = high; + + a = ((uint128_t) small[1]) * small[2]; + low = a; + high = a >> 64; + out[3] += low; + out[3] *= 2; + out[4] += high; + + a = ((uint128_t) small[1]) * small[1]; + low = a; + high = a >> 64; + out[2] += low; + out[3] += high; + + a = ((uint128_t) small[1]) * small[3]; + low = a; + high = a >> 64; + out[4] += low; + out[4] *= 2; + out[5] = high; + + a = ((uint128_t) small[2]) * small[3]; + low = a; + high = a >> 64; + out[5] += low; + out[5] *= 2; + out[6] = high; + out[6] += high; + + a = ((uint128_t) small[2]) * small[2]; + low = a; + high = a >> 64; + out[4] += low; + out[5] += high; + + a = ((uint128_t) small[3]) * small[3]; + low = a; + high = a >> 64; + out[6] += low; + out[7] = high; +} + +/*- + * felem_square sets |out| = |in|^2 * On entry: * in[i] < 2^109 * On exit: * out[i] < 7 * 2^64 < 2^67 */ static void felem_square(longfelem out, const felem in) - { - u64 small[4]; - felem_shrink(small, in); - smallfelem_square(out, small); - } - -/* smallfelem_mul sets |out| = |small1| * |small2| +{ + u64 small[4]; + felem_shrink(small, in); + smallfelem_square(out, small); +} + +/*- + * smallfelem_mul sets |out| = |small1| * |small2| * On entry: * small1[i] < 2^64 * small2[i] < 2^64 * On exit: * out[i] < 7 * 2^64 < 2^67 */ -static void smallfelem_mul(longfelem out, const smallfelem small1, const smallfelem small2) - { - limb a; - u64 high, low; - - a = ((uint128_t) small1[0]) * small2[0]; - low = a; - high = a >> 64; - out[0] = low; - out[1] = high; - - - a = ((uint128_t) small1[0]) * small2[1]; - low = a; - high = a >> 64; - out[1] += low; - out[2] = high; - - a = ((uint128_t) small1[1]) * small2[0]; - low = a; - high = a >> 64; - out[1] += low; - out[2] += high; - - - a = ((uint128_t) small1[0]) * small2[2]; - low = a; - high = a >> 64; - out[2] += low; - out[3] = high; - - a = ((uint128_t) small1[1]) * small2[1]; - low = a; - high = a >> 64; - out[2] += low; - out[3] += high; - - a = ((uint128_t) small1[2]) * small2[0]; - low = a; - high = a >> 64; - out[2] += low; - out[3] += high; - - - a = ((uint128_t) small1[0]) * small2[3]; - low = a; - high = a >> 64; - out[3] += low; - out[4] = high; - - a = ((uint128_t) small1[1]) * small2[2]; - low = a; - high = a >> 64; - out[3] += low; - out[4] += high; - - a = ((uint128_t) small1[2]) * small2[1]; - low = a; - high = a >> 64; - out[3] += low; - out[4] += high; - - a = ((uint128_t) small1[3]) * small2[0]; - low = a; - high = a >> 64; - out[3] += low; - out[4] += high; - - - a = ((uint128_t) small1[1]) * small2[3]; - low = a; - high = a >> 64; - out[4] += low; - out[5] = high; - - a = ((uint128_t) small1[2]) * small2[2]; - low = a; - high = a >> 64; - out[4] += low; - out[5] += high; - - a = ((uint128_t) small1[3]) * small2[1]; - low = a; - high = a >> 64; - out[4] += low; - out[5] += high; - - - a = ((uint128_t) small1[2]) * small2[3]; - low = a; - high = a >> 64; - out[5] += low; - out[6] = high; - - a = ((uint128_t) small1[3]) * small2[2]; - low = a; - high = a >> 64; - out[5] += low; - out[6] += high; - - - a = ((uint128_t) small1[3]) * small2[3]; - low = a; - high = a >> 64; - out[6] += low; - out[7] = high; - } - -/* felem_mul sets |out| = |in1| * |in2| +static void smallfelem_mul(longfelem out, const smallfelem small1, + const smallfelem small2) +{ + limb a; + u64 high, low; + + a = ((uint128_t) small1[0]) * small2[0]; + low = a; + high = a >> 64; + out[0] = low; + out[1] = high; + + a = ((uint128_t) small1[0]) * small2[1]; + low = a; + high = a >> 64; + out[1] += low; + out[2] = high; + + a = ((uint128_t) small1[1]) * small2[0]; + low = a; + high = a >> 64; + out[1] += low; + out[2] += high; + + a = ((uint128_t) small1[0]) * small2[2]; + low = a; + high = a >> 64; + out[2] += low; + out[3] = high; + + a = ((uint128_t) small1[1]) * small2[1]; + low = a; + high = a >> 64; + out[2] += low; + out[3] += high; + + a = ((uint128_t) small1[2]) * small2[0]; + low = a; + high = a >> 64; + out[2] += low; + out[3] += high; + + a = ((uint128_t) small1[0]) * small2[3]; + low = a; + high = a >> 64; + out[3] += low; + out[4] = high; + + a = ((uint128_t) small1[1]) * small2[2]; + low = a; + high = a >> 64; + out[3] += low; + out[4] += high; + + a = ((uint128_t) small1[2]) * small2[1]; + low = a; + high = a >> 64; + out[3] += low; + out[4] += high; + + a = ((uint128_t) small1[3]) * small2[0]; + low = a; + high = a >> 64; + out[3] += low; + out[4] += high; + + a = ((uint128_t) small1[1]) * small2[3]; + low = a; + high = a >> 64; + out[4] += low; + out[5] = high; + + a = ((uint128_t) small1[2]) * small2[2]; + low = a; + high = a >> 64; + out[4] += low; + out[5] += high; + + a = ((uint128_t) small1[3]) * small2[1]; + low = a; + high = a >> 64; + out[4] += low; + out[5] += high; + + a = ((uint128_t) small1[2]) * small2[3]; + low = a; + high = a >> 64; + out[5] += low; + out[6] = high; + + a = ((uint128_t) small1[3]) * small2[2]; + low = a; + high = a >> 64; + out[5] += low; + out[6] += high; + + a = ((uint128_t) small1[3]) * small2[3]; + low = a; + high = a >> 64; + out[6] += low; + out[7] = high; +} + +/*- + * felem_mul sets |out| = |in1| * |in2| * On entry: * in1[i] < 2^109 * in2[i] < 2^109 @@ -666,37 +699,41 @@ static void smallfelem_mul(longfelem out, const smallfelem small1, const smallfe * out[i] < 7 * 2^64 < 2^67 */ static void felem_mul(longfelem out, const felem in1, const felem in2) - { - smallfelem small1, small2; - felem_shrink(small1, in1); - felem_shrink(small2, in2); - smallfelem_mul(out, small1, small2); - } - -/* felem_small_mul sets |out| = |small1| * |in2| +{ + smallfelem small1, small2; + felem_shrink(small1, in1); + felem_shrink(small2, in2); + smallfelem_mul(out, small1, small2); +} + +/*- + * felem_small_mul sets |out| = |small1| * |in2| * On entry: * small1[i] < 2^64 * in2[i] < 2^109 * On exit: * out[i] < 7 * 2^64 < 2^67 */ -static void felem_small_mul(longfelem out, const smallfelem small1, const felem in2) - { - smallfelem small2; - felem_shrink(small2, in2); - smallfelem_mul(out, small1, small2); - } - -#define two100m36m4 (((limb)1) << 100) - (((limb)1) << 36) - (((limb)1) << 4) -#define two100 (((limb)1) << 100) -#define two100m36p4 (((limb)1) << 100) - (((limb)1) << 36) + (((limb)1) << 4) +static void felem_small_mul(longfelem out, const smallfelem small1, + const felem in2) +{ + smallfelem small2; + felem_shrink(small2, in2); + smallfelem_mul(out, small1, small2); +} + +# define two100m36m4 (((limb)1) << 100) - (((limb)1) << 36) - (((limb)1) << 4) +# define two100 (((limb)1) << 100) +# define two100m36p4 (((limb)1) << 100) - (((limb)1) << 36) + (((limb)1) << 4) /* zero100 is 0 mod p */ -static const felem zero100 = { two100m36m4, two100, two100m36p4, two100m36p4 }; +static const felem zero100 = + { two100m36m4, two100, two100m36p4, two100m36p4 }; -/* Internal function for the different flavours of felem_reduce. +/*- + * Internal function for the different flavours of felem_reduce. * felem_reduce_ reduces the higher coefficients in[4]-in[7]. * On entry: - * out[0] >= in[6] + 2^32*in[6] + in[7] + 2^32*in[7] + * out[0] >= in[6] + 2^32*in[6] + in[7] + 2^32*in[7] * out[1] >= in[7] + 2^32*in[4] * out[2] >= in[5] + 2^32*in[5] * out[3] >= in[4] + 2^32*in[5] + 2^32*in[6] @@ -707,40 +744,41 @@ static const felem zero100 = { two100m36m4, two100, two100m36p4, two100m36p4 }; * out[3] <= out[3] + 2^32*in[4] + 3*in[7] */ static void felem_reduce_(felem out, const longfelem in) - { - int128_t c; - /* combine common terms from below */ - c = in[4] + (in[5] << 32); - out[0] += c; - out[3] -= c; - - c = in[5] - in[7]; - out[1] += c; - out[2] -= c; - - /* the remaining terms */ - /* 256: [(0,1),(96,-1),(192,-1),(224,1)] */ - out[1] -= (in[4] << 32); - out[3] += (in[4] << 32); - - /* 320: [(32,1),(64,1),(128,-1),(160,-1),(224,-1)] */ - out[2] -= (in[5] << 32); - - /* 384: [(0,-1),(32,-1),(96,2),(128,2),(224,-1)] */ - out[0] -= in[6]; - out[0] -= (in[6] << 32); - out[1] += (in[6] << 33); - out[2] += (in[6] * 2); - out[3] -= (in[6] << 32); - - /* 448: [(0,-1),(32,-1),(64,-1),(128,1),(160,2),(192,3)] */ - out[0] -= in[7]; - out[0] -= (in[7] << 32); - out[2] += (in[7] << 33); - out[3] += (in[7] * 3); - } - -/* felem_reduce converts a longfelem into an felem. +{ + int128_t c; + /* combine common terms from below */ + c = in[4] + (in[5] << 32); + out[0] += c; + out[3] -= c; + + c = in[5] - in[7]; + out[1] += c; + out[2] -= c; + + /* the remaining terms */ + /* 256: [(0,1),(96,-1),(192,-1),(224,1)] */ + out[1] -= (in[4] << 32); + out[3] += (in[4] << 32); + + /* 320: [(32,1),(64,1),(128,-1),(160,-1),(224,-1)] */ + out[2] -= (in[5] << 32); + + /* 384: [(0,-1),(32,-1),(96,2),(128,2),(224,-1)] */ + out[0] -= in[6]; + out[0] -= (in[6] << 32); + out[1] += (in[6] << 33); + out[2] += (in[6] * 2); + out[3] -= (in[6] << 32); + + /* 448: [(0,-1),(32,-1),(64,-1),(128,1),(160,2),(192,3)] */ + out[0] -= in[7]; + out[0] -= (in[7] << 32); + out[2] += (in[7] << 33); + out[3] += (in[7] * 3); +} + +/*- + * felem_reduce converts a longfelem into an felem. * To be called directly after felem_square or felem_mul. * On entry: * in[0] < 2^64, in[1] < 3*2^64, in[2] < 5*2^64, in[3] < 7*2^64 @@ -749,189 +787,203 @@ static void felem_reduce_(felem out, const longfelem in) * out[i] < 2^101 */ static void felem_reduce(felem out, const longfelem in) - { - out[0] = zero100[0] + in[0]; - out[1] = zero100[1] + in[1]; - out[2] = zero100[2] + in[2]; - out[3] = zero100[3] + in[3]; - - felem_reduce_(out, in); - - /* out[0] > 2^100 - 2^36 - 2^4 - 3*2^64 - 3*2^96 - 2^64 - 2^96 > 0 - * out[1] > 2^100 - 2^64 - 7*2^96 > 0 - * out[2] > 2^100 - 2^36 + 2^4 - 5*2^64 - 5*2^96 > 0 - * out[3] > 2^100 - 2^36 + 2^4 - 7*2^64 - 5*2^96 - 3*2^96 > 0 - * - * out[0] < 2^100 + 2^64 + 7*2^64 + 5*2^96 < 2^101 - * out[1] < 2^100 + 3*2^64 + 5*2^64 + 3*2^97 < 2^101 - * out[2] < 2^100 + 5*2^64 + 2^64 + 3*2^65 + 2^97 < 2^101 - * out[3] < 2^100 + 7*2^64 + 7*2^96 + 3*2^64 < 2^101 - */ - } - -/* felem_reduce_zero105 converts a larger longfelem into an felem. +{ + out[0] = zero100[0] + in[0]; + out[1] = zero100[1] + in[1]; + out[2] = zero100[2] + in[2]; + out[3] = zero100[3] + in[3]; + + felem_reduce_(out, in); + + /*- + * out[0] > 2^100 - 2^36 - 2^4 - 3*2^64 - 3*2^96 - 2^64 - 2^96 > 0 + * out[1] > 2^100 - 2^64 - 7*2^96 > 0 + * out[2] > 2^100 - 2^36 + 2^4 - 5*2^64 - 5*2^96 > 0 + * out[3] > 2^100 - 2^36 + 2^4 - 7*2^64 - 5*2^96 - 3*2^96 > 0 + * + * out[0] < 2^100 + 2^64 + 7*2^64 + 5*2^96 < 2^101 + * out[1] < 2^100 + 3*2^64 + 5*2^64 + 3*2^97 < 2^101 + * out[2] < 2^100 + 5*2^64 + 2^64 + 3*2^65 + 2^97 < 2^101 + * out[3] < 2^100 + 7*2^64 + 7*2^96 + 3*2^64 < 2^101 + */ +} + +/*- + * felem_reduce_zero105 converts a larger longfelem into an felem. * On entry: * in[0] < 2^71 * On exit: * out[i] < 2^106 */ static void felem_reduce_zero105(felem out, const longfelem in) - { - out[0] = zero105[0] + in[0]; - out[1] = zero105[1] + in[1]; - out[2] = zero105[2] + in[2]; - out[3] = zero105[3] + in[3]; - - felem_reduce_(out, in); - - /* out[0] > 2^105 - 2^41 - 2^9 - 2^71 - 2^103 - 2^71 - 2^103 > 0 - * out[1] > 2^105 - 2^71 - 2^103 > 0 - * out[2] > 2^105 - 2^41 + 2^9 - 2^71 - 2^103 > 0 - * out[3] > 2^105 - 2^41 + 2^9 - 2^71 - 2^103 - 2^103 > 0 - * - * out[0] < 2^105 + 2^71 + 2^71 + 2^103 < 2^106 - * out[1] < 2^105 + 2^71 + 2^71 + 2^103 < 2^106 - * out[2] < 2^105 + 2^71 + 2^71 + 2^71 + 2^103 < 2^106 - * out[3] < 2^105 + 2^71 + 2^103 + 2^71 < 2^106 - */ - } - -/* subtract_u64 sets *result = *result - v and *carry to one if the subtraction - * underflowed. */ -static void subtract_u64(u64* result, u64* carry, u64 v) - { - uint128_t r = *result; - r -= v; - *carry = (r >> 64) & 1; - *result = (u64) r; - } - -/* felem_contract converts |in| to its unique, minimal representation. - * On entry: - * in[i] < 2^109 +{ + out[0] = zero105[0] + in[0]; + out[1] = zero105[1] + in[1]; + out[2] = zero105[2] + in[2]; + out[3] = zero105[3] + in[3]; + + felem_reduce_(out, in); + + /*- + * out[0] > 2^105 - 2^41 - 2^9 - 2^71 - 2^103 - 2^71 - 2^103 > 0 + * out[1] > 2^105 - 2^71 - 2^103 > 0 + * out[2] > 2^105 - 2^41 + 2^9 - 2^71 - 2^103 > 0 + * out[3] > 2^105 - 2^41 + 2^9 - 2^71 - 2^103 - 2^103 > 0 + * + * out[0] < 2^105 + 2^71 + 2^71 + 2^103 < 2^106 + * out[1] < 2^105 + 2^71 + 2^71 + 2^103 < 2^106 + * out[2] < 2^105 + 2^71 + 2^71 + 2^71 + 2^103 < 2^106 + * out[3] < 2^105 + 2^71 + 2^103 + 2^71 < 2^106 + */ +} + +/* + * subtract_u64 sets *result = *result - v and *carry to one if the + * subtraction underflowed. + */ +static void subtract_u64(u64 *result, u64 *carry, u64 v) +{ + uint128_t r = *result; + r -= v; + *carry = (r >> 64) & 1; + *result = (u64)r; +} + +/* + * felem_contract converts |in| to its unique, minimal representation. On + * entry: in[i] < 2^109 */ static void felem_contract(smallfelem out, const felem in) - { - unsigned i; - u64 all_equal_so_far = 0, result = 0, carry; - - felem_shrink(out, in); - /* small is minimal except that the value might be > p */ - - all_equal_so_far--; - /* We are doing a constant time test if out >= kPrime. We need to - * compare each u64, from most-significant to least significant. For - * each one, if all words so far have been equal (m is all ones) then a - * non-equal result is the answer. Otherwise we continue. */ - for (i = 3; i < 4; i--) - { - u64 equal; - uint128_t a = ((uint128_t) kPrime[i]) - out[i]; - /* if out[i] > kPrime[i] then a will underflow and the high - * 64-bits will all be set. */ - result |= all_equal_so_far & ((u64) (a >> 64)); - - /* if kPrime[i] == out[i] then |equal| will be all zeros and - * the decrement will make it all ones. */ - equal = kPrime[i] ^ out[i]; - equal--; - equal &= equal << 32; - equal &= equal << 16; - equal &= equal << 8; - equal &= equal << 4; - equal &= equal << 2; - equal &= equal << 1; - equal = ((s64) equal) >> 63; - - all_equal_so_far &= equal; - } - - /* if all_equal_so_far is still all ones then the two values are equal - * and so out >= kPrime is true. */ - result |= all_equal_so_far; - - /* if out >= kPrime then we subtract kPrime. */ - subtract_u64(&out[0], &carry, result & kPrime[0]); - subtract_u64(&out[1], &carry, carry); - subtract_u64(&out[2], &carry, carry); - subtract_u64(&out[3], &carry, carry); - - subtract_u64(&out[1], &carry, result & kPrime[1]); - subtract_u64(&out[2], &carry, carry); - subtract_u64(&out[3], &carry, carry); - - subtract_u64(&out[2], &carry, result & kPrime[2]); - subtract_u64(&out[3], &carry, carry); - - subtract_u64(&out[3], &carry, result & kPrime[3]); - } +{ + unsigned i; + u64 all_equal_so_far = 0, result = 0, carry; + + felem_shrink(out, in); + /* small is minimal except that the value might be > p */ + + all_equal_so_far--; + /* + * We are doing a constant time test if out >= kPrime. We need to compare + * each u64, from most-significant to least significant. For each one, if + * all words so far have been equal (m is all ones) then a non-equal + * result is the answer. Otherwise we continue. + */ + for (i = 3; i < 4; i--) { + u64 equal; + uint128_t a = ((uint128_t) kPrime[i]) - out[i]; + /* + * if out[i] > kPrime[i] then a will underflow and the high 64-bits + * will all be set. + */ + result |= all_equal_so_far & ((u64)(a >> 64)); + + /* + * if kPrime[i] == out[i] then |equal| will be all zeros and the + * decrement will make it all ones. + */ + equal = kPrime[i] ^ out[i]; + equal--; + equal &= equal << 32; + equal &= equal << 16; + equal &= equal << 8; + equal &= equal << 4; + equal &= equal << 2; + equal &= equal << 1; + equal = ((s64) equal) >> 63; + + all_equal_so_far &= equal; + } + + /* + * if all_equal_so_far is still all ones then the two values are equal + * and so out >= kPrime is true. + */ + result |= all_equal_so_far; + + /* if out >= kPrime then we subtract kPrime. */ + subtract_u64(&out[0], &carry, result & kPrime[0]); + subtract_u64(&out[1], &carry, carry); + subtract_u64(&out[2], &carry, carry); + subtract_u64(&out[3], &carry, carry); + + subtract_u64(&out[1], &carry, result & kPrime[1]); + subtract_u64(&out[2], &carry, carry); + subtract_u64(&out[3], &carry, carry); + + subtract_u64(&out[2], &carry, result & kPrime[2]); + subtract_u64(&out[3], &carry, carry); + + subtract_u64(&out[3], &carry, result & kPrime[3]); +} static void smallfelem_square_contract(smallfelem out, const smallfelem in) - { - longfelem longtmp; - felem tmp; - - smallfelem_square(longtmp, in); - felem_reduce(tmp, longtmp); - felem_contract(out, tmp); - } - -static void smallfelem_mul_contract(smallfelem out, const smallfelem in1, const smallfelem in2) - { - longfelem longtmp; - felem tmp; - - smallfelem_mul(longtmp, in1, in2); - felem_reduce(tmp, longtmp); - felem_contract(out, tmp); - } - -/* felem_is_zero returns a limb with all bits set if |in| == 0 (mod p) and 0 +{ + longfelem longtmp; + felem tmp; + + smallfelem_square(longtmp, in); + felem_reduce(tmp, longtmp); + felem_contract(out, tmp); +} + +static void smallfelem_mul_contract(smallfelem out, const smallfelem in1, + const smallfelem in2) +{ + longfelem longtmp; + felem tmp; + + smallfelem_mul(longtmp, in1, in2); + felem_reduce(tmp, longtmp); + felem_contract(out, tmp); +} + +/*- + * felem_is_zero returns a limb with all bits set if |in| == 0 (mod p) and 0 * otherwise. * On entry: * small[i] < 2^64 */ static limb smallfelem_is_zero(const smallfelem small) - { - limb result; - u64 is_p; - - u64 is_zero = small[0] | small[1] | small[2] | small[3]; - is_zero--; - is_zero &= is_zero << 32; - is_zero &= is_zero << 16; - is_zero &= is_zero << 8; - is_zero &= is_zero << 4; - is_zero &= is_zero << 2; - is_zero &= is_zero << 1; - is_zero = ((s64) is_zero) >> 63; - - is_p = (small[0] ^ kPrime[0]) | - (small[1] ^ kPrime[1]) | - (small[2] ^ kPrime[2]) | - (small[3] ^ kPrime[3]); - is_p--; - is_p &= is_p << 32; - is_p &= is_p << 16; - is_p &= is_p << 8; - is_p &= is_p << 4; - is_p &= is_p << 2; - is_p &= is_p << 1; - is_p = ((s64) is_p) >> 63; - - is_zero |= is_p; - - result = is_zero; - result |= ((limb) is_zero) << 64; - return result; - } +{ + limb result; + u64 is_p; + + u64 is_zero = small[0] | small[1] | small[2] | small[3]; + is_zero--; + is_zero &= is_zero << 32; + is_zero &= is_zero << 16; + is_zero &= is_zero << 8; + is_zero &= is_zero << 4; + is_zero &= is_zero << 2; + is_zero &= is_zero << 1; + is_zero = ((s64) is_zero) >> 63; + + is_p = (small[0] ^ kPrime[0]) | + (small[1] ^ kPrime[1]) | + (small[2] ^ kPrime[2]) | (small[3] ^ kPrime[3]); + is_p--; + is_p &= is_p << 32; + is_p &= is_p << 16; + is_p &= is_p << 8; + is_p &= is_p << 4; + is_p &= is_p << 2; + is_p &= is_p << 1; + is_p = ((s64) is_p) >> 63; + + is_zero |= is_p; + + result = is_zero; + result |= ((limb) is_zero) << 64; + return result; +} static int smallfelem_is_zero_int(const smallfelem small) - { - return (int) (smallfelem_is_zero(small) & ((limb)1)); - } +{ + return (int)(smallfelem_is_zero(small) & ((limb) 1)); +} -/* felem_inv calculates |out| = |in|^{-1} +/*- + * felem_inv calculates |out| = |in|^{-1} * * Based on Fermat's Little Theorem: * a^p = a (mod p) @@ -939,213 +991,248 @@ static int smallfelem_is_zero_int(const smallfelem small) * a^{p-2} = a^{-1} (mod p) */ static void felem_inv(felem out, const felem in) - { - felem ftmp, ftmp2; - /* each e_I will hold |in|^{2^I - 1} */ - felem e2, e4, e8, e16, e32, e64; - longfelem tmp; - unsigned i; - - felem_square(tmp, in); felem_reduce(ftmp, tmp); /* 2^1 */ - felem_mul(tmp, in, ftmp); felem_reduce(ftmp, tmp); /* 2^2 - 2^0 */ - felem_assign(e2, ftmp); - felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^3 - 2^1 */ - felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^4 - 2^2 */ - felem_mul(tmp, ftmp, e2); felem_reduce(ftmp, tmp); /* 2^4 - 2^0 */ - felem_assign(e4, ftmp); - felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^5 - 2^1 */ - felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^6 - 2^2 */ - felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^7 - 2^3 */ - felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^8 - 2^4 */ - felem_mul(tmp, ftmp, e4); felem_reduce(ftmp, tmp); /* 2^8 - 2^0 */ - felem_assign(e8, ftmp); - for (i = 0; i < 8; i++) { - felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); - } /* 2^16 - 2^8 */ - felem_mul(tmp, ftmp, e8); felem_reduce(ftmp, tmp); /* 2^16 - 2^0 */ - felem_assign(e16, ftmp); - for (i = 0; i < 16; i++) { - felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); - } /* 2^32 - 2^16 */ - felem_mul(tmp, ftmp, e16); felem_reduce(ftmp, tmp); /* 2^32 - 2^0 */ - felem_assign(e32, ftmp); - for (i = 0; i < 32; i++) { - felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); - } /* 2^64 - 2^32 */ - felem_assign(e64, ftmp); - felem_mul(tmp, ftmp, in); felem_reduce(ftmp, tmp); /* 2^64 - 2^32 + 2^0 */ - for (i = 0; i < 192; i++) { - felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); - } /* 2^256 - 2^224 + 2^192 */ - - felem_mul(tmp, e64, e32); felem_reduce(ftmp2, tmp); /* 2^64 - 2^0 */ - for (i = 0; i < 16; i++) { - felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp); - } /* 2^80 - 2^16 */ - felem_mul(tmp, ftmp2, e16); felem_reduce(ftmp2, tmp); /* 2^80 - 2^0 */ - for (i = 0; i < 8; i++) { - felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp); - } /* 2^88 - 2^8 */ - felem_mul(tmp, ftmp2, e8); felem_reduce(ftmp2, tmp); /* 2^88 - 2^0 */ - for (i = 0; i < 4; i++) { - felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp); - } /* 2^92 - 2^4 */ - felem_mul(tmp, ftmp2, e4); felem_reduce(ftmp2, tmp); /* 2^92 - 2^0 */ - felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp); /* 2^93 - 2^1 */ - felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp); /* 2^94 - 2^2 */ - felem_mul(tmp, ftmp2, e2); felem_reduce(ftmp2, tmp); /* 2^94 - 2^0 */ - felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp); /* 2^95 - 2^1 */ - felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp); /* 2^96 - 2^2 */ - felem_mul(tmp, ftmp2, in); felem_reduce(ftmp2, tmp); /* 2^96 - 3 */ - - felem_mul(tmp, ftmp2, ftmp); felem_reduce(out, tmp); /* 2^256 - 2^224 + 2^192 + 2^96 - 3 */ - } +{ + felem ftmp, ftmp2; + /* each e_I will hold |in|^{2^I - 1} */ + felem e2, e4, e8, e16, e32, e64; + longfelem tmp; + unsigned i; + + felem_square(tmp, in); + felem_reduce(ftmp, tmp); /* 2^1 */ + felem_mul(tmp, in, ftmp); + felem_reduce(ftmp, tmp); /* 2^2 - 2^0 */ + felem_assign(e2, ftmp); + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^3 - 2^1 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^4 - 2^2 */ + felem_mul(tmp, ftmp, e2); + felem_reduce(ftmp, tmp); /* 2^4 - 2^0 */ + felem_assign(e4, ftmp); + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^5 - 2^1 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^6 - 2^2 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^7 - 2^3 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^8 - 2^4 */ + felem_mul(tmp, ftmp, e4); + felem_reduce(ftmp, tmp); /* 2^8 - 2^0 */ + felem_assign(e8, ftmp); + for (i = 0; i < 8; i++) { + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + } /* 2^16 - 2^8 */ + felem_mul(tmp, ftmp, e8); + felem_reduce(ftmp, tmp); /* 2^16 - 2^0 */ + felem_assign(e16, ftmp); + for (i = 0; i < 16; i++) { + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + } /* 2^32 - 2^16 */ + felem_mul(tmp, ftmp, e16); + felem_reduce(ftmp, tmp); /* 2^32 - 2^0 */ + felem_assign(e32, ftmp); + for (i = 0; i < 32; i++) { + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + } /* 2^64 - 2^32 */ + felem_assign(e64, ftmp); + felem_mul(tmp, ftmp, in); + felem_reduce(ftmp, tmp); /* 2^64 - 2^32 + 2^0 */ + for (i = 0; i < 192; i++) { + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + } /* 2^256 - 2^224 + 2^192 */ + + felem_mul(tmp, e64, e32); + felem_reduce(ftmp2, tmp); /* 2^64 - 2^0 */ + for (i = 0; i < 16; i++) { + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); + } /* 2^80 - 2^16 */ + felem_mul(tmp, ftmp2, e16); + felem_reduce(ftmp2, tmp); /* 2^80 - 2^0 */ + for (i = 0; i < 8; i++) { + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); + } /* 2^88 - 2^8 */ + felem_mul(tmp, ftmp2, e8); + felem_reduce(ftmp2, tmp); /* 2^88 - 2^0 */ + for (i = 0; i < 4; i++) { + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); + } /* 2^92 - 2^4 */ + felem_mul(tmp, ftmp2, e4); + felem_reduce(ftmp2, tmp); /* 2^92 - 2^0 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^93 - 2^1 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^94 - 2^2 */ + felem_mul(tmp, ftmp2, e2); + felem_reduce(ftmp2, tmp); /* 2^94 - 2^0 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^95 - 2^1 */ + felem_square(tmp, ftmp2); + felem_reduce(ftmp2, tmp); /* 2^96 - 2^2 */ + felem_mul(tmp, ftmp2, in); + felem_reduce(ftmp2, tmp); /* 2^96 - 3 */ + + felem_mul(tmp, ftmp2, ftmp); + felem_reduce(out, tmp); /* 2^256 - 2^224 + 2^192 + 2^96 - 3 */ +} static void smallfelem_inv_contract(smallfelem out, const smallfelem in) - { - felem tmp; +{ + felem tmp; - smallfelem_expand(tmp, in); - felem_inv(tmp, tmp); - felem_contract(out, tmp); - } + smallfelem_expand(tmp, in); + felem_inv(tmp, tmp); + felem_contract(out, tmp); +} -/* Group operations +/*- + * Group operations * ---------------- * * Building on top of the field operations we have the operations on the * elliptic curve group itself. Points on the curve are represented in Jacobian - * coordinates */ + * coordinates + */ -/* point_double calculates 2*(x_in, y_in, z_in) +/*- + * point_double calculates 2*(x_in, y_in, z_in) * * The method is taken from: * http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b * * Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed. - * while x_out == y_in is not (maybe this works, but it's not tested). */ + * while x_out == y_in is not (maybe this works, but it's not tested). + */ static void point_double(felem x_out, felem y_out, felem z_out, - const felem x_in, const felem y_in, const felem z_in) - { - longfelem tmp, tmp2; - felem delta, gamma, beta, alpha, ftmp, ftmp2; - smallfelem small1, small2; - - felem_assign(ftmp, x_in); - /* ftmp[i] < 2^106 */ - felem_assign(ftmp2, x_in); - /* ftmp2[i] < 2^106 */ - - /* delta = z^2 */ - felem_square(tmp, z_in); - felem_reduce(delta, tmp); - /* delta[i] < 2^101 */ - - /* gamma = y^2 */ - felem_square(tmp, y_in); - felem_reduce(gamma, tmp); - /* gamma[i] < 2^101 */ - felem_shrink(small1, gamma); - - /* beta = x*gamma */ - felem_small_mul(tmp, small1, x_in); - felem_reduce(beta, tmp); - /* beta[i] < 2^101 */ - - /* alpha = 3*(x-delta)*(x+delta) */ - felem_diff(ftmp, delta); - /* ftmp[i] < 2^105 + 2^106 < 2^107 */ - felem_sum(ftmp2, delta); - /* ftmp2[i] < 2^105 + 2^106 < 2^107 */ - felem_scalar(ftmp2, 3); - /* ftmp2[i] < 3 * 2^107 < 2^109 */ - felem_mul(tmp, ftmp, ftmp2); - felem_reduce(alpha, tmp); - /* alpha[i] < 2^101 */ - felem_shrink(small2, alpha); - - /* x' = alpha^2 - 8*beta */ - smallfelem_square(tmp, small2); - felem_reduce(x_out, tmp); - felem_assign(ftmp, beta); - felem_scalar(ftmp, 8); - /* ftmp[i] < 8 * 2^101 = 2^104 */ - felem_diff(x_out, ftmp); - /* x_out[i] < 2^105 + 2^101 < 2^106 */ - - /* z' = (y + z)^2 - gamma - delta */ - felem_sum(delta, gamma); - /* delta[i] < 2^101 + 2^101 = 2^102 */ - felem_assign(ftmp, y_in); - felem_sum(ftmp, z_in); - /* ftmp[i] < 2^106 + 2^106 = 2^107 */ - felem_square(tmp, ftmp); - felem_reduce(z_out, tmp); - felem_diff(z_out, delta); - /* z_out[i] < 2^105 + 2^101 < 2^106 */ - - /* y' = alpha*(4*beta - x') - 8*gamma^2 */ - felem_scalar(beta, 4); - /* beta[i] < 4 * 2^101 = 2^103 */ - felem_diff_zero107(beta, x_out); - /* beta[i] < 2^107 + 2^103 < 2^108 */ - felem_small_mul(tmp, small2, beta); - /* tmp[i] < 7 * 2^64 < 2^67 */ - smallfelem_square(tmp2, small1); - /* tmp2[i] < 7 * 2^64 */ - longfelem_scalar(tmp2, 8); - /* tmp2[i] < 8 * 7 * 2^64 = 7 * 2^67 */ - longfelem_diff(tmp, tmp2); - /* tmp[i] < 2^67 + 2^70 + 2^40 < 2^71 */ - felem_reduce_zero105(y_out, tmp); - /* y_out[i] < 2^106 */ - } - -/* point_double_small is the same as point_double, except that it operates on - * smallfelems */ + const felem x_in, const felem y_in, const felem z_in) +{ + longfelem tmp, tmp2; + felem delta, gamma, beta, alpha, ftmp, ftmp2; + smallfelem small1, small2; + + felem_assign(ftmp, x_in); + /* ftmp[i] < 2^106 */ + felem_assign(ftmp2, x_in); + /* ftmp2[i] < 2^106 */ + + /* delta = z^2 */ + felem_square(tmp, z_in); + felem_reduce(delta, tmp); + /* delta[i] < 2^101 */ + + /* gamma = y^2 */ + felem_square(tmp, y_in); + felem_reduce(gamma, tmp); + /* gamma[i] < 2^101 */ + felem_shrink(small1, gamma); + + /* beta = x*gamma */ + felem_small_mul(tmp, small1, x_in); + felem_reduce(beta, tmp); + /* beta[i] < 2^101 */ + + /* alpha = 3*(x-delta)*(x+delta) */ + felem_diff(ftmp, delta); + /* ftmp[i] < 2^105 + 2^106 < 2^107 */ + felem_sum(ftmp2, delta); + /* ftmp2[i] < 2^105 + 2^106 < 2^107 */ + felem_scalar(ftmp2, 3); + /* ftmp2[i] < 3 * 2^107 < 2^109 */ + felem_mul(tmp, ftmp, ftmp2); + felem_reduce(alpha, tmp); + /* alpha[i] < 2^101 */ + felem_shrink(small2, alpha); + + /* x' = alpha^2 - 8*beta */ + smallfelem_square(tmp, small2); + felem_reduce(x_out, tmp); + felem_assign(ftmp, beta); + felem_scalar(ftmp, 8); + /* ftmp[i] < 8 * 2^101 = 2^104 */ + felem_diff(x_out, ftmp); + /* x_out[i] < 2^105 + 2^101 < 2^106 */ + + /* z' = (y + z)^2 - gamma - delta */ + felem_sum(delta, gamma); + /* delta[i] < 2^101 + 2^101 = 2^102 */ + felem_assign(ftmp, y_in); + felem_sum(ftmp, z_in); + /* ftmp[i] < 2^106 + 2^106 = 2^107 */ + felem_square(tmp, ftmp); + felem_reduce(z_out, tmp); + felem_diff(z_out, delta); + /* z_out[i] < 2^105 + 2^101 < 2^106 */ + + /* y' = alpha*(4*beta - x') - 8*gamma^2 */ + felem_scalar(beta, 4); + /* beta[i] < 4 * 2^101 = 2^103 */ + felem_diff_zero107(beta, x_out); + /* beta[i] < 2^107 + 2^103 < 2^108 */ + felem_small_mul(tmp, small2, beta); + /* tmp[i] < 7 * 2^64 < 2^67 */ + smallfelem_square(tmp2, small1); + /* tmp2[i] < 7 * 2^64 */ + longfelem_scalar(tmp2, 8); + /* tmp2[i] < 8 * 7 * 2^64 = 7 * 2^67 */ + longfelem_diff(tmp, tmp2); + /* tmp[i] < 2^67 + 2^70 + 2^40 < 2^71 */ + felem_reduce_zero105(y_out, tmp); + /* y_out[i] < 2^106 */ +} + +/* + * point_double_small is the same as point_double, except that it operates on + * smallfelems + */ static void point_double_small(smallfelem x_out, smallfelem y_out, smallfelem z_out, - const smallfelem x_in, const smallfelem y_in, const smallfelem z_in) - { - felem felem_x_out, felem_y_out, felem_z_out; - felem felem_x_in, felem_y_in, felem_z_in; - - smallfelem_expand(felem_x_in, x_in); - smallfelem_expand(felem_y_in, y_in); - smallfelem_expand(felem_z_in, z_in); - point_double(felem_x_out, felem_y_out, felem_z_out, - felem_x_in, felem_y_in, felem_z_in); - felem_shrink(x_out, felem_x_out); - felem_shrink(y_out, felem_y_out); - felem_shrink(z_out, felem_z_out); - } + const smallfelem x_in, const smallfelem y_in, + const smallfelem z_in) +{ + felem felem_x_out, felem_y_out, felem_z_out; + felem felem_x_in, felem_y_in, felem_z_in; + + smallfelem_expand(felem_x_in, x_in); + smallfelem_expand(felem_y_in, y_in); + smallfelem_expand(felem_z_in, z_in); + point_double(felem_x_out, felem_y_out, felem_z_out, + felem_x_in, felem_y_in, felem_z_in); + felem_shrink(x_out, felem_x_out); + felem_shrink(y_out, felem_y_out); + felem_shrink(z_out, felem_z_out); +} /* copy_conditional copies in to out iff mask is all ones. */ -static void -copy_conditional(felem out, const felem in, limb mask) - { - unsigned i; - for (i = 0; i < NLIMBS; ++i) - { - const limb tmp = mask & (in[i] ^ out[i]); - out[i] ^= tmp; - } - } +static void copy_conditional(felem out, const felem in, limb mask) +{ + unsigned i; + for (i = 0; i < NLIMBS; ++i) { + const limb tmp = mask & (in[i] ^ out[i]); + out[i] ^= tmp; + } +} /* copy_small_conditional copies in to out iff mask is all ones. */ -static void -copy_small_conditional(felem out, const smallfelem in, limb mask) - { - unsigned i; - const u64 mask64 = mask; - for (i = 0; i < NLIMBS; ++i) - { - out[i] = ((limb) (in[i] & mask64)) | (out[i] & ~mask); - } - } - -/* point_add calcuates (x1, y1, z1) + (x2, y2, z2) +static void copy_small_conditional(felem out, const smallfelem in, limb mask) +{ + unsigned i; + const u64 mask64 = mask; + for (i = 0; i < NLIMBS; ++i) { + out[i] = ((limb) (in[i] & mask64)) | (out[i] & ~mask); + } +} + +/*- + * point_add calcuates (x1, y1, z1) + (x2, y2, z2) * * The method is taken from: * http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl, @@ -1154,187 +1241,191 @@ copy_small_conditional(felem out, const smallfelem in, limb mask) * This function includes a branch for checking whether the two input points * are equal, (while not equal to the point at infinity). This case never * happens during single point multiplication, so there is no timing leak for - * ECDH or ECDSA signing. */ + * ECDH or ECDSA signing. + */ static void point_add(felem x3, felem y3, felem z3, - const felem x1, const felem y1, const felem z1, - const int mixed, const smallfelem x2, const smallfelem y2, const smallfelem z2) - { - felem ftmp, ftmp2, ftmp3, ftmp4, ftmp5, ftmp6, x_out, y_out, z_out; - longfelem tmp, tmp2; - smallfelem small1, small2, small3, small4, small5; - limb x_equal, y_equal, z1_is_zero, z2_is_zero; - - felem_shrink(small3, z1); - - z1_is_zero = smallfelem_is_zero(small3); - z2_is_zero = smallfelem_is_zero(z2); - - /* ftmp = z1z1 = z1**2 */ - smallfelem_square(tmp, small3); - felem_reduce(ftmp, tmp); - /* ftmp[i] < 2^101 */ - felem_shrink(small1, ftmp); - - if(!mixed) - { - /* ftmp2 = z2z2 = z2**2 */ - smallfelem_square(tmp, z2); - felem_reduce(ftmp2, tmp); - /* ftmp2[i] < 2^101 */ - felem_shrink(small2, ftmp2); - - felem_shrink(small5, x1); - - /* u1 = ftmp3 = x1*z2z2 */ - smallfelem_mul(tmp, small5, small2); - felem_reduce(ftmp3, tmp); - /* ftmp3[i] < 2^101 */ - - /* ftmp5 = z1 + z2 */ - felem_assign(ftmp5, z1); - felem_small_sum(ftmp5, z2); - /* ftmp5[i] < 2^107 */ - - /* ftmp5 = (z1 + z2)**2 - (z1z1 + z2z2) = 2z1z2 */ - felem_square(tmp, ftmp5); - felem_reduce(ftmp5, tmp); - /* ftmp2 = z2z2 + z1z1 */ - felem_sum(ftmp2, ftmp); - /* ftmp2[i] < 2^101 + 2^101 = 2^102 */ - felem_diff(ftmp5, ftmp2); - /* ftmp5[i] < 2^105 + 2^101 < 2^106 */ - - /* ftmp2 = z2 * z2z2 */ - smallfelem_mul(tmp, small2, z2); - felem_reduce(ftmp2, tmp); - - /* s1 = ftmp2 = y1 * z2**3 */ - felem_mul(tmp, y1, ftmp2); - felem_reduce(ftmp6, tmp); - /* ftmp6[i] < 2^101 */ - } - else - { - /* We'll assume z2 = 1 (special case z2 = 0 is handled later) */ - - /* u1 = ftmp3 = x1*z2z2 */ - felem_assign(ftmp3, x1); - /* ftmp3[i] < 2^106 */ - - /* ftmp5 = 2z1z2 */ - felem_assign(ftmp5, z1); - felem_scalar(ftmp5, 2); - /* ftmp5[i] < 2*2^106 = 2^107 */ - - /* s1 = ftmp2 = y1 * z2**3 */ - felem_assign(ftmp6, y1); - /* ftmp6[i] < 2^106 */ - } - - /* u2 = x2*z1z1 */ - smallfelem_mul(tmp, x2, small1); - felem_reduce(ftmp4, tmp); - - /* h = ftmp4 = u2 - u1 */ - felem_diff_zero107(ftmp4, ftmp3); - /* ftmp4[i] < 2^107 + 2^101 < 2^108 */ - felem_shrink(small4, ftmp4); - - x_equal = smallfelem_is_zero(small4); - - /* z_out = ftmp5 * h */ - felem_small_mul(tmp, small4, ftmp5); - felem_reduce(z_out, tmp); - /* z_out[i] < 2^101 */ - - /* ftmp = z1 * z1z1 */ - smallfelem_mul(tmp, small1, small3); - felem_reduce(ftmp, tmp); - - /* s2 = tmp = y2 * z1**3 */ - felem_small_mul(tmp, y2, ftmp); - felem_reduce(ftmp5, tmp); - - /* r = ftmp5 = (s2 - s1)*2 */ - felem_diff_zero107(ftmp5, ftmp6); - /* ftmp5[i] < 2^107 + 2^107 = 2^108*/ - felem_scalar(ftmp5, 2); - /* ftmp5[i] < 2^109 */ - felem_shrink(small1, ftmp5); - y_equal = smallfelem_is_zero(small1); - - if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) - { - point_double(x3, y3, z3, x1, y1, z1); - return; - } - - /* I = ftmp = (2h)**2 */ - felem_assign(ftmp, ftmp4); - felem_scalar(ftmp, 2); - /* ftmp[i] < 2*2^108 = 2^109 */ - felem_square(tmp, ftmp); - felem_reduce(ftmp, tmp); - - /* J = ftmp2 = h * I */ - felem_mul(tmp, ftmp4, ftmp); - felem_reduce(ftmp2, tmp); - - /* V = ftmp4 = U1 * I */ - felem_mul(tmp, ftmp3, ftmp); - felem_reduce(ftmp4, tmp); - - /* x_out = r**2 - J - 2V */ - smallfelem_square(tmp, small1); - felem_reduce(x_out, tmp); - felem_assign(ftmp3, ftmp4); - felem_scalar(ftmp4, 2); - felem_sum(ftmp4, ftmp2); - /* ftmp4[i] < 2*2^101 + 2^101 < 2^103 */ - felem_diff(x_out, ftmp4); - /* x_out[i] < 2^105 + 2^101 */ - - /* y_out = r(V-x_out) - 2 * s1 * J */ - felem_diff_zero107(ftmp3, x_out); - /* ftmp3[i] < 2^107 + 2^101 < 2^108 */ - felem_small_mul(tmp, small1, ftmp3); - felem_mul(tmp2, ftmp6, ftmp2); - longfelem_scalar(tmp2, 2); - /* tmp2[i] < 2*2^67 = 2^68 */ - longfelem_diff(tmp, tmp2); - /* tmp[i] < 2^67 + 2^70 + 2^40 < 2^71 */ - felem_reduce_zero105(y_out, tmp); - /* y_out[i] < 2^106 */ - - copy_small_conditional(x_out, x2, z1_is_zero); - copy_conditional(x_out, x1, z2_is_zero); - copy_small_conditional(y_out, y2, z1_is_zero); - copy_conditional(y_out, y1, z2_is_zero); - copy_small_conditional(z_out, z2, z1_is_zero); - copy_conditional(z_out, z1, z2_is_zero); - felem_assign(x3, x_out); - felem_assign(y3, y_out); - felem_assign(z3, z_out); - } - -/* point_add_small is the same as point_add, except that it operates on - * smallfelems */ + const felem x1, const felem y1, const felem z1, + const int mixed, const smallfelem x2, + const smallfelem y2, const smallfelem z2) +{ + felem ftmp, ftmp2, ftmp3, ftmp4, ftmp5, ftmp6, x_out, y_out, z_out; + longfelem tmp, tmp2; + smallfelem small1, small2, small3, small4, small5; + limb x_equal, y_equal, z1_is_zero, z2_is_zero; + + felem_shrink(small3, z1); + + z1_is_zero = smallfelem_is_zero(small3); + z2_is_zero = smallfelem_is_zero(z2); + + /* ftmp = z1z1 = z1**2 */ + smallfelem_square(tmp, small3); + felem_reduce(ftmp, tmp); + /* ftmp[i] < 2^101 */ + felem_shrink(small1, ftmp); + + if (!mixed) { + /* ftmp2 = z2z2 = z2**2 */ + smallfelem_square(tmp, z2); + felem_reduce(ftmp2, tmp); + /* ftmp2[i] < 2^101 */ + felem_shrink(small2, ftmp2); + + felem_shrink(small5, x1); + + /* u1 = ftmp3 = x1*z2z2 */ + smallfelem_mul(tmp, small5, small2); + felem_reduce(ftmp3, tmp); + /* ftmp3[i] < 2^101 */ + + /* ftmp5 = z1 + z2 */ + felem_assign(ftmp5, z1); + felem_small_sum(ftmp5, z2); + /* ftmp5[i] < 2^107 */ + + /* ftmp5 = (z1 + z2)**2 - (z1z1 + z2z2) = 2z1z2 */ + felem_square(tmp, ftmp5); + felem_reduce(ftmp5, tmp); + /* ftmp2 = z2z2 + z1z1 */ + felem_sum(ftmp2, ftmp); + /* ftmp2[i] < 2^101 + 2^101 = 2^102 */ + felem_diff(ftmp5, ftmp2); + /* ftmp5[i] < 2^105 + 2^101 < 2^106 */ + + /* ftmp2 = z2 * z2z2 */ + smallfelem_mul(tmp, small2, z2); + felem_reduce(ftmp2, tmp); + + /* s1 = ftmp2 = y1 * z2**3 */ + felem_mul(tmp, y1, ftmp2); + felem_reduce(ftmp6, tmp); + /* ftmp6[i] < 2^101 */ + } else { + /* + * We'll assume z2 = 1 (special case z2 = 0 is handled later) + */ + + /* u1 = ftmp3 = x1*z2z2 */ + felem_assign(ftmp3, x1); + /* ftmp3[i] < 2^106 */ + + /* ftmp5 = 2z1z2 */ + felem_assign(ftmp5, z1); + felem_scalar(ftmp5, 2); + /* ftmp5[i] < 2*2^106 = 2^107 */ + + /* s1 = ftmp2 = y1 * z2**3 */ + felem_assign(ftmp6, y1); + /* ftmp6[i] < 2^106 */ + } + + /* u2 = x2*z1z1 */ + smallfelem_mul(tmp, x2, small1); + felem_reduce(ftmp4, tmp); + + /* h = ftmp4 = u2 - u1 */ + felem_diff_zero107(ftmp4, ftmp3); + /* ftmp4[i] < 2^107 + 2^101 < 2^108 */ + felem_shrink(small4, ftmp4); + + x_equal = smallfelem_is_zero(small4); + + /* z_out = ftmp5 * h */ + felem_small_mul(tmp, small4, ftmp5); + felem_reduce(z_out, tmp); + /* z_out[i] < 2^101 */ + + /* ftmp = z1 * z1z1 */ + smallfelem_mul(tmp, small1, small3); + felem_reduce(ftmp, tmp); + + /* s2 = tmp = y2 * z1**3 */ + felem_small_mul(tmp, y2, ftmp); + felem_reduce(ftmp5, tmp); + + /* r = ftmp5 = (s2 - s1)*2 */ + felem_diff_zero107(ftmp5, ftmp6); + /* ftmp5[i] < 2^107 + 2^107 = 2^108 */ + felem_scalar(ftmp5, 2); + /* ftmp5[i] < 2^109 */ + felem_shrink(small1, ftmp5); + y_equal = smallfelem_is_zero(small1); + + if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) { + point_double(x3, y3, z3, x1, y1, z1); + return; + } + + /* I = ftmp = (2h)**2 */ + felem_assign(ftmp, ftmp4); + felem_scalar(ftmp, 2); + /* ftmp[i] < 2*2^108 = 2^109 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); + + /* J = ftmp2 = h * I */ + felem_mul(tmp, ftmp4, ftmp); + felem_reduce(ftmp2, tmp); + + /* V = ftmp4 = U1 * I */ + felem_mul(tmp, ftmp3, ftmp); + felem_reduce(ftmp4, tmp); + + /* x_out = r**2 - J - 2V */ + smallfelem_square(tmp, small1); + felem_reduce(x_out, tmp); + felem_assign(ftmp3, ftmp4); + felem_scalar(ftmp4, 2); + felem_sum(ftmp4, ftmp2); + /* ftmp4[i] < 2*2^101 + 2^101 < 2^103 */ + felem_diff(x_out, ftmp4); + /* x_out[i] < 2^105 + 2^101 */ + + /* y_out = r(V-x_out) - 2 * s1 * J */ + felem_diff_zero107(ftmp3, x_out); + /* ftmp3[i] < 2^107 + 2^101 < 2^108 */ + felem_small_mul(tmp, small1, ftmp3); + felem_mul(tmp2, ftmp6, ftmp2); + longfelem_scalar(tmp2, 2); + /* tmp2[i] < 2*2^67 = 2^68 */ + longfelem_diff(tmp, tmp2); + /* tmp[i] < 2^67 + 2^70 + 2^40 < 2^71 */ + felem_reduce_zero105(y_out, tmp); + /* y_out[i] < 2^106 */ + + copy_small_conditional(x_out, x2, z1_is_zero); + copy_conditional(x_out, x1, z2_is_zero); + copy_small_conditional(y_out, y2, z1_is_zero); + copy_conditional(y_out, y1, z2_is_zero); + copy_small_conditional(z_out, z2, z1_is_zero); + copy_conditional(z_out, z1, z2_is_zero); + felem_assign(x3, x_out); + felem_assign(y3, y_out); + felem_assign(z3, z_out); +} + +/* + * point_add_small is the same as point_add, except that it operates on + * smallfelems + */ static void point_add_small(smallfelem x3, smallfelem y3, smallfelem z3, - smallfelem x1, smallfelem y1, smallfelem z1, - smallfelem x2, smallfelem y2, smallfelem z2) - { - felem felem_x3, felem_y3, felem_z3; - felem felem_x1, felem_y1, felem_z1; - smallfelem_expand(felem_x1, x1); - smallfelem_expand(felem_y1, y1); - smallfelem_expand(felem_z1, z1); - point_add(felem_x3, felem_y3, felem_z3, felem_x1, felem_y1, felem_z1, 0, x2, y2, z2); - felem_shrink(x3, felem_x3); - felem_shrink(y3, felem_y3); - felem_shrink(z3, felem_z3); - } - -/* Base point pre computation + smallfelem x1, smallfelem y1, smallfelem z1, + smallfelem x2, smallfelem y2, smallfelem z2) +{ + felem felem_x3, felem_y3, felem_z3; + felem felem_x1, felem_y1, felem_z1; + smallfelem_expand(felem_x1, x1); + smallfelem_expand(felem_y1, y1); + smallfelem_expand(felem_z1, z1); + point_add(felem_x3, felem_y3, felem_z3, felem_x1, felem_y1, felem_z1, 0, + x2, y2, z2); + felem_shrink(x3, felem_x3); + felem_shrink(y3, felem_y3); + felem_shrink(z3, felem_z3); +} + +/*- + * Base point pre computation * -------------------------- * * Two different sorts of precomputed tables are used in the following code. @@ -1370,801 +1461,909 @@ static void point_add_small(smallfelem x3, smallfelem y3, smallfelem z3, * Tables for other points have table[i] = iG for i in 0 .. 16. */ /* gmul is the table of precomputed base points */ -static const smallfelem gmul[2][16][3] = -{{{{0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}}, - {{0xf4a13945d898c296, 0x77037d812deb33a0, 0xf8bce6e563a440f2, 0x6b17d1f2e12c4247}, - {0xcbb6406837bf51f5, 0x2bce33576b315ece, 0x8ee7eb4a7c0f9e16, 0x4fe342e2fe1a7f9b}, - {1, 0, 0, 0}}, - {{0x90e75cb48e14db63, 0x29493baaad651f7e, 0x8492592e326e25de, 0x0fa822bc2811aaa5}, - {0xe41124545f462ee7, 0x34b1a65050fe82f5, 0x6f4ad4bcb3df188b, 0xbff44ae8f5dba80d}, - {1, 0, 0, 0}}, - {{0x93391ce2097992af, 0xe96c98fd0d35f1fa, 0xb257c0de95e02789, 0x300a4bbc89d6726f}, - {0xaa54a291c08127a0, 0x5bb1eeada9d806a5, 0x7f1ddb25ff1e3c6f, 0x72aac7e0d09b4644}, - {1, 0, 0, 0}}, - {{0x57c84fc9d789bd85, 0xfc35ff7dc297eac3, 0xfb982fd588c6766e, 0x447d739beedb5e67}, - {0x0c7e33c972e25b32, 0x3d349b95a7fae500, 0xe12e9d953a4aaff7, 0x2d4825ab834131ee}, - {1, 0, 0, 0}}, - {{0x13949c932a1d367f, 0xef7fbd2b1a0a11b7, 0xddc6068bb91dfc60, 0xef9519328a9c72ff}, - {0x196035a77376d8a8, 0x23183b0895ca1740, 0xc1ee9807022c219c, 0x611e9fc37dbb2c9b}, - {1, 0, 0, 0}}, - {{0xcae2b1920b57f4bc, 0x2936df5ec6c9bc36, 0x7dea6482e11238bf, 0x550663797b51f5d8}, - {0x44ffe216348a964c, 0x9fb3d576dbdefbe1, 0x0afa40018d9d50e5, 0x157164848aecb851}, - {1, 0, 0, 0}}, - {{0xe48ecafffc5cde01, 0x7ccd84e70d715f26, 0xa2e8f483f43e4391, 0xeb5d7745b21141ea}, - {0xcac917e2731a3479, 0x85f22cfe2844b645, 0x0990e6a158006cee, 0xeafd72ebdbecc17b}, - {1, 0, 0, 0}}, - {{0x6cf20ffb313728be, 0x96439591a3c6b94a, 0x2736ff8344315fc5, 0xa6d39677a7849276}, - {0xf2bab833c357f5f4, 0x824a920c2284059b, 0x66b8babd2d27ecdf, 0x674f84749b0b8816}, - {1, 0, 0, 0}}, - {{0x2df48c04677c8a3e, 0x74e02f080203a56b, 0x31855f7db8c7fedb, 0x4e769e7672c9ddad}, - {0xa4c36165b824bbb0, 0xfb9ae16f3b9122a5, 0x1ec0057206947281, 0x42b99082de830663}, - {1, 0, 0, 0}}, - {{0x6ef95150dda868b9, 0xd1f89e799c0ce131, 0x7fdc1ca008a1c478, 0x78878ef61c6ce04d}, - {0x9c62b9121fe0d976, 0x6ace570ebde08d4f, 0xde53142c12309def, 0xb6cb3f5d7b72c321}, - {1, 0, 0, 0}}, - {{0x7f991ed2c31a3573, 0x5b82dd5bd54fb496, 0x595c5220812ffcae, 0x0c88bc4d716b1287}, - {0x3a57bf635f48aca8, 0x7c8181f4df2564f3, 0x18d1b5b39c04e6aa, 0xdd5ddea3f3901dc6}, - {1, 0, 0, 0}}, - {{0xe96a79fb3e72ad0c, 0x43a0a28c42ba792f, 0xefe0a423083e49f3, 0x68f344af6b317466}, - {0xcdfe17db3fb24d4a, 0x668bfc2271f5c626, 0x604ed93c24d67ff3, 0x31b9c405f8540a20}, - {1, 0, 0, 0}}, - {{0xd36b4789a2582e7f, 0x0d1a10144ec39c28, 0x663c62c3edbad7a0, 0x4052bf4b6f461db9}, - {0x235a27c3188d25eb, 0xe724f33999bfcc5b, 0x862be6bd71d70cc8, 0xfecf4d5190b0fc61}, - {1, 0, 0, 0}}, - {{0x74346c10a1d4cfac, 0xafdf5cc08526a7a4, 0x123202a8f62bff7a, 0x1eddbae2c802e41a}, - {0x8fa0af2dd603f844, 0x36e06b7e4c701917, 0x0c45f45273db33a0, 0x43104d86560ebcfc}, - {1, 0, 0, 0}}, - {{0x9615b5110d1d78e5, 0x66b0de3225c4744b, 0x0a4a46fb6aaf363a, 0xb48e26b484f7a21c}, - {0x06ebb0f621a01b2d, 0xc004e4048b7b0f98, 0x64131bcdfed6f668, 0xfac015404d4d3dab}, - {1, 0, 0, 0}}}, - {{{0, 0, 0, 0}, - {0, 0, 0, 0}, - {0, 0, 0, 0}}, - {{0x3a5a9e22185a5943, 0x1ab919365c65dfb6, 0x21656b32262c71da, 0x7fe36b40af22af89}, - {0xd50d152c699ca101, 0x74b3d5867b8af212, 0x9f09f40407dca6f1, 0xe697d45825b63624}, - {1, 0, 0, 0}}, - {{0xa84aa9397512218e, 0xe9a521b074ca0141, 0x57880b3a18a2e902, 0x4a5b506612a677a6}, - {0x0beada7a4c4f3840, 0x626db15419e26d9d, 0xc42604fbe1627d40, 0xeb13461ceac089f1}, - {1, 0, 0, 0}}, - {{0xf9faed0927a43281, 0x5e52c4144103ecbc, 0xc342967aa815c857, 0x0781b8291c6a220a}, - {0x5a8343ceeac55f80, 0x88f80eeee54a05e3, 0x97b2a14f12916434, 0x690cde8df0151593}, - {1, 0, 0, 0}}, - {{0xaee9c75df7f82f2a, 0x9e4c35874afdf43a, 0xf5622df437371326, 0x8a535f566ec73617}, - {0xc5f9a0ac223094b7, 0xcde533864c8c7669, 0x37e02819085a92bf, 0x0455c08468b08bd7}, - {1, 0, 0, 0}}, - {{0x0c0a6e2c9477b5d9, 0xf9a4bf62876dc444, 0x5050a949b6cdc279, 0x06bada7ab77f8276}, - {0xc8b4aed1ea48dac9, 0xdebd8a4b7ea1070f, 0x427d49101366eb70, 0x5b476dfd0e6cb18a}, - {1, 0, 0, 0}}, - {{0x7c5c3e44278c340a, 0x4d54606812d66f3b, 0x29a751b1ae23c5d8, 0x3e29864e8a2ec908}, - {0x142d2a6626dbb850, 0xad1744c4765bd780, 0x1f150e68e322d1ed, 0x239b90ea3dc31e7e}, - {1, 0, 0, 0}}, - {{0x78c416527a53322a, 0x305dde6709776f8e, 0xdbcab759f8862ed4, 0x820f4dd949f72ff7}, - {0x6cc544a62b5debd4, 0x75be5d937b4e8cc4, 0x1b481b1b215c14d3, 0x140406ec783a05ec}, - {1, 0, 0, 0}}, - {{0x6a703f10e895df07, 0xfd75f3fa01876bd8, 0xeb5b06e70ce08ffe, 0x68f6b8542783dfee}, - {0x90c76f8a78712655, 0xcf5293d2f310bf7f, 0xfbc8044dfda45028, 0xcbe1feba92e40ce6}, - {1, 0, 0, 0}}, - {{0xe998ceea4396e4c1, 0xfc82ef0b6acea274, 0x230f729f2250e927, 0xd0b2f94d2f420109}, - {0x4305adddb38d4966, 0x10b838f8624c3b45, 0x7db2636658954e7a, 0x971459828b0719e5}, - {1, 0, 0, 0}}, - {{0x4bd6b72623369fc9, 0x57f2929e53d0b876, 0xc2d5cba4f2340687, 0x961610004a866aba}, - {0x49997bcd2e407a5e, 0x69ab197d92ddcb24, 0x2cf1f2438fe5131c, 0x7acb9fadcee75e44}, - {1, 0, 0, 0}}, - {{0x254e839423d2d4c0, 0xf57f0c917aea685b, 0xa60d880f6f75aaea, 0x24eb9acca333bf5b}, - {0xe3de4ccb1cda5dea, 0xfeef9341c51a6b4f, 0x743125f88bac4c4d, 0x69f891c5acd079cc}, - {1, 0, 0, 0}}, - {{0xeee44b35702476b5, 0x7ed031a0e45c2258, 0xb422d1e7bd6f8514, 0xe51f547c5972a107}, - {0xa25bcd6fc9cf343d, 0x8ca922ee097c184e, 0xa62f98b3a9fe9a06, 0x1c309a2b25bb1387}, - {1, 0, 0, 0}}, - {{0x9295dbeb1967c459, 0xb00148833472c98e, 0xc504977708011828, 0x20b87b8aa2c4e503}, - {0x3063175de057c277, 0x1bd539338fe582dd, 0x0d11adef5f69a044, 0xf5c6fa49919776be}, - {1, 0, 0, 0}}, - {{0x8c944e760fd59e11, 0x3876cba1102fad5f, 0xa454c3fad83faa56, 0x1ed7d1b9332010b9}, - {0xa1011a270024b889, 0x05e4d0dcac0cd344, 0x52b520f0eb6a2a24, 0x3a2b03f03217257a}, - {1, 0, 0, 0}}, - {{0xf20fc2afdf1d043d, 0xf330240db58d5a62, 0xfc7d229ca0058c3b, 0x15fee545c78dd9f6}, - {0x501e82885bc98cda, 0x41ef80e5d046ac04, 0x557d9f49461210fb, 0x4ab5b6b2b8753f81}, - {1, 0, 0, 0}}}}; - -/* select_point selects the |idx|th point from a precomputation table and - * copies it to out. */ -static void select_point(const u64 idx, unsigned int size, const smallfelem pre_comp[16][3], smallfelem out[3]) - { - unsigned i, j; - u64 *outlimbs = &out[0][0]; - memset(outlimbs, 0, 3 * sizeof(smallfelem)); - - for (i = 0; i < size; i++) - { - const u64 *inlimbs = (u64*) &pre_comp[i][0][0]; - u64 mask = i ^ idx; - mask |= mask >> 4; - mask |= mask >> 2; - mask |= mask >> 1; - mask &= 1; - mask--; - for (j = 0; j < NLIMBS * 3; j++) - outlimbs[j] |= inlimbs[j] & mask; - } - } +static const smallfelem gmul[2][16][3] = { + {{{0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}}, + {{0xf4a13945d898c296, 0x77037d812deb33a0, 0xf8bce6e563a440f2, + 0x6b17d1f2e12c4247}, + {0xcbb6406837bf51f5, 0x2bce33576b315ece, 0x8ee7eb4a7c0f9e16, + 0x4fe342e2fe1a7f9b}, + {1, 0, 0, 0}}, + {{0x90e75cb48e14db63, 0x29493baaad651f7e, 0x8492592e326e25de, + 0x0fa822bc2811aaa5}, + {0xe41124545f462ee7, 0x34b1a65050fe82f5, 0x6f4ad4bcb3df188b, + 0xbff44ae8f5dba80d}, + {1, 0, 0, 0}}, + {{0x93391ce2097992af, 0xe96c98fd0d35f1fa, 0xb257c0de95e02789, + 0x300a4bbc89d6726f}, + {0xaa54a291c08127a0, 0x5bb1eeada9d806a5, 0x7f1ddb25ff1e3c6f, + 0x72aac7e0d09b4644}, + {1, 0, 0, 0}}, + {{0x57c84fc9d789bd85, 0xfc35ff7dc297eac3, 0xfb982fd588c6766e, + 0x447d739beedb5e67}, + {0x0c7e33c972e25b32, 0x3d349b95a7fae500, 0xe12e9d953a4aaff7, + 0x2d4825ab834131ee}, + {1, 0, 0, 0}}, + {{0x13949c932a1d367f, 0xef7fbd2b1a0a11b7, 0xddc6068bb91dfc60, + 0xef9519328a9c72ff}, + {0x196035a77376d8a8, 0x23183b0895ca1740, 0xc1ee9807022c219c, + 0x611e9fc37dbb2c9b}, + {1, 0, 0, 0}}, + {{0xcae2b1920b57f4bc, 0x2936df5ec6c9bc36, 0x7dea6482e11238bf, + 0x550663797b51f5d8}, + {0x44ffe216348a964c, 0x9fb3d576dbdefbe1, 0x0afa40018d9d50e5, + 0x157164848aecb851}, + {1, 0, 0, 0}}, + {{0xe48ecafffc5cde01, 0x7ccd84e70d715f26, 0xa2e8f483f43e4391, + 0xeb5d7745b21141ea}, + {0xcac917e2731a3479, 0x85f22cfe2844b645, 0x0990e6a158006cee, + 0xeafd72ebdbecc17b}, + {1, 0, 0, 0}}, + {{0x6cf20ffb313728be, 0x96439591a3c6b94a, 0x2736ff8344315fc5, + 0xa6d39677a7849276}, + {0xf2bab833c357f5f4, 0x824a920c2284059b, 0x66b8babd2d27ecdf, + 0x674f84749b0b8816}, + {1, 0, 0, 0}}, + {{0x2df48c04677c8a3e, 0x74e02f080203a56b, 0x31855f7db8c7fedb, + 0x4e769e7672c9ddad}, + {0xa4c36165b824bbb0, 0xfb9ae16f3b9122a5, 0x1ec0057206947281, + 0x42b99082de830663}, + {1, 0, 0, 0}}, + {{0x6ef95150dda868b9, 0xd1f89e799c0ce131, 0x7fdc1ca008a1c478, + 0x78878ef61c6ce04d}, + {0x9c62b9121fe0d976, 0x6ace570ebde08d4f, 0xde53142c12309def, + 0xb6cb3f5d7b72c321}, + {1, 0, 0, 0}}, + {{0x7f991ed2c31a3573, 0x5b82dd5bd54fb496, 0x595c5220812ffcae, + 0x0c88bc4d716b1287}, + {0x3a57bf635f48aca8, 0x7c8181f4df2564f3, 0x18d1b5b39c04e6aa, + 0xdd5ddea3f3901dc6}, + {1, 0, 0, 0}}, + {{0xe96a79fb3e72ad0c, 0x43a0a28c42ba792f, 0xefe0a423083e49f3, + 0x68f344af6b317466}, + {0xcdfe17db3fb24d4a, 0x668bfc2271f5c626, 0x604ed93c24d67ff3, + 0x31b9c405f8540a20}, + {1, 0, 0, 0}}, + {{0xd36b4789a2582e7f, 0x0d1a10144ec39c28, 0x663c62c3edbad7a0, + 0x4052bf4b6f461db9}, + {0x235a27c3188d25eb, 0xe724f33999bfcc5b, 0x862be6bd71d70cc8, + 0xfecf4d5190b0fc61}, + {1, 0, 0, 0}}, + {{0x74346c10a1d4cfac, 0xafdf5cc08526a7a4, 0x123202a8f62bff7a, + 0x1eddbae2c802e41a}, + {0x8fa0af2dd603f844, 0x36e06b7e4c701917, 0x0c45f45273db33a0, + 0x43104d86560ebcfc}, + {1, 0, 0, 0}}, + {{0x9615b5110d1d78e5, 0x66b0de3225c4744b, 0x0a4a46fb6aaf363a, + 0xb48e26b484f7a21c}, + {0x06ebb0f621a01b2d, 0xc004e4048b7b0f98, 0x64131bcdfed6f668, + 0xfac015404d4d3dab}, + {1, 0, 0, 0}}}, + {{{0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}}, + {{0x3a5a9e22185a5943, 0x1ab919365c65dfb6, 0x21656b32262c71da, + 0x7fe36b40af22af89}, + {0xd50d152c699ca101, 0x74b3d5867b8af212, 0x9f09f40407dca6f1, + 0xe697d45825b63624}, + {1, 0, 0, 0}}, + {{0xa84aa9397512218e, 0xe9a521b074ca0141, 0x57880b3a18a2e902, + 0x4a5b506612a677a6}, + {0x0beada7a4c4f3840, 0x626db15419e26d9d, 0xc42604fbe1627d40, + 0xeb13461ceac089f1}, + {1, 0, 0, 0}}, + {{0xf9faed0927a43281, 0x5e52c4144103ecbc, 0xc342967aa815c857, + 0x0781b8291c6a220a}, + {0x5a8343ceeac55f80, 0x88f80eeee54a05e3, 0x97b2a14f12916434, + 0x690cde8df0151593}, + {1, 0, 0, 0}}, + {{0xaee9c75df7f82f2a, 0x9e4c35874afdf43a, 0xf5622df437371326, + 0x8a535f566ec73617}, + {0xc5f9a0ac223094b7, 0xcde533864c8c7669, 0x37e02819085a92bf, + 0x0455c08468b08bd7}, + {1, 0, 0, 0}}, + {{0x0c0a6e2c9477b5d9, 0xf9a4bf62876dc444, 0x5050a949b6cdc279, + 0x06bada7ab77f8276}, + {0xc8b4aed1ea48dac9, 0xdebd8a4b7ea1070f, 0x427d49101366eb70, + 0x5b476dfd0e6cb18a}, + {1, 0, 0, 0}}, + {{0x7c5c3e44278c340a, 0x4d54606812d66f3b, 0x29a751b1ae23c5d8, + 0x3e29864e8a2ec908}, + {0x142d2a6626dbb850, 0xad1744c4765bd780, 0x1f150e68e322d1ed, + 0x239b90ea3dc31e7e}, + {1, 0, 0, 0}}, + {{0x78c416527a53322a, 0x305dde6709776f8e, 0xdbcab759f8862ed4, + 0x820f4dd949f72ff7}, + {0x6cc544a62b5debd4, 0x75be5d937b4e8cc4, 0x1b481b1b215c14d3, + 0x140406ec783a05ec}, + {1, 0, 0, 0}}, + {{0x6a703f10e895df07, 0xfd75f3fa01876bd8, 0xeb5b06e70ce08ffe, + 0x68f6b8542783dfee}, + {0x90c76f8a78712655, 0xcf5293d2f310bf7f, 0xfbc8044dfda45028, + 0xcbe1feba92e40ce6}, + {1, 0, 0, 0}}, + {{0xe998ceea4396e4c1, 0xfc82ef0b6acea274, 0x230f729f2250e927, + 0xd0b2f94d2f420109}, + {0x4305adddb38d4966, 0x10b838f8624c3b45, 0x7db2636658954e7a, + 0x971459828b0719e5}, + {1, 0, 0, 0}}, + {{0x4bd6b72623369fc9, 0x57f2929e53d0b876, 0xc2d5cba4f2340687, + 0x961610004a866aba}, + {0x49997bcd2e407a5e, 0x69ab197d92ddcb24, 0x2cf1f2438fe5131c, + 0x7acb9fadcee75e44}, + {1, 0, 0, 0}}, + {{0x254e839423d2d4c0, 0xf57f0c917aea685b, 0xa60d880f6f75aaea, + 0x24eb9acca333bf5b}, + {0xe3de4ccb1cda5dea, 0xfeef9341c51a6b4f, 0x743125f88bac4c4d, + 0x69f891c5acd079cc}, + {1, 0, 0, 0}}, + {{0xeee44b35702476b5, 0x7ed031a0e45c2258, 0xb422d1e7bd6f8514, + 0xe51f547c5972a107}, + {0xa25bcd6fc9cf343d, 0x8ca922ee097c184e, 0xa62f98b3a9fe9a06, + 0x1c309a2b25bb1387}, + {1, 0, 0, 0}}, + {{0x9295dbeb1967c459, 0xb00148833472c98e, 0xc504977708011828, + 0x20b87b8aa2c4e503}, + {0x3063175de057c277, 0x1bd539338fe582dd, 0x0d11adef5f69a044, + 0xf5c6fa49919776be}, + {1, 0, 0, 0}}, + {{0x8c944e760fd59e11, 0x3876cba1102fad5f, 0xa454c3fad83faa56, + 0x1ed7d1b9332010b9}, + {0xa1011a270024b889, 0x05e4d0dcac0cd344, 0x52b520f0eb6a2a24, + 0x3a2b03f03217257a}, + {1, 0, 0, 0}}, + {{0xf20fc2afdf1d043d, 0xf330240db58d5a62, 0xfc7d229ca0058c3b, + 0x15fee545c78dd9f6}, + {0x501e82885bc98cda, 0x41ef80e5d046ac04, 0x557d9f49461210fb, + 0x4ab5b6b2b8753f81}, + {1, 0, 0, 0}}} +}; + +/* + * select_point selects the |idx|th point from a precomputation table and + * copies it to out. + */ +static void select_point(const u64 idx, unsigned int size, + const smallfelem pre_comp[16][3], smallfelem out[3]) +{ + unsigned i, j; + u64 *outlimbs = &out[0][0]; + memset(outlimbs, 0, 3 * sizeof(smallfelem)); + + for (i = 0; i < size; i++) { + const u64 *inlimbs = (u64 *)&pre_comp[i][0][0]; + u64 mask = i ^ idx; + mask |= mask >> 4; + mask |= mask >> 2; + mask |= mask >> 1; + mask &= 1; + mask--; + for (j = 0; j < NLIMBS * 3; j++) + outlimbs[j] |= inlimbs[j] & mask; + } +} /* get_bit returns the |i|th bit in |in| */ static char get_bit(const felem_bytearray in, int i) - { - if ((i < 0) || (i >= 256)) - return 0; - return (in[i >> 3] >> (i & 7)) & 1; - } - -/* Interleaved point multiplication using precomputed point multiples: - * The small point multiples 0*P, 1*P, ..., 17*P are in pre_comp[], - * the scalars in scalars[]. If g_scalar is non-NULL, we also add this multiple - * of the generator, using certain (large) precomputed multiples in g_pre_comp. - * Output point (X, Y, Z) is stored in x_out, y_out, z_out */ +{ + if ((i < 0) || (i >= 256)) + return 0; + return (in[i >> 3] >> (i & 7)) & 1; +} + +/* + * Interleaved point multiplication using precomputed point multiples: The + * small point multiples 0*P, 1*P, ..., 17*P are in pre_comp[], the scalars + * in scalars[]. If g_scalar is non-NULL, we also add this multiple of the + * generator, using certain (large) precomputed multiples in g_pre_comp. + * Output point (X, Y, Z) is stored in x_out, y_out, z_out + */ static void batch_mul(felem x_out, felem y_out, felem z_out, - const felem_bytearray scalars[], const unsigned num_points, const u8 *g_scalar, - const int mixed, const smallfelem pre_comp[][17][3], const smallfelem g_pre_comp[2][16][3]) - { - int i, skip; - unsigned num, gen_mul = (g_scalar != NULL); - felem nq[3], ftmp; - smallfelem tmp[3]; - u64 bits; - u8 sign, digit; - - /* set nq to the point at infinity */ - memset(nq, 0, 3 * sizeof(felem)); - - /* Loop over all scalars msb-to-lsb, interleaving additions - * of multiples of the generator (two in each of the last 32 rounds) - * and additions of other points multiples (every 5th round). - */ - skip = 1; /* save two point operations in the first round */ - for (i = (num_points ? 255 : 31); i >= 0; --i) - { - /* double */ - if (!skip) - point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]); - - /* add multiples of the generator */ - if (gen_mul && (i <= 31)) - { - /* first, look 32 bits upwards */ - bits = get_bit(g_scalar, i + 224) << 3; - bits |= get_bit(g_scalar, i + 160) << 2; - bits |= get_bit(g_scalar, i + 96) << 1; - bits |= get_bit(g_scalar, i + 32); - /* select the point to add, in constant time */ - select_point(bits, 16, g_pre_comp[1], tmp); - - if (!skip) - { - point_add(nq[0], nq[1], nq[2], - nq[0], nq[1], nq[2], - 1 /* mixed */, tmp[0], tmp[1], tmp[2]); - } - else - { - smallfelem_expand(nq[0], tmp[0]); - smallfelem_expand(nq[1], tmp[1]); - smallfelem_expand(nq[2], tmp[2]); - skip = 0; - } - - /* second, look at the current position */ - bits = get_bit(g_scalar, i + 192) << 3; - bits |= get_bit(g_scalar, i + 128) << 2; - bits |= get_bit(g_scalar, i + 64) << 1; - bits |= get_bit(g_scalar, i); - /* select the point to add, in constant time */ - select_point(bits, 16, g_pre_comp[0], tmp); - point_add(nq[0], nq[1], nq[2], - nq[0], nq[1], nq[2], - 1 /* mixed */, tmp[0], tmp[1], tmp[2]); - } - - /* do other additions every 5 doublings */ - if (num_points && (i % 5 == 0)) - { - /* loop over all scalars */ - for (num = 0; num < num_points; ++num) - { - bits = get_bit(scalars[num], i + 4) << 5; - bits |= get_bit(scalars[num], i + 3) << 4; - bits |= get_bit(scalars[num], i + 2) << 3; - bits |= get_bit(scalars[num], i + 1) << 2; - bits |= get_bit(scalars[num], i) << 1; - bits |= get_bit(scalars[num], i - 1); - ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits); - - /* select the point to add or subtract, in constant time */ - select_point(digit, 17, pre_comp[num], tmp); - smallfelem_neg(ftmp, tmp[1]); /* (X, -Y, Z) is the negative point */ - copy_small_conditional(ftmp, tmp[1], (((limb) sign) - 1)); - felem_contract(tmp[1], ftmp); - - if (!skip) - { - point_add(nq[0], nq[1], nq[2], - nq[0], nq[1], nq[2], - mixed, tmp[0], tmp[1], tmp[2]); - } - else - { - smallfelem_expand(nq[0], tmp[0]); - smallfelem_expand(nq[1], tmp[1]); - smallfelem_expand(nq[2], tmp[2]); - skip = 0; - } - } - } - } - felem_assign(x_out, nq[0]); - felem_assign(y_out, nq[1]); - felem_assign(z_out, nq[2]); - } + const felem_bytearray scalars[], + const unsigned num_points, const u8 *g_scalar, + const int mixed, const smallfelem pre_comp[][17][3], + const smallfelem g_pre_comp[2][16][3]) +{ + int i, skip; + unsigned num, gen_mul = (g_scalar != NULL); + felem nq[3], ftmp; + smallfelem tmp[3]; + u64 bits; + u8 sign, digit; + + /* set nq to the point at infinity */ + memset(nq, 0, 3 * sizeof(felem)); + + /* + * Loop over all scalars msb-to-lsb, interleaving additions of multiples + * of the generator (two in each of the last 32 rounds) and additions of + * other points multiples (every 5th round). + */ + skip = 1; /* save two point operations in the first + * round */ + for (i = (num_points ? 255 : 31); i >= 0; --i) { + /* double */ + if (!skip) + point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]); + + /* add multiples of the generator */ + if (gen_mul && (i <= 31)) { + /* first, look 32 bits upwards */ + bits = get_bit(g_scalar, i + 224) << 3; + bits |= get_bit(g_scalar, i + 160) << 2; + bits |= get_bit(g_scalar, i + 96) << 1; + bits |= get_bit(g_scalar, i + 32); + /* select the point to add, in constant time */ + select_point(bits, 16, g_pre_comp[1], tmp); + + if (!skip) { + /* Arg 1 below is for "mixed" */ + point_add(nq[0], nq[1], nq[2], + nq[0], nq[1], nq[2], 1, tmp[0], tmp[1], tmp[2]); + } else { + smallfelem_expand(nq[0], tmp[0]); + smallfelem_expand(nq[1], tmp[1]); + smallfelem_expand(nq[2], tmp[2]); + skip = 0; + } + + /* second, look at the current position */ + bits = get_bit(g_scalar, i + 192) << 3; + bits |= get_bit(g_scalar, i + 128) << 2; + bits |= get_bit(g_scalar, i + 64) << 1; + bits |= get_bit(g_scalar, i); + /* select the point to add, in constant time */ + select_point(bits, 16, g_pre_comp[0], tmp); + /* Arg 1 below is for "mixed" */ + point_add(nq[0], nq[1], nq[2], + nq[0], nq[1], nq[2], 1, tmp[0], tmp[1], tmp[2]); + } + + /* do other additions every 5 doublings */ + if (num_points && (i % 5 == 0)) { + /* loop over all scalars */ + for (num = 0; num < num_points; ++num) { + bits = get_bit(scalars[num], i + 4) << 5; + bits |= get_bit(scalars[num], i + 3) << 4; + bits |= get_bit(scalars[num], i + 2) << 3; + bits |= get_bit(scalars[num], i + 1) << 2; + bits |= get_bit(scalars[num], i) << 1; + bits |= get_bit(scalars[num], i - 1); + ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits); + + /* + * select the point to add or subtract, in constant time + */ + select_point(digit, 17, pre_comp[num], tmp); + smallfelem_neg(ftmp, tmp[1]); /* (X, -Y, Z) is the negative + * point */ + copy_small_conditional(ftmp, tmp[1], (((limb) sign) - 1)); + felem_contract(tmp[1], ftmp); + + if (!skip) { + point_add(nq[0], nq[1], nq[2], + nq[0], nq[1], nq[2], + mixed, tmp[0], tmp[1], tmp[2]); + } else { + smallfelem_expand(nq[0], tmp[0]); + smallfelem_expand(nq[1], tmp[1]); + smallfelem_expand(nq[2], tmp[2]); + skip = 0; + } + } + } + } + felem_assign(x_out, nq[0]); + felem_assign(y_out, nq[1]); + felem_assign(z_out, nq[2]); +} /* Precomputation for the group generator. */ typedef struct { - smallfelem g_pre_comp[2][16][3]; - int references; + smallfelem g_pre_comp[2][16][3]; + int references; } NISTP256_PRE_COMP; const EC_METHOD *EC_GFp_nistp256_method(void) - { - static const EC_METHOD ret = { - EC_FLAGS_DEFAULT_OCT, - NID_X9_62_prime_field, - ec_GFp_nistp256_group_init, - ec_GFp_simple_group_finish, - ec_GFp_simple_group_clear_finish, - ec_GFp_nist_group_copy, - ec_GFp_nistp256_group_set_curve, - ec_GFp_simple_group_get_curve, - ec_GFp_simple_group_get_degree, - ec_GFp_simple_group_check_discriminant, - ec_GFp_simple_point_init, - ec_GFp_simple_point_finish, - ec_GFp_simple_point_clear_finish, - ec_GFp_simple_point_copy, - ec_GFp_simple_point_set_to_infinity, - ec_GFp_simple_set_Jprojective_coordinates_GFp, - ec_GFp_simple_get_Jprojective_coordinates_GFp, - ec_GFp_simple_point_set_affine_coordinates, - ec_GFp_nistp256_point_get_affine_coordinates, - 0 /* point_set_compressed_coordinates */, - 0 /* point2oct */, - 0 /* oct2point */, - ec_GFp_simple_add, - ec_GFp_simple_dbl, - ec_GFp_simple_invert, - 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, - ec_GFp_nistp256_points_mul, - ec_GFp_nistp256_precompute_mult, - ec_GFp_nistp256_have_precompute_mult, - ec_GFp_nist_field_mul, - ec_GFp_nist_field_sqr, - 0 /* field_div */, - 0 /* field_encode */, - 0 /* field_decode */, - 0 /* field_set_to_one */ }; - - return &ret; - } +{ + static const EC_METHOD ret = { + EC_FLAGS_DEFAULT_OCT, + NID_X9_62_prime_field, + ec_GFp_nistp256_group_init, + ec_GFp_simple_group_finish, + ec_GFp_simple_group_clear_finish, + ec_GFp_nist_group_copy, + ec_GFp_nistp256_group_set_curve, + ec_GFp_simple_group_get_curve, + ec_GFp_simple_group_get_degree, + ec_GFp_simple_group_check_discriminant, + ec_GFp_simple_point_init, + ec_GFp_simple_point_finish, + ec_GFp_simple_point_clear_finish, + ec_GFp_simple_point_copy, + ec_GFp_simple_point_set_to_infinity, + ec_GFp_simple_set_Jprojective_coordinates_GFp, + ec_GFp_simple_get_Jprojective_coordinates_GFp, + ec_GFp_simple_point_set_affine_coordinates, + ec_GFp_nistp256_point_get_affine_coordinates, + 0 /* point_set_compressed_coordinates */ , + 0 /* point2oct */ , + 0 /* oct2point */ , + ec_GFp_simple_add, + ec_GFp_simple_dbl, + ec_GFp_simple_invert, + 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, + ec_GFp_nistp256_points_mul, + ec_GFp_nistp256_precompute_mult, + ec_GFp_nistp256_have_precompute_mult, + ec_GFp_nist_field_mul, + ec_GFp_nist_field_sqr, + 0 /* field_div */ , + 0 /* field_encode */ , + 0 /* field_decode */ , + 0 /* field_set_to_one */ + }; + + return &ret; +} /******************************************************************************/ -/* FUNCTIONS TO MANAGE PRECOMPUTATION +/* + * FUNCTIONS TO MANAGE PRECOMPUTATION */ static NISTP256_PRE_COMP *nistp256_pre_comp_new() - { - NISTP256_PRE_COMP *ret = NULL; - ret = (NISTP256_PRE_COMP *) OPENSSL_malloc(sizeof *ret); - if (!ret) - { - ECerr(EC_F_NISTP256_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); - return ret; - } - memset(ret->g_pre_comp, 0, sizeof(ret->g_pre_comp)); - ret->references = 1; - return ret; - } +{ + NISTP256_PRE_COMP *ret = NULL; + ret = (NISTP256_PRE_COMP *) OPENSSL_malloc(sizeof *ret); + if (!ret) { + ECerr(EC_F_NISTP256_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + return ret; + } + memset(ret->g_pre_comp, 0, sizeof(ret->g_pre_comp)); + ret->references = 1; + return ret; +} static void *nistp256_pre_comp_dup(void *src_) - { - NISTP256_PRE_COMP *src = src_; +{ + NISTP256_PRE_COMP *src = src_; - /* no need to actually copy, these objects never change! */ - CRYPTO_add(&src->references, 1, CRYPTO_LOCK_EC_PRE_COMP); + /* no need to actually copy, these objects never change! */ + CRYPTO_add(&src->references, 1, CRYPTO_LOCK_EC_PRE_COMP); - return src_; - } + return src_; +} static void nistp256_pre_comp_free(void *pre_) - { - int i; - NISTP256_PRE_COMP *pre = pre_; +{ + int i; + NISTP256_PRE_COMP *pre = pre_; - if (!pre) - return; + if (!pre) + return; - i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP); - if (i > 0) - return; + i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP); + if (i > 0) + return; - OPENSSL_free(pre); - } + OPENSSL_free(pre); +} static void nistp256_pre_comp_clear_free(void *pre_) - { - int i; - NISTP256_PRE_COMP *pre = pre_; +{ + int i; + NISTP256_PRE_COMP *pre = pre_; - if (!pre) - return; + if (!pre) + return; - i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP); - if (i > 0) - return; + i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP); + if (i > 0) + return; - OPENSSL_cleanse(pre, sizeof *pre); - OPENSSL_free(pre); - } + OPENSSL_cleanse(pre, sizeof *pre); + OPENSSL_free(pre); +} /******************************************************************************/ -/* OPENSSL EC_METHOD FUNCTIONS +/* + * OPENSSL EC_METHOD FUNCTIONS */ int ec_GFp_nistp256_group_init(EC_GROUP *group) - { - int ret; - ret = ec_GFp_simple_group_init(group); - group->a_is_minus3 = 1; - return ret; - } +{ + int ret; + ret = ec_GFp_simple_group_init(group); + group->a_is_minus3 = 1; + return ret; +} int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p, - const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) - { - int ret = 0; - BN_CTX *new_ctx = NULL; - BIGNUM *curve_p, *curve_a, *curve_b; - - if (ctx == NULL) - if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0; - BN_CTX_start(ctx); - if (((curve_p = BN_CTX_get(ctx)) == NULL) || - ((curve_a = BN_CTX_get(ctx)) == NULL) || - ((curve_b = BN_CTX_get(ctx)) == NULL)) goto err; - BN_bin2bn(nistp256_curve_params[0], sizeof(felem_bytearray), curve_p); - BN_bin2bn(nistp256_curve_params[1], sizeof(felem_bytearray), curve_a); - BN_bin2bn(nistp256_curve_params[2], sizeof(felem_bytearray), curve_b); - if ((BN_cmp(curve_p, p)) || (BN_cmp(curve_a, a)) || - (BN_cmp(curve_b, b))) - { - ECerr(EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE, - EC_R_WRONG_CURVE_PARAMETERS); - goto err; - } - group->field_mod_func = BN_nist_mod_256; - ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); -err: - BN_CTX_end(ctx); - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - return ret; - } - -/* Takes the Jacobian coordinates (X, Y, Z) of a point and returns - * (X', Y') = (X/Z^2, Y/Z^3) */ + const BIGNUM *a, const BIGNUM *b, + BN_CTX *ctx) +{ + int ret = 0; + BN_CTX *new_ctx = NULL; + BIGNUM *curve_p, *curve_a, *curve_b; + + if (ctx == NULL) + if ((ctx = new_ctx = BN_CTX_new()) == NULL) + return 0; + BN_CTX_start(ctx); + if (((curve_p = BN_CTX_get(ctx)) == NULL) || + ((curve_a = BN_CTX_get(ctx)) == NULL) || + ((curve_b = BN_CTX_get(ctx)) == NULL)) + goto err; + BN_bin2bn(nistp256_curve_params[0], sizeof(felem_bytearray), curve_p); + BN_bin2bn(nistp256_curve_params[1], sizeof(felem_bytearray), curve_a); + BN_bin2bn(nistp256_curve_params[2], sizeof(felem_bytearray), curve_b); + if ((BN_cmp(curve_p, p)) || (BN_cmp(curve_a, a)) || (BN_cmp(curve_b, b))) { + ECerr(EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE, + EC_R_WRONG_CURVE_PARAMETERS); + goto err; + } + group->field_mod_func = BN_nist_mod_256; + ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); + err: + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; +} + +/* + * Takes the Jacobian coordinates (X, Y, Z) of a point and returns (X', Y') = + * (X/Z^2, Y/Z^3) + */ int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group, - const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx) - { - felem z1, z2, x_in, y_in; - smallfelem x_out, y_out; - longfelem tmp; - - if (EC_POINT_is_at_infinity(group, point)) - { - ECerr(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES, - EC_R_POINT_AT_INFINITY); - return 0; - } - if ((!BN_to_felem(x_in, &point->X)) || (!BN_to_felem(y_in, &point->Y)) || - (!BN_to_felem(z1, &point->Z))) return 0; - felem_inv(z2, z1); - felem_square(tmp, z2); felem_reduce(z1, tmp); - felem_mul(tmp, x_in, z1); felem_reduce(x_in, tmp); - felem_contract(x_out, x_in); - if (x != NULL) - { - if (!smallfelem_to_BN(x, x_out)) { - ECerr(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES, - ERR_R_BN_LIB); - return 0; - } - } - felem_mul(tmp, z1, z2); felem_reduce(z1, tmp); - felem_mul(tmp, y_in, z1); felem_reduce(y_in, tmp); - felem_contract(y_out, y_in); - if (y != NULL) - { - if (!smallfelem_to_BN(y, y_out)) - { - ECerr(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES, - ERR_R_BN_LIB); - return 0; - } - } - return 1; - } - -static void make_points_affine(size_t num, smallfelem points[/* num */][3], smallfelem tmp_smallfelems[/* num+1 */]) - { - /* Runs in constant time, unless an input is the point at infinity - * (which normally shouldn't happen). */ - ec_GFp_nistp_points_make_affine_internal( - num, - points, - sizeof(smallfelem), - tmp_smallfelems, - (void (*)(void *)) smallfelem_one, - (int (*)(const void *)) smallfelem_is_zero_int, - (void (*)(void *, const void *)) smallfelem_assign, - (void (*)(void *, const void *)) smallfelem_square_contract, - (void (*)(void *, const void *, const void *)) smallfelem_mul_contract, - (void (*)(void *, const void *)) smallfelem_inv_contract, - (void (*)(void *, const void *)) smallfelem_assign /* nothing to contract */); - } - -/* Computes scalar*generator + \sum scalars[i]*points[i], ignoring NULL values - * Result is stored in r (r can equal one of the inputs). */ + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx) +{ + felem z1, z2, x_in, y_in; + smallfelem x_out, y_out; + longfelem tmp; + + if (EC_POINT_is_at_infinity(group, point)) { + ECerr(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES, + EC_R_POINT_AT_INFINITY); + return 0; + } + if ((!BN_to_felem(x_in, &point->X)) || (!BN_to_felem(y_in, &point->Y)) || + (!BN_to_felem(z1, &point->Z))) + return 0; + felem_inv(z2, z1); + felem_square(tmp, z2); + felem_reduce(z1, tmp); + felem_mul(tmp, x_in, z1); + felem_reduce(x_in, tmp); + felem_contract(x_out, x_in); + if (x != NULL) { + if (!smallfelem_to_BN(x, x_out)) { + ECerr(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES, + ERR_R_BN_LIB); + return 0; + } + } + felem_mul(tmp, z1, z2); + felem_reduce(z1, tmp); + felem_mul(tmp, y_in, z1); + felem_reduce(y_in, tmp); + felem_contract(y_out, y_in); + if (y != NULL) { + if (!smallfelem_to_BN(y, y_out)) { + ECerr(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES, + ERR_R_BN_LIB); + return 0; + } + } + return 1; +} + +/* points below is of size |num|, and tmp_smallfelems is of size |num+1| */ +static void make_points_affine(size_t num, smallfelem points[][3], + smallfelem tmp_smallfelems[]) +{ + /* + * Runs in constant time, unless an input is the point at infinity (which + * normally shouldn't happen). + */ + ec_GFp_nistp_points_make_affine_internal(num, + points, + sizeof(smallfelem), + tmp_smallfelems, + (void (*)(void *))smallfelem_one, + (int (*)(const void *)) + smallfelem_is_zero_int, + (void (*)(void *, const void *)) + smallfelem_assign, + (void (*)(void *, const void *)) + smallfelem_square_contract, + (void (*) + (void *, const void *, + const void *)) + smallfelem_mul_contract, + (void (*)(void *, const void *)) + smallfelem_inv_contract, + /* nothing to contract */ + (void (*)(void *, const void *)) + smallfelem_assign); +} + +/* + * Computes scalar*generator + \sum scalars[i]*points[i], ignoring NULL + * values Result is stored in r (r can equal one of the inputs). + */ int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r, - const BIGNUM *scalar, size_t num, const EC_POINT *points[], - const BIGNUM *scalars[], BN_CTX *ctx) - { - int ret = 0; - int j; - int mixed = 0; - BN_CTX *new_ctx = NULL; - BIGNUM *x, *y, *z, *tmp_scalar; - felem_bytearray g_secret; - felem_bytearray *secrets = NULL; - smallfelem (*pre_comp)[17][3] = NULL; - smallfelem *tmp_smallfelems = NULL; - felem_bytearray tmp; - unsigned i, num_bytes; - int have_pre_comp = 0; - size_t num_points = num; - smallfelem x_in, y_in, z_in; - felem x_out, y_out, z_out; - NISTP256_PRE_COMP *pre = NULL; - const smallfelem (*g_pre_comp)[16][3] = NULL; - EC_POINT *generator = NULL; - const EC_POINT *p = NULL; - const BIGNUM *p_scalar = NULL; - - if (ctx == NULL) - if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0; - BN_CTX_start(ctx); - if (((x = BN_CTX_get(ctx)) == NULL) || - ((y = BN_CTX_get(ctx)) == NULL) || - ((z = BN_CTX_get(ctx)) == NULL) || - ((tmp_scalar = BN_CTX_get(ctx)) == NULL)) - goto err; - - if (scalar != NULL) - { - pre = EC_EX_DATA_get_data(group->extra_data, - nistp256_pre_comp_dup, nistp256_pre_comp_free, - nistp256_pre_comp_clear_free); - if (pre) - /* we have precomputation, try to use it */ - g_pre_comp = (const smallfelem (*)[16][3]) pre->g_pre_comp; - else - /* try to use the standard precomputation */ - g_pre_comp = &gmul[0]; - generator = EC_POINT_new(group); - if (generator == NULL) - goto err; - /* get the generator from precomputation */ - if (!smallfelem_to_BN(x, g_pre_comp[0][1][0]) || - !smallfelem_to_BN(y, g_pre_comp[0][1][1]) || - !smallfelem_to_BN(z, g_pre_comp[0][1][2])) - { - ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB); - goto err; - } - if (!EC_POINT_set_Jprojective_coordinates_GFp(group, - generator, x, y, z, ctx)) - goto err; - if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) - /* precomputation matches generator */ - have_pre_comp = 1; - else - /* we don't have valid precomputation: - * treat the generator as a random point */ - num_points++; - } - if (num_points > 0) - { - if (num_points >= 3) - { - /* unless we precompute multiples for just one or two points, - * converting those into affine form is time well spent */ - mixed = 1; - } - secrets = OPENSSL_malloc(num_points * sizeof(felem_bytearray)); - pre_comp = OPENSSL_malloc(num_points * 17 * 3 * sizeof(smallfelem)); - if (mixed) - tmp_smallfelems = OPENSSL_malloc((num_points * 17 + 1) * sizeof(smallfelem)); - if ((secrets == NULL) || (pre_comp == NULL) || (mixed && (tmp_smallfelems == NULL))) - { - ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_MALLOC_FAILURE); - goto err; - } - - /* we treat NULL scalars as 0, and NULL points as points at infinity, - * i.e., they contribute nothing to the linear combination */ - memset(secrets, 0, num_points * sizeof(felem_bytearray)); - memset(pre_comp, 0, num_points * 17 * 3 * sizeof(smallfelem)); - for (i = 0; i < num_points; ++i) - { - if (i == num) - /* we didn't have a valid precomputation, so we pick - * the generator */ - { - p = EC_GROUP_get0_generator(group); - p_scalar = scalar; - } - else - /* the i^th point */ - { - p = points[i]; - p_scalar = scalars[i]; - } - if ((p_scalar != NULL) && (p != NULL)) - { - /* reduce scalar to 0 <= scalar < 2^256 */ - if ((BN_num_bits(p_scalar) > 256) || (BN_is_negative(p_scalar))) - { - /* this is an unusual input, and we don't guarantee - * constant-timeness */ - if (!BN_nnmod(tmp_scalar, p_scalar, &group->order, ctx)) - { - ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB); - goto err; - } - num_bytes = BN_bn2bin(tmp_scalar, tmp); - } - else - num_bytes = BN_bn2bin(p_scalar, tmp); - flip_endian(secrets[i], tmp, num_bytes); - /* precompute multiples */ - if ((!BN_to_felem(x_out, &p->X)) || - (!BN_to_felem(y_out, &p->Y)) || - (!BN_to_felem(z_out, &p->Z))) goto err; - felem_shrink(pre_comp[i][1][0], x_out); - felem_shrink(pre_comp[i][1][1], y_out); - felem_shrink(pre_comp[i][1][2], z_out); - for (j = 2; j <= 16; ++j) - { - if (j & 1) - { - point_add_small( - pre_comp[i][j][0], pre_comp[i][j][1], pre_comp[i][j][2], - pre_comp[i][1][0], pre_comp[i][1][1], pre_comp[i][1][2], - pre_comp[i][j-1][0], pre_comp[i][j-1][1], pre_comp[i][j-1][2]); - } - else - { - point_double_small( - pre_comp[i][j][0], pre_comp[i][j][1], pre_comp[i][j][2], - pre_comp[i][j/2][0], pre_comp[i][j/2][1], pre_comp[i][j/2][2]); - } - } - } - } - if (mixed) - make_points_affine(num_points * 17, pre_comp[0], tmp_smallfelems); - } - - /* the scalar for the generator */ - if ((scalar != NULL) && (have_pre_comp)) - { - memset(g_secret, 0, sizeof(g_secret)); - /* reduce scalar to 0 <= scalar < 2^256 */ - if ((BN_num_bits(scalar) > 256) || (BN_is_negative(scalar))) - { - /* this is an unusual input, and we don't guarantee - * constant-timeness */ - if (!BN_nnmod(tmp_scalar, scalar, &group->order, ctx)) - { - ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB); - goto err; - } - num_bytes = BN_bn2bin(tmp_scalar, tmp); - } - else - num_bytes = BN_bn2bin(scalar, tmp); - flip_endian(g_secret, tmp, num_bytes); - /* do the multiplication with generator precomputation*/ - batch_mul(x_out, y_out, z_out, - (const felem_bytearray (*)) secrets, num_points, - g_secret, - mixed, (const smallfelem (*)[17][3]) pre_comp, - g_pre_comp); - } - else - /* do the multiplication without generator precomputation */ - batch_mul(x_out, y_out, z_out, - (const felem_bytearray (*)) secrets, num_points, - NULL, mixed, (const smallfelem (*)[17][3]) pre_comp, NULL); - /* reduce the output to its unique minimal representation */ - felem_contract(x_in, x_out); - felem_contract(y_in, y_out); - felem_contract(z_in, z_out); - if ((!smallfelem_to_BN(x, x_in)) || (!smallfelem_to_BN(y, y_in)) || - (!smallfelem_to_BN(z, z_in))) - { - ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB); - goto err; - } - ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx); - -err: - BN_CTX_end(ctx); - if (generator != NULL) - EC_POINT_free(generator); - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - if (secrets != NULL) - OPENSSL_free(secrets); - if (pre_comp != NULL) - OPENSSL_free(pre_comp); - if (tmp_smallfelems != NULL) - OPENSSL_free(tmp_smallfelems); - return ret; - } + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], + const BIGNUM *scalars[], BN_CTX *ctx) +{ + int ret = 0; + int j; + int mixed = 0; + BN_CTX *new_ctx = NULL; + BIGNUM *x, *y, *z, *tmp_scalar; + felem_bytearray g_secret; + felem_bytearray *secrets = NULL; + smallfelem(*pre_comp)[17][3] = NULL; + smallfelem *tmp_smallfelems = NULL; + felem_bytearray tmp; + unsigned i, num_bytes; + int have_pre_comp = 0; + size_t num_points = num; + smallfelem x_in, y_in, z_in; + felem x_out, y_out, z_out; + NISTP256_PRE_COMP *pre = NULL; + const smallfelem(*g_pre_comp)[16][3] = NULL; + EC_POINT *generator = NULL; + const EC_POINT *p = NULL; + const BIGNUM *p_scalar = NULL; + + if (ctx == NULL) + if ((ctx = new_ctx = BN_CTX_new()) == NULL) + return 0; + BN_CTX_start(ctx); + if (((x = BN_CTX_get(ctx)) == NULL) || + ((y = BN_CTX_get(ctx)) == NULL) || + ((z = BN_CTX_get(ctx)) == NULL) || + ((tmp_scalar = BN_CTX_get(ctx)) == NULL)) + goto err; + + if (scalar != NULL) { + pre = EC_EX_DATA_get_data(group->extra_data, + nistp256_pre_comp_dup, + nistp256_pre_comp_free, + nistp256_pre_comp_clear_free); + if (pre) + /* we have precomputation, try to use it */ + g_pre_comp = (const smallfelem(*)[16][3])pre->g_pre_comp; + else + /* try to use the standard precomputation */ + g_pre_comp = &gmul[0]; + generator = EC_POINT_new(group); + if (generator == NULL) + goto err; + /* get the generator from precomputation */ + if (!smallfelem_to_BN(x, g_pre_comp[0][1][0]) || + !smallfelem_to_BN(y, g_pre_comp[0][1][1]) || + !smallfelem_to_BN(z, g_pre_comp[0][1][2])) { + ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB); + goto err; + } + if (!EC_POINT_set_Jprojective_coordinates_GFp(group, + generator, x, y, z, + ctx)) + goto err; + if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) + /* precomputation matches generator */ + have_pre_comp = 1; + else + /* + * we don't have valid precomputation: treat the generator as a + * random point + */ + num_points++; + } + if (num_points > 0) { + if (num_points >= 3) { + /* + * unless we precompute multiples for just one or two points, + * converting those into affine form is time well spent + */ + mixed = 1; + } + secrets = OPENSSL_malloc(num_points * sizeof(felem_bytearray)); + pre_comp = OPENSSL_malloc(num_points * 17 * 3 * sizeof(smallfelem)); + if (mixed) + tmp_smallfelems = + OPENSSL_malloc((num_points * 17 + 1) * sizeof(smallfelem)); + if ((secrets == NULL) || (pre_comp == NULL) + || (mixed && (tmp_smallfelems == NULL))) { + ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* + * we treat NULL scalars as 0, and NULL points as points at infinity, + * i.e., they contribute nothing to the linear combination + */ + memset(secrets, 0, num_points * sizeof(felem_bytearray)); + memset(pre_comp, 0, num_points * 17 * 3 * sizeof(smallfelem)); + for (i = 0; i < num_points; ++i) { + if (i == num) + /* + * we didn't have a valid precomputation, so we pick the + * generator + */ + { + p = EC_GROUP_get0_generator(group); + p_scalar = scalar; + } else + /* the i^th point */ + { + p = points[i]; + p_scalar = scalars[i]; + } + if ((p_scalar != NULL) && (p != NULL)) { + /* reduce scalar to 0 <= scalar < 2^256 */ + if ((BN_num_bits(p_scalar) > 256) + || (BN_is_negative(p_scalar))) { + /* + * this is an unusual input, and we don't guarantee + * constant-timeness + */ + if (!BN_nnmod(tmp_scalar, p_scalar, &group->order, ctx)) { + ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB); + goto err; + } + num_bytes = BN_bn2bin(tmp_scalar, tmp); + } else + num_bytes = BN_bn2bin(p_scalar, tmp); + flip_endian(secrets[i], tmp, num_bytes); + /* precompute multiples */ + if ((!BN_to_felem(x_out, &p->X)) || + (!BN_to_felem(y_out, &p->Y)) || + (!BN_to_felem(z_out, &p->Z))) + goto err; + felem_shrink(pre_comp[i][1][0], x_out); + felem_shrink(pre_comp[i][1][1], y_out); + felem_shrink(pre_comp[i][1][2], z_out); + for (j = 2; j <= 16; ++j) { + if (j & 1) { + point_add_small(pre_comp[i][j][0], pre_comp[i][j][1], + pre_comp[i][j][2], pre_comp[i][1][0], + pre_comp[i][1][1], pre_comp[i][1][2], + pre_comp[i][j - 1][0], + pre_comp[i][j - 1][1], + pre_comp[i][j - 1][2]); + } else { + point_double_small(pre_comp[i][j][0], + pre_comp[i][j][1], + pre_comp[i][j][2], + pre_comp[i][j / 2][0], + pre_comp[i][j / 2][1], + pre_comp[i][j / 2][2]); + } + } + } + } + if (mixed) + make_points_affine(num_points * 17, pre_comp[0], tmp_smallfelems); + } + + /* the scalar for the generator */ + if ((scalar != NULL) && (have_pre_comp)) { + memset(g_secret, 0, sizeof(g_secret)); + /* reduce scalar to 0 <= scalar < 2^256 */ + if ((BN_num_bits(scalar) > 256) || (BN_is_negative(scalar))) { + /* + * this is an unusual input, and we don't guarantee + * constant-timeness + */ + if (!BN_nnmod(tmp_scalar, scalar, &group->order, ctx)) { + ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB); + goto err; + } + num_bytes = BN_bn2bin(tmp_scalar, tmp); + } else + num_bytes = BN_bn2bin(scalar, tmp); + flip_endian(g_secret, tmp, num_bytes); + /* do the multiplication with generator precomputation */ + batch_mul(x_out, y_out, z_out, + (const felem_bytearray(*))secrets, num_points, + g_secret, + mixed, (const smallfelem(*)[17][3])pre_comp, g_pre_comp); + } else + /* do the multiplication without generator precomputation */ + batch_mul(x_out, y_out, z_out, + (const felem_bytearray(*))secrets, num_points, + NULL, mixed, (const smallfelem(*)[17][3])pre_comp, NULL); + /* reduce the output to its unique minimal representation */ + felem_contract(x_in, x_out); + felem_contract(y_in, y_out); + felem_contract(z_in, z_out); + if ((!smallfelem_to_BN(x, x_in)) || (!smallfelem_to_BN(y, y_in)) || + (!smallfelem_to_BN(z, z_in))) { + ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB); + goto err; + } + ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx); + + err: + BN_CTX_end(ctx); + if (generator != NULL) + EC_POINT_free(generator); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + if (secrets != NULL) + OPENSSL_free(secrets); + if (pre_comp != NULL) + OPENSSL_free(pre_comp); + if (tmp_smallfelems != NULL) + OPENSSL_free(tmp_smallfelems); + return ret; +} int ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx) - { - int ret = 0; - NISTP256_PRE_COMP *pre = NULL; - int i, j; - BN_CTX *new_ctx = NULL; - BIGNUM *x, *y; - EC_POINT *generator = NULL; - smallfelem tmp_smallfelems[32]; - felem x_tmp, y_tmp, z_tmp; - - /* throw away old precomputation */ - EC_EX_DATA_free_data(&group->extra_data, nistp256_pre_comp_dup, - nistp256_pre_comp_free, nistp256_pre_comp_clear_free); - if (ctx == NULL) - if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0; - BN_CTX_start(ctx); - if (((x = BN_CTX_get(ctx)) == NULL) || - ((y = BN_CTX_get(ctx)) == NULL)) - goto err; - /* get the generator */ - if (group->generator == NULL) goto err; - generator = EC_POINT_new(group); - if (generator == NULL) - goto err; - BN_bin2bn(nistp256_curve_params[3], sizeof (felem_bytearray), x); - BN_bin2bn(nistp256_curve_params[4], sizeof (felem_bytearray), y); - if (!EC_POINT_set_affine_coordinates_GFp(group, generator, x, y, ctx)) - goto err; - if ((pre = nistp256_pre_comp_new()) == NULL) - goto err; - /* if the generator is the standard one, use built-in precomputation */ - if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) - { - memcpy(pre->g_pre_comp, gmul, sizeof(pre->g_pre_comp)); - ret = 1; - goto err; - } - if ((!BN_to_felem(x_tmp, &group->generator->X)) || - (!BN_to_felem(y_tmp, &group->generator->Y)) || - (!BN_to_felem(z_tmp, &group->generator->Z))) - goto err; - felem_shrink(pre->g_pre_comp[0][1][0], x_tmp); - felem_shrink(pre->g_pre_comp[0][1][1], y_tmp); - felem_shrink(pre->g_pre_comp[0][1][2], z_tmp); - /* compute 2^64*G, 2^128*G, 2^192*G for the first table, - * 2^32*G, 2^96*G, 2^160*G, 2^224*G for the second one - */ - for (i = 1; i <= 8; i <<= 1) - { - point_double_small( - pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2], - pre->g_pre_comp[0][i][0], pre->g_pre_comp[0][i][1], pre->g_pre_comp[0][i][2]); - for (j = 0; j < 31; ++j) - { - point_double_small( - pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2], - pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2]); - } - if (i == 8) - break; - point_double_small( - pre->g_pre_comp[0][2*i][0], pre->g_pre_comp[0][2*i][1], pre->g_pre_comp[0][2*i][2], - pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2]); - for (j = 0; j < 31; ++j) - { - point_double_small( - pre->g_pre_comp[0][2*i][0], pre->g_pre_comp[0][2*i][1], pre->g_pre_comp[0][2*i][2], - pre->g_pre_comp[0][2*i][0], pre->g_pre_comp[0][2*i][1], pre->g_pre_comp[0][2*i][2]); - } - } - for (i = 0; i < 2; i++) - { - /* g_pre_comp[i][0] is the point at infinity */ - memset(pre->g_pre_comp[i][0], 0, sizeof(pre->g_pre_comp[i][0])); - /* the remaining multiples */ - /* 2^64*G + 2^128*G resp. 2^96*G + 2^160*G */ - point_add_small( - pre->g_pre_comp[i][6][0], pre->g_pre_comp[i][6][1], pre->g_pre_comp[i][6][2], - pre->g_pre_comp[i][4][0], pre->g_pre_comp[i][4][1], pre->g_pre_comp[i][4][2], - pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], pre->g_pre_comp[i][2][2]); - /* 2^64*G + 2^192*G resp. 2^96*G + 2^224*G */ - point_add_small( - pre->g_pre_comp[i][10][0], pre->g_pre_comp[i][10][1], pre->g_pre_comp[i][10][2], - pre->g_pre_comp[i][8][0], pre->g_pre_comp[i][8][1], pre->g_pre_comp[i][8][2], - pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], pre->g_pre_comp[i][2][2]); - /* 2^128*G + 2^192*G resp. 2^160*G + 2^224*G */ - point_add_small( - pre->g_pre_comp[i][12][0], pre->g_pre_comp[i][12][1], pre->g_pre_comp[i][12][2], - pre->g_pre_comp[i][8][0], pre->g_pre_comp[i][8][1], pre->g_pre_comp[i][8][2], - pre->g_pre_comp[i][4][0], pre->g_pre_comp[i][4][1], pre->g_pre_comp[i][4][2]); - /* 2^64*G + 2^128*G + 2^192*G resp. 2^96*G + 2^160*G + 2^224*G */ - point_add_small( - pre->g_pre_comp[i][14][0], pre->g_pre_comp[i][14][1], pre->g_pre_comp[i][14][2], - pre->g_pre_comp[i][12][0], pre->g_pre_comp[i][12][1], pre->g_pre_comp[i][12][2], - pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], pre->g_pre_comp[i][2][2]); - for (j = 1; j < 8; ++j) - { - /* odd multiples: add G resp. 2^32*G */ - point_add_small( - pre->g_pre_comp[i][2*j+1][0], pre->g_pre_comp[i][2*j+1][1], pre->g_pre_comp[i][2*j+1][2], - pre->g_pre_comp[i][2*j][0], pre->g_pre_comp[i][2*j][1], pre->g_pre_comp[i][2*j][2], - pre->g_pre_comp[i][1][0], pre->g_pre_comp[i][1][1], pre->g_pre_comp[i][1][2]); - } - } - make_points_affine(31, &(pre->g_pre_comp[0][1]), tmp_smallfelems); - - if (!EC_EX_DATA_set_data(&group->extra_data, pre, nistp256_pre_comp_dup, - nistp256_pre_comp_free, nistp256_pre_comp_clear_free)) - goto err; - ret = 1; - pre = NULL; +{ + int ret = 0; + NISTP256_PRE_COMP *pre = NULL; + int i, j; + BN_CTX *new_ctx = NULL; + BIGNUM *x, *y; + EC_POINT *generator = NULL; + smallfelem tmp_smallfelems[32]; + felem x_tmp, y_tmp, z_tmp; + + /* throw away old precomputation */ + EC_EX_DATA_free_data(&group->extra_data, nistp256_pre_comp_dup, + nistp256_pre_comp_free, + nistp256_pre_comp_clear_free); + if (ctx == NULL) + if ((ctx = new_ctx = BN_CTX_new()) == NULL) + return 0; + BN_CTX_start(ctx); + if (((x = BN_CTX_get(ctx)) == NULL) || ((y = BN_CTX_get(ctx)) == NULL)) + goto err; + /* get the generator */ + if (group->generator == NULL) + goto err; + generator = EC_POINT_new(group); + if (generator == NULL) + goto err; + BN_bin2bn(nistp256_curve_params[3], sizeof(felem_bytearray), x); + BN_bin2bn(nistp256_curve_params[4], sizeof(felem_bytearray), y); + if (!EC_POINT_set_affine_coordinates_GFp(group, generator, x, y, ctx)) + goto err; + if ((pre = nistp256_pre_comp_new()) == NULL) + goto err; + /* + * if the generator is the standard one, use built-in precomputation + */ + if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) { + memcpy(pre->g_pre_comp, gmul, sizeof(pre->g_pre_comp)); + ret = 1; + goto err; + } + if ((!BN_to_felem(x_tmp, &group->generator->X)) || + (!BN_to_felem(y_tmp, &group->generator->Y)) || + (!BN_to_felem(z_tmp, &group->generator->Z))) + goto err; + felem_shrink(pre->g_pre_comp[0][1][0], x_tmp); + felem_shrink(pre->g_pre_comp[0][1][1], y_tmp); + felem_shrink(pre->g_pre_comp[0][1][2], z_tmp); + /* + * compute 2^64*G, 2^128*G, 2^192*G for the first table, 2^32*G, 2^96*G, + * 2^160*G, 2^224*G for the second one + */ + for (i = 1; i <= 8; i <<= 1) { + point_double_small(pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], + pre->g_pre_comp[1][i][2], pre->g_pre_comp[0][i][0], + pre->g_pre_comp[0][i][1], + pre->g_pre_comp[0][i][2]); + for (j = 0; j < 31; ++j) { + point_double_small(pre->g_pre_comp[1][i][0], + pre->g_pre_comp[1][i][1], + pre->g_pre_comp[1][i][2], + pre->g_pre_comp[1][i][0], + pre->g_pre_comp[1][i][1], + pre->g_pre_comp[1][i][2]); + } + if (i == 8) + break; + point_double_small(pre->g_pre_comp[0][2 * i][0], + pre->g_pre_comp[0][2 * i][1], + pre->g_pre_comp[0][2 * i][2], + pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], + pre->g_pre_comp[1][i][2]); + for (j = 0; j < 31; ++j) { + point_double_small(pre->g_pre_comp[0][2 * i][0], + pre->g_pre_comp[0][2 * i][1], + pre->g_pre_comp[0][2 * i][2], + pre->g_pre_comp[0][2 * i][0], + pre->g_pre_comp[0][2 * i][1], + pre->g_pre_comp[0][2 * i][2]); + } + } + for (i = 0; i < 2; i++) { + /* g_pre_comp[i][0] is the point at infinity */ + memset(pre->g_pre_comp[i][0], 0, sizeof(pre->g_pre_comp[i][0])); + /* the remaining multiples */ + /* 2^64*G + 2^128*G resp. 2^96*G + 2^160*G */ + point_add_small(pre->g_pre_comp[i][6][0], pre->g_pre_comp[i][6][1], + pre->g_pre_comp[i][6][2], pre->g_pre_comp[i][4][0], + pre->g_pre_comp[i][4][1], pre->g_pre_comp[i][4][2], + pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], + pre->g_pre_comp[i][2][2]); + /* 2^64*G + 2^192*G resp. 2^96*G + 2^224*G */ + point_add_small(pre->g_pre_comp[i][10][0], pre->g_pre_comp[i][10][1], + pre->g_pre_comp[i][10][2], pre->g_pre_comp[i][8][0], + pre->g_pre_comp[i][8][1], pre->g_pre_comp[i][8][2], + pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], + pre->g_pre_comp[i][2][2]); + /* 2^128*G + 2^192*G resp. 2^160*G + 2^224*G */ + point_add_small(pre->g_pre_comp[i][12][0], pre->g_pre_comp[i][12][1], + pre->g_pre_comp[i][12][2], pre->g_pre_comp[i][8][0], + pre->g_pre_comp[i][8][1], pre->g_pre_comp[i][8][2], + pre->g_pre_comp[i][4][0], pre->g_pre_comp[i][4][1], + pre->g_pre_comp[i][4][2]); + /* + * 2^64*G + 2^128*G + 2^192*G resp. 2^96*G + 2^160*G + 2^224*G + */ + point_add_small(pre->g_pre_comp[i][14][0], pre->g_pre_comp[i][14][1], + pre->g_pre_comp[i][14][2], pre->g_pre_comp[i][12][0], + pre->g_pre_comp[i][12][1], pre->g_pre_comp[i][12][2], + pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], + pre->g_pre_comp[i][2][2]); + for (j = 1; j < 8; ++j) { + /* odd multiples: add G resp. 2^32*G */ + point_add_small(pre->g_pre_comp[i][2 * j + 1][0], + pre->g_pre_comp[i][2 * j + 1][1], + pre->g_pre_comp[i][2 * j + 1][2], + pre->g_pre_comp[i][2 * j][0], + pre->g_pre_comp[i][2 * j][1], + pre->g_pre_comp[i][2 * j][2], + pre->g_pre_comp[i][1][0], + pre->g_pre_comp[i][1][1], + pre->g_pre_comp[i][1][2]); + } + } + make_points_affine(31, &(pre->g_pre_comp[0][1]), tmp_smallfelems); + + if (!EC_EX_DATA_set_data(&group->extra_data, pre, nistp256_pre_comp_dup, + nistp256_pre_comp_free, + nistp256_pre_comp_clear_free)) + goto err; + ret = 1; + pre = NULL; err: - BN_CTX_end(ctx); - if (generator != NULL) - EC_POINT_free(generator); - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - if (pre) - nistp256_pre_comp_free(pre); - return ret; - } + BN_CTX_end(ctx); + if (generator != NULL) + EC_POINT_free(generator); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + if (pre) + nistp256_pre_comp_free(pre); + return ret; +} int ec_GFp_nistp256_have_precompute_mult(const EC_GROUP *group) - { - if (EC_EX_DATA_get_data(group->extra_data, nistp256_pre_comp_dup, - nistp256_pre_comp_free, nistp256_pre_comp_clear_free) - != NULL) - return 1; - else - return 0; - } +{ + if (EC_EX_DATA_get_data(group->extra_data, nistp256_pre_comp_dup, + nistp256_pre_comp_free, + nistp256_pre_comp_clear_free) + != NULL) + return 1; + else + return 0; +} #else -static void *dummy=&dummy; +static void *dummy = &dummy; #endif diff --git a/openssl/crypto/ec/ecp_nistp521.c b/openssl/crypto/ec/ecp_nistp521.c index 178b655f7..cc7634512 100644 --- a/openssl/crypto/ec/ecp_nistp521.c +++ b/openssl/crypto/ec/ecp_nistp521.c @@ -29,87 +29,90 @@ #include <openssl/opensslconf.h> #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 -#ifndef OPENSSL_SYS_VMS -#include <stdint.h> -#else -#include <inttypes.h> -#endif +# ifndef OPENSSL_SYS_VMS +# include <stdint.h> +# else +# include <inttypes.h> +# endif -#include <string.h> -#include <openssl/err.h> -#include "ec_lcl.h" +# include <string.h> +# include <openssl/err.h> +# include "ec_lcl.h" -#if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +# if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) /* even with gcc, the typedef won't work for 32-bit platforms */ - typedef __uint128_t uint128_t; /* nonstandard; implemented by gcc on 64-bit platforms */ -#else - #error "Need GCC 3.1 or later to define type uint128_t" -#endif +typedef __uint128_t uint128_t; /* nonstandard; implemented by gcc on 64-bit + * platforms */ +# else +# error "Need GCC 3.1 or later to define type uint128_t" +# endif typedef uint8_t u8; typedef uint64_t u64; typedef int64_t s64; -/* The underlying field. - * - * P521 operates over GF(2^521-1). We can serialise an element of this field - * into 66 bytes where the most significant byte contains only a single bit. We - * call this an felem_bytearray. */ +/* + * The underlying field. P521 operates over GF(2^521-1). We can serialise an + * element of this field into 66 bytes where the most significant byte + * contains only a single bit. We call this an felem_bytearray. + */ typedef u8 felem_bytearray[66]; -/* These are the parameters of P521, taken from FIPS 186-3, section D.1.2.5. - * These values are big-endian. */ -static const felem_bytearray nistp521_curve_params[5] = - { - {0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* p */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff}, - {0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* a = -3 */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfc}, - {0x00, 0x51, 0x95, 0x3e, 0xb9, 0x61, 0x8e, 0x1c, /* b */ - 0x9a, 0x1f, 0x92, 0x9a, 0x21, 0xa0, 0xb6, 0x85, - 0x40, 0xee, 0xa2, 0xda, 0x72, 0x5b, 0x99, 0xb3, - 0x15, 0xf3, 0xb8, 0xb4, 0x89, 0x91, 0x8e, 0xf1, - 0x09, 0xe1, 0x56, 0x19, 0x39, 0x51, 0xec, 0x7e, - 0x93, 0x7b, 0x16, 0x52, 0xc0, 0xbd, 0x3b, 0xb1, - 0xbf, 0x07, 0x35, 0x73, 0xdf, 0x88, 0x3d, 0x2c, - 0x34, 0xf1, 0xef, 0x45, 0x1f, 0xd4, 0x6b, 0x50, - 0x3f, 0x00}, - {0x00, 0xc6, 0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, /* x */ - 0xe9, 0xcd, 0x9e, 0x3e, 0xcb, 0x66, 0x23, 0x95, - 0xb4, 0x42, 0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f, - 0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d, - 0x3d, 0xba, 0xa1, 0x4b, 0x5e, 0x77, 0xef, 0xe7, - 0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff, - 0xa8, 0xde, 0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a, - 0x42, 0x9b, 0xf9, 0x7e, 0x7e, 0x31, 0xc2, 0xe5, - 0xbd, 0x66}, - {0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, /* y */ - 0xc0, 0x04, 0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d, - 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, - 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, - 0x66, 0x2c, 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4, - 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, - 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, - 0xc2, 0x40, 0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1, - 0x66, 0x50} - }; - -/* The representation of field elements. +/* + * These are the parameters of P521, taken from FIPS 186-3, section D.1.2.5. + * These values are big-endian. + */ +static const felem_bytearray nistp521_curve_params[5] = { + {0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* p */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff}, + {0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* a = -3 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfc}, + {0x00, 0x51, 0x95, 0x3e, 0xb9, 0x61, 0x8e, 0x1c, /* b */ + 0x9a, 0x1f, 0x92, 0x9a, 0x21, 0xa0, 0xb6, 0x85, + 0x40, 0xee, 0xa2, 0xda, 0x72, 0x5b, 0x99, 0xb3, + 0x15, 0xf3, 0xb8, 0xb4, 0x89, 0x91, 0x8e, 0xf1, + 0x09, 0xe1, 0x56, 0x19, 0x39, 0x51, 0xec, 0x7e, + 0x93, 0x7b, 0x16, 0x52, 0xc0, 0xbd, 0x3b, 0xb1, + 0xbf, 0x07, 0x35, 0x73, 0xdf, 0x88, 0x3d, 0x2c, + 0x34, 0xf1, 0xef, 0x45, 0x1f, 0xd4, 0x6b, 0x50, + 0x3f, 0x00}, + {0x00, 0xc6, 0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, /* x */ + 0xe9, 0xcd, 0x9e, 0x3e, 0xcb, 0x66, 0x23, 0x95, + 0xb4, 0x42, 0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f, + 0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d, + 0x3d, 0xba, 0xa1, 0x4b, 0x5e, 0x77, 0xef, 0xe7, + 0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff, + 0xa8, 0xde, 0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a, + 0x42, 0x9b, 0xf9, 0x7e, 0x7e, 0x31, 0xc2, 0xe5, + 0xbd, 0x66}, + {0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, /* y */ + 0xc0, 0x04, 0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d, + 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, + 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, + 0x66, 0x2c, 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4, + 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, + 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, + 0xc2, 0x40, 0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1, + 0x66, 0x50} +}; + +/*- + * The representation of field elements. * ------------------------------------ * * We represent field elements with nine values. These values are either 64 or @@ -122,7 +125,7 @@ static const felem_bytearray nistp521_curve_params[5] = * A field element with 64-bit limbs is an 'felem'. One with 128-bit limbs is a * 'largefelem' */ -#define NLIMBS 9 +# define NLIMBS 9 typedef uint64_t limb; typedef limb felem[NLIMBS]; @@ -131,350 +134,358 @@ typedef uint128_t largefelem[NLIMBS]; static const limb bottom57bits = 0x1ffffffffffffff; static const limb bottom58bits = 0x3ffffffffffffff; -/* bin66_to_felem takes a little-endian byte array and converts it into felem - * form. This assumes that the CPU is little-endian. */ +/* + * bin66_to_felem takes a little-endian byte array and converts it into felem + * form. This assumes that the CPU is little-endian. + */ static void bin66_to_felem(felem out, const u8 in[66]) - { - out[0] = (*((limb*) &in[0])) & bottom58bits; - out[1] = (*((limb*) &in[7]) >> 2) & bottom58bits; - out[2] = (*((limb*) &in[14]) >> 4) & bottom58bits; - out[3] = (*((limb*) &in[21]) >> 6) & bottom58bits; - out[4] = (*((limb*) &in[29])) & bottom58bits; - out[5] = (*((limb*) &in[36]) >> 2) & bottom58bits; - out[6] = (*((limb*) &in[43]) >> 4) & bottom58bits; - out[7] = (*((limb*) &in[50]) >> 6) & bottom58bits; - out[8] = (*((limb*) &in[58])) & bottom57bits; - } - -/* felem_to_bin66 takes an felem and serialises into a little endian, 66 byte - * array. This assumes that the CPU is little-endian. */ +{ + out[0] = (*((limb *) & in[0])) & bottom58bits; + out[1] = (*((limb *) & in[7]) >> 2) & bottom58bits; + out[2] = (*((limb *) & in[14]) >> 4) & bottom58bits; + out[3] = (*((limb *) & in[21]) >> 6) & bottom58bits; + out[4] = (*((limb *) & in[29])) & bottom58bits; + out[5] = (*((limb *) & in[36]) >> 2) & bottom58bits; + out[6] = (*((limb *) & in[43]) >> 4) & bottom58bits; + out[7] = (*((limb *) & in[50]) >> 6) & bottom58bits; + out[8] = (*((limb *) & in[58])) & bottom57bits; +} + +/* + * felem_to_bin66 takes an felem and serialises into a little endian, 66 byte + * array. This assumes that the CPU is little-endian. + */ static void felem_to_bin66(u8 out[66], const felem in) - { - memset(out, 0, 66); - (*((limb*) &out[0])) = in[0]; - (*((limb*) &out[7])) |= in[1] << 2; - (*((limb*) &out[14])) |= in[2] << 4; - (*((limb*) &out[21])) |= in[3] << 6; - (*((limb*) &out[29])) = in[4]; - (*((limb*) &out[36])) |= in[5] << 2; - (*((limb*) &out[43])) |= in[6] << 4; - (*((limb*) &out[50])) |= in[7] << 6; - (*((limb*) &out[58])) = in[8]; - } +{ + memset(out, 0, 66); + (*((limb *) & out[0])) = in[0]; + (*((limb *) & out[7])) |= in[1] << 2; + (*((limb *) & out[14])) |= in[2] << 4; + (*((limb *) & out[21])) |= in[3] << 6; + (*((limb *) & out[29])) = in[4]; + (*((limb *) & out[36])) |= in[5] << 2; + (*((limb *) & out[43])) |= in[6] << 4; + (*((limb *) & out[50])) |= in[7] << 6; + (*((limb *) & out[58])) = in[8]; +} /* To preserve endianness when using BN_bn2bin and BN_bin2bn */ static void flip_endian(u8 *out, const u8 *in, unsigned len) - { - unsigned i; - for (i = 0; i < len; ++i) - out[i] = in[len-1-i]; - } +{ + unsigned i; + for (i = 0; i < len; ++i) + out[i] = in[len - 1 - i]; +} /* BN_to_felem converts an OpenSSL BIGNUM into an felem */ static int BN_to_felem(felem out, const BIGNUM *bn) - { - felem_bytearray b_in; - felem_bytearray b_out; - unsigned num_bytes; - - /* BN_bn2bin eats leading zeroes */ - memset(b_out, 0, sizeof b_out); - num_bytes = BN_num_bytes(bn); - if (num_bytes > sizeof b_out) - { - ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); - return 0; - } - if (BN_is_negative(bn)) - { - ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); - return 0; - } - num_bytes = BN_bn2bin(bn, b_in); - flip_endian(b_out, b_in, num_bytes); - bin66_to_felem(out, b_out); - return 1; - } +{ + felem_bytearray b_in; + felem_bytearray b_out; + unsigned num_bytes; + + /* BN_bn2bin eats leading zeroes */ + memset(b_out, 0, sizeof b_out); + num_bytes = BN_num_bytes(bn); + if (num_bytes > sizeof b_out) { + ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); + return 0; + } + if (BN_is_negative(bn)) { + ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); + return 0; + } + num_bytes = BN_bn2bin(bn, b_in); + flip_endian(b_out, b_in, num_bytes); + bin66_to_felem(out, b_out); + return 1; +} /* felem_to_BN converts an felem into an OpenSSL BIGNUM */ static BIGNUM *felem_to_BN(BIGNUM *out, const felem in) - { - felem_bytearray b_in, b_out; - felem_to_bin66(b_in, in); - flip_endian(b_out, b_in, sizeof b_out); - return BN_bin2bn(b_out, sizeof b_out, out); - } - +{ + felem_bytearray b_in, b_out; + felem_to_bin66(b_in, in); + flip_endian(b_out, b_in, sizeof b_out); + return BN_bin2bn(b_out, sizeof b_out, out); +} -/* Field operations - * ---------------- */ +/*- + * Field operations + * ---------------- + */ static void felem_one(felem out) - { - out[0] = 1; - out[1] = 0; - out[2] = 0; - out[3] = 0; - out[4] = 0; - out[5] = 0; - out[6] = 0; - out[7] = 0; - out[8] = 0; - } +{ + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 0; + out[5] = 0; + out[6] = 0; + out[7] = 0; + out[8] = 0; +} static void felem_assign(felem out, const felem in) - { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; - out[4] = in[4]; - out[5] = in[5]; - out[6] = in[6]; - out[7] = in[7]; - out[8] = in[8]; - } +{ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; + out[4] = in[4]; + out[5] = in[5]; + out[6] = in[6]; + out[7] = in[7]; + out[8] = in[8]; +} /* felem_sum64 sets out = out + in. */ static void felem_sum64(felem out, const felem in) - { - out[0] += in[0]; - out[1] += in[1]; - out[2] += in[2]; - out[3] += in[3]; - out[4] += in[4]; - out[5] += in[5]; - out[6] += in[6]; - out[7] += in[7]; - out[8] += in[8]; - } +{ + out[0] += in[0]; + out[1] += in[1]; + out[2] += in[2]; + out[3] += in[3]; + out[4] += in[4]; + out[5] += in[5]; + out[6] += in[6]; + out[7] += in[7]; + out[8] += in[8]; +} /* felem_scalar sets out = in * scalar */ static void felem_scalar(felem out, const felem in, limb scalar) - { - out[0] = in[0] * scalar; - out[1] = in[1] * scalar; - out[2] = in[2] * scalar; - out[3] = in[3] * scalar; - out[4] = in[4] * scalar; - out[5] = in[5] * scalar; - out[6] = in[6] * scalar; - out[7] = in[7] * scalar; - out[8] = in[8] * scalar; - } +{ + out[0] = in[0] * scalar; + out[1] = in[1] * scalar; + out[2] = in[2] * scalar; + out[3] = in[3] * scalar; + out[4] = in[4] * scalar; + out[5] = in[5] * scalar; + out[6] = in[6] * scalar; + out[7] = in[7] * scalar; + out[8] = in[8] * scalar; +} /* felem_scalar64 sets out = out * scalar */ static void felem_scalar64(felem out, limb scalar) - { - out[0] *= scalar; - out[1] *= scalar; - out[2] *= scalar; - out[3] *= scalar; - out[4] *= scalar; - out[5] *= scalar; - out[6] *= scalar; - out[7] *= scalar; - out[8] *= scalar; - } +{ + out[0] *= scalar; + out[1] *= scalar; + out[2] *= scalar; + out[3] *= scalar; + out[4] *= scalar; + out[5] *= scalar; + out[6] *= scalar; + out[7] *= scalar; + out[8] *= scalar; +} /* felem_scalar128 sets out = out * scalar */ static void felem_scalar128(largefelem out, limb scalar) - { - out[0] *= scalar; - out[1] *= scalar; - out[2] *= scalar; - out[3] *= scalar; - out[4] *= scalar; - out[5] *= scalar; - out[6] *= scalar; - out[7] *= scalar; - out[8] *= scalar; - } - -/* felem_neg sets |out| to |-in| +{ + out[0] *= scalar; + out[1] *= scalar; + out[2] *= scalar; + out[3] *= scalar; + out[4] *= scalar; + out[5] *= scalar; + out[6] *= scalar; + out[7] *= scalar; + out[8] *= scalar; +} + +/*- + * felem_neg sets |out| to |-in| * On entry: * in[i] < 2^59 + 2^14 * On exit: * out[i] < 2^62 */ static void felem_neg(felem out, const felem in) - { - /* In order to prevent underflow, we subtract from 0 mod p. */ - static const limb two62m3 = (((limb)1) << 62) - (((limb)1) << 5); - static const limb two62m2 = (((limb)1) << 62) - (((limb)1) << 4); - - out[0] = two62m3 - in[0]; - out[1] = two62m2 - in[1]; - out[2] = two62m2 - in[2]; - out[3] = two62m2 - in[3]; - out[4] = two62m2 - in[4]; - out[5] = two62m2 - in[5]; - out[6] = two62m2 - in[6]; - out[7] = two62m2 - in[7]; - out[8] = two62m2 - in[8]; - } - -/* felem_diff64 subtracts |in| from |out| +{ + /* In order to prevent underflow, we subtract from 0 mod p. */ + static const limb two62m3 = (((limb) 1) << 62) - (((limb) 1) << 5); + static const limb two62m2 = (((limb) 1) << 62) - (((limb) 1) << 4); + + out[0] = two62m3 - in[0]; + out[1] = two62m2 - in[1]; + out[2] = two62m2 - in[2]; + out[3] = two62m2 - in[3]; + out[4] = two62m2 - in[4]; + out[5] = two62m2 - in[5]; + out[6] = two62m2 - in[6]; + out[7] = two62m2 - in[7]; + out[8] = two62m2 - in[8]; +} + +/*- + * felem_diff64 subtracts |in| from |out| * On entry: * in[i] < 2^59 + 2^14 * On exit: * out[i] < out[i] + 2^62 */ static void felem_diff64(felem out, const felem in) - { - /* In order to prevent underflow, we add 0 mod p before subtracting. */ - static const limb two62m3 = (((limb)1) << 62) - (((limb)1) << 5); - static const limb two62m2 = (((limb)1) << 62) - (((limb)1) << 4); - - out[0] += two62m3 - in[0]; - out[1] += two62m2 - in[1]; - out[2] += two62m2 - in[2]; - out[3] += two62m2 - in[3]; - out[4] += two62m2 - in[4]; - out[5] += two62m2 - in[5]; - out[6] += two62m2 - in[6]; - out[7] += two62m2 - in[7]; - out[8] += two62m2 - in[8]; - } - -/* felem_diff_128_64 subtracts |in| from |out| +{ + /* + * In order to prevent underflow, we add 0 mod p before subtracting. + */ + static const limb two62m3 = (((limb) 1) << 62) - (((limb) 1) << 5); + static const limb two62m2 = (((limb) 1) << 62) - (((limb) 1) << 4); + + out[0] += two62m3 - in[0]; + out[1] += two62m2 - in[1]; + out[2] += two62m2 - in[2]; + out[3] += two62m2 - in[3]; + out[4] += two62m2 - in[4]; + out[5] += two62m2 - in[5]; + out[6] += two62m2 - in[6]; + out[7] += two62m2 - in[7]; + out[8] += two62m2 - in[8]; +} + +/*- + * felem_diff_128_64 subtracts |in| from |out| * On entry: * in[i] < 2^62 + 2^17 * On exit: * out[i] < out[i] + 2^63 */ static void felem_diff_128_64(largefelem out, const felem in) - { - /* In order to prevent underflow, we add 0 mod p before subtracting. */ - static const limb two63m6 = (((limb)1) << 62) - (((limb)1) << 5); - static const limb two63m5 = (((limb)1) << 62) - (((limb)1) << 4); - - out[0] += two63m6 - in[0]; - out[1] += two63m5 - in[1]; - out[2] += two63m5 - in[2]; - out[3] += two63m5 - in[3]; - out[4] += two63m5 - in[4]; - out[5] += two63m5 - in[5]; - out[6] += two63m5 - in[6]; - out[7] += two63m5 - in[7]; - out[8] += two63m5 - in[8]; - } - -/* felem_diff_128_64 subtracts |in| from |out| +{ + /* + * In order to prevent underflow, we add 0 mod p before subtracting. + */ + static const limb two63m6 = (((limb) 1) << 62) - (((limb) 1) << 5); + static const limb two63m5 = (((limb) 1) << 62) - (((limb) 1) << 4); + + out[0] += two63m6 - in[0]; + out[1] += two63m5 - in[1]; + out[2] += two63m5 - in[2]; + out[3] += two63m5 - in[3]; + out[4] += two63m5 - in[4]; + out[5] += two63m5 - in[5]; + out[6] += two63m5 - in[6]; + out[7] += two63m5 - in[7]; + out[8] += two63m5 - in[8]; +} + +/*- + * felem_diff_128_64 subtracts |in| from |out| * On entry: * in[i] < 2^126 * On exit: * out[i] < out[i] + 2^127 - 2^69 */ static void felem_diff128(largefelem out, const largefelem in) - { - /* In order to prevent underflow, we add 0 mod p before subtracting. */ - static const uint128_t two127m70 = (((uint128_t)1) << 127) - (((uint128_t)1) << 70); - static const uint128_t two127m69 = (((uint128_t)1) << 127) - (((uint128_t)1) << 69); - - out[0] += (two127m70 - in[0]); - out[1] += (two127m69 - in[1]); - out[2] += (two127m69 - in[2]); - out[3] += (two127m69 - in[3]); - out[4] += (two127m69 - in[4]); - out[5] += (two127m69 - in[5]); - out[6] += (two127m69 - in[6]); - out[7] += (two127m69 - in[7]); - out[8] += (two127m69 - in[8]); - } - -/* felem_square sets |out| = |in|^2 +{ + /* + * In order to prevent underflow, we add 0 mod p before subtracting. + */ + static const uint128_t two127m70 = + (((uint128_t) 1) << 127) - (((uint128_t) 1) << 70); + static const uint128_t two127m69 = + (((uint128_t) 1) << 127) - (((uint128_t) 1) << 69); + + out[0] += (two127m70 - in[0]); + out[1] += (two127m69 - in[1]); + out[2] += (two127m69 - in[2]); + out[3] += (two127m69 - in[3]); + out[4] += (two127m69 - in[4]); + out[5] += (two127m69 - in[5]); + out[6] += (two127m69 - in[6]); + out[7] += (two127m69 - in[7]); + out[8] += (two127m69 - in[8]); +} + +/*- + * felem_square sets |out| = |in|^2 * On entry: * in[i] < 2^62 * On exit: * out[i] < 17 * max(in[i]) * max(in[i]) */ static void felem_square(largefelem out, const felem in) - { - felem inx2, inx4; - felem_scalar(inx2, in, 2); - felem_scalar(inx4, in, 4); - - /* We have many cases were we want to do - * in[x] * in[y] + - * in[y] * in[x] - * This is obviously just - * 2 * in[x] * in[y] - * However, rather than do the doubling on the 128 bit result, we - * double one of the inputs to the multiplication by reading from - * |inx2| */ - - out[0] = ((uint128_t) in[0]) * in[0]; - out[1] = ((uint128_t) in[0]) * inx2[1]; - out[2] = ((uint128_t) in[0]) * inx2[2] + - ((uint128_t) in[1]) * in[1]; - out[3] = ((uint128_t) in[0]) * inx2[3] + - ((uint128_t) in[1]) * inx2[2]; - out[4] = ((uint128_t) in[0]) * inx2[4] + - ((uint128_t) in[1]) * inx2[3] + - ((uint128_t) in[2]) * in[2]; - out[5] = ((uint128_t) in[0]) * inx2[5] + - ((uint128_t) in[1]) * inx2[4] + - ((uint128_t) in[2]) * inx2[3]; - out[6] = ((uint128_t) in[0]) * inx2[6] + - ((uint128_t) in[1]) * inx2[5] + - ((uint128_t) in[2]) * inx2[4] + - ((uint128_t) in[3]) * in[3]; - out[7] = ((uint128_t) in[0]) * inx2[7] + - ((uint128_t) in[1]) * inx2[6] + - ((uint128_t) in[2]) * inx2[5] + - ((uint128_t) in[3]) * inx2[4]; - out[8] = ((uint128_t) in[0]) * inx2[8] + - ((uint128_t) in[1]) * inx2[7] + - ((uint128_t) in[2]) * inx2[6] + - ((uint128_t) in[3]) * inx2[5] + - ((uint128_t) in[4]) * in[4]; - - /* The remaining limbs fall above 2^521, with the first falling at - * 2^522. They correspond to locations one bit up from the limbs - * produced above so we would have to multiply by two to align them. - * Again, rather than operate on the 128-bit result, we double one of - * the inputs to the multiplication. If we want to double for both this - * reason, and the reason above, then we end up multiplying by four. */ - - /* 9 */ - out[0] += ((uint128_t) in[1]) * inx4[8] + - ((uint128_t) in[2]) * inx4[7] + - ((uint128_t) in[3]) * inx4[6] + - ((uint128_t) in[4]) * inx4[5]; - - /* 10 */ - out[1] += ((uint128_t) in[2]) * inx4[8] + - ((uint128_t) in[3]) * inx4[7] + - ((uint128_t) in[4]) * inx4[6] + - ((uint128_t) in[5]) * inx2[5]; - - /* 11 */ - out[2] += ((uint128_t) in[3]) * inx4[8] + - ((uint128_t) in[4]) * inx4[7] + - ((uint128_t) in[5]) * inx4[6]; - - /* 12 */ - out[3] += ((uint128_t) in[4]) * inx4[8] + - ((uint128_t) in[5]) * inx4[7] + - ((uint128_t) in[6]) * inx2[6]; - - /* 13 */ - out[4] += ((uint128_t) in[5]) * inx4[8] + - ((uint128_t) in[6]) * inx4[7]; - - /* 14 */ - out[5] += ((uint128_t) in[6]) * inx4[8] + - ((uint128_t) in[7]) * inx2[7]; - - /* 15 */ - out[6] += ((uint128_t) in[7]) * inx4[8]; - - /* 16 */ - out[7] += ((uint128_t) in[8]) * inx2[8]; - } - -/* felem_mul sets |out| = |in1| * |in2| +{ + felem inx2, inx4; + felem_scalar(inx2, in, 2); + felem_scalar(inx4, in, 4); + + /*- + * We have many cases were we want to do + * in[x] * in[y] + + * in[y] * in[x] + * This is obviously just + * 2 * in[x] * in[y] + * However, rather than do the doubling on the 128 bit result, we + * double one of the inputs to the multiplication by reading from + * |inx2| + */ + + out[0] = ((uint128_t) in[0]) * in[0]; + out[1] = ((uint128_t) in[0]) * inx2[1]; + out[2] = ((uint128_t) in[0]) * inx2[2] + ((uint128_t) in[1]) * in[1]; + out[3] = ((uint128_t) in[0]) * inx2[3] + ((uint128_t) in[1]) * inx2[2]; + out[4] = ((uint128_t) in[0]) * inx2[4] + + ((uint128_t) in[1]) * inx2[3] + ((uint128_t) in[2]) * in[2]; + out[5] = ((uint128_t) in[0]) * inx2[5] + + ((uint128_t) in[1]) * inx2[4] + ((uint128_t) in[2]) * inx2[3]; + out[6] = ((uint128_t) in[0]) * inx2[6] + + ((uint128_t) in[1]) * inx2[5] + + ((uint128_t) in[2]) * inx2[4] + ((uint128_t) in[3]) * in[3]; + out[7] = ((uint128_t) in[0]) * inx2[7] + + ((uint128_t) in[1]) * inx2[6] + + ((uint128_t) in[2]) * inx2[5] + ((uint128_t) in[3]) * inx2[4]; + out[8] = ((uint128_t) in[0]) * inx2[8] + + ((uint128_t) in[1]) * inx2[7] + + ((uint128_t) in[2]) * inx2[6] + + ((uint128_t) in[3]) * inx2[5] + ((uint128_t) in[4]) * in[4]; + + /* + * The remaining limbs fall above 2^521, with the first falling at 2^522. + * They correspond to locations one bit up from the limbs produced above + * so we would have to multiply by two to align them. Again, rather than + * operate on the 128-bit result, we double one of the inputs to the + * multiplication. If we want to double for both this reason, and the + * reason above, then we end up multiplying by four. + */ + + /* 9 */ + out[0] += ((uint128_t) in[1]) * inx4[8] + + ((uint128_t) in[2]) * inx4[7] + + ((uint128_t) in[3]) * inx4[6] + ((uint128_t) in[4]) * inx4[5]; + + /* 10 */ + out[1] += ((uint128_t) in[2]) * inx4[8] + + ((uint128_t) in[3]) * inx4[7] + + ((uint128_t) in[4]) * inx4[6] + ((uint128_t) in[5]) * inx2[5]; + + /* 11 */ + out[2] += ((uint128_t) in[3]) * inx4[8] + + ((uint128_t) in[4]) * inx4[7] + ((uint128_t) in[5]) * inx4[6]; + + /* 12 */ + out[3] += ((uint128_t) in[4]) * inx4[8] + + ((uint128_t) in[5]) * inx4[7] + ((uint128_t) in[6]) * inx2[6]; + + /* 13 */ + out[4] += ((uint128_t) in[5]) * inx4[8] + ((uint128_t) in[6]) * inx4[7]; + + /* 14 */ + out[5] += ((uint128_t) in[6]) * inx4[8] + ((uint128_t) in[7]) * inx2[7]; + + /* 15 */ + out[6] += ((uint128_t) in[7]) * inx4[8]; + + /* 16 */ + out[7] += ((uint128_t) in[8]) * inx2[8]; +} + +/*- + * felem_mul sets |out| = |in1| * |in2| * On entry: * in1[i] < 2^64 * in2[i] < 2^63 @@ -482,202 +493,197 @@ static void felem_square(largefelem out, const felem in) * out[i] < 17 * max(in1[i]) * max(in2[i]) */ static void felem_mul(largefelem out, const felem in1, const felem in2) - { - felem in2x2; - felem_scalar(in2x2, in2, 2); - - out[0] = ((uint128_t) in1[0]) * in2[0]; - - out[1] = ((uint128_t) in1[0]) * in2[1] + - ((uint128_t) in1[1]) * in2[0]; - - out[2] = ((uint128_t) in1[0]) * in2[2] + - ((uint128_t) in1[1]) * in2[1] + - ((uint128_t) in1[2]) * in2[0]; - - out[3] = ((uint128_t) in1[0]) * in2[3] + - ((uint128_t) in1[1]) * in2[2] + - ((uint128_t) in1[2]) * in2[1] + - ((uint128_t) in1[3]) * in2[0]; - - out[4] = ((uint128_t) in1[0]) * in2[4] + - ((uint128_t) in1[1]) * in2[3] + - ((uint128_t) in1[2]) * in2[2] + - ((uint128_t) in1[3]) * in2[1] + - ((uint128_t) in1[4]) * in2[0]; - - out[5] = ((uint128_t) in1[0]) * in2[5] + - ((uint128_t) in1[1]) * in2[4] + - ((uint128_t) in1[2]) * in2[3] + - ((uint128_t) in1[3]) * in2[2] + - ((uint128_t) in1[4]) * in2[1] + - ((uint128_t) in1[5]) * in2[0]; - - out[6] = ((uint128_t) in1[0]) * in2[6] + - ((uint128_t) in1[1]) * in2[5] + - ((uint128_t) in1[2]) * in2[4] + - ((uint128_t) in1[3]) * in2[3] + - ((uint128_t) in1[4]) * in2[2] + - ((uint128_t) in1[5]) * in2[1] + - ((uint128_t) in1[6]) * in2[0]; - - out[7] = ((uint128_t) in1[0]) * in2[7] + - ((uint128_t) in1[1]) * in2[6] + - ((uint128_t) in1[2]) * in2[5] + - ((uint128_t) in1[3]) * in2[4] + - ((uint128_t) in1[4]) * in2[3] + - ((uint128_t) in1[5]) * in2[2] + - ((uint128_t) in1[6]) * in2[1] + - ((uint128_t) in1[7]) * in2[0]; - - out[8] = ((uint128_t) in1[0]) * in2[8] + - ((uint128_t) in1[1]) * in2[7] + - ((uint128_t) in1[2]) * in2[6] + - ((uint128_t) in1[3]) * in2[5] + - ((uint128_t) in1[4]) * in2[4] + - ((uint128_t) in1[5]) * in2[3] + - ((uint128_t) in1[6]) * in2[2] + - ((uint128_t) in1[7]) * in2[1] + - ((uint128_t) in1[8]) * in2[0]; - - /* See comment in felem_square about the use of in2x2 here */ - - out[0] += ((uint128_t) in1[1]) * in2x2[8] + - ((uint128_t) in1[2]) * in2x2[7] + - ((uint128_t) in1[3]) * in2x2[6] + - ((uint128_t) in1[4]) * in2x2[5] + - ((uint128_t) in1[5]) * in2x2[4] + - ((uint128_t) in1[6]) * in2x2[3] + - ((uint128_t) in1[7]) * in2x2[2] + - ((uint128_t) in1[8]) * in2x2[1]; - - out[1] += ((uint128_t) in1[2]) * in2x2[8] + - ((uint128_t) in1[3]) * in2x2[7] + - ((uint128_t) in1[4]) * in2x2[6] + - ((uint128_t) in1[5]) * in2x2[5] + - ((uint128_t) in1[6]) * in2x2[4] + - ((uint128_t) in1[7]) * in2x2[3] + - ((uint128_t) in1[8]) * in2x2[2]; - - out[2] += ((uint128_t) in1[3]) * in2x2[8] + - ((uint128_t) in1[4]) * in2x2[7] + - ((uint128_t) in1[5]) * in2x2[6] + - ((uint128_t) in1[6]) * in2x2[5] + - ((uint128_t) in1[7]) * in2x2[4] + - ((uint128_t) in1[8]) * in2x2[3]; - - out[3] += ((uint128_t) in1[4]) * in2x2[8] + - ((uint128_t) in1[5]) * in2x2[7] + - ((uint128_t) in1[6]) * in2x2[6] + - ((uint128_t) in1[7]) * in2x2[5] + - ((uint128_t) in1[8]) * in2x2[4]; - - out[4] += ((uint128_t) in1[5]) * in2x2[8] + - ((uint128_t) in1[6]) * in2x2[7] + - ((uint128_t) in1[7]) * in2x2[6] + - ((uint128_t) in1[8]) * in2x2[5]; - - out[5] += ((uint128_t) in1[6]) * in2x2[8] + - ((uint128_t) in1[7]) * in2x2[7] + - ((uint128_t) in1[8]) * in2x2[6]; - - out[6] += ((uint128_t) in1[7]) * in2x2[8] + - ((uint128_t) in1[8]) * in2x2[7]; - - out[7] += ((uint128_t) in1[8]) * in2x2[8]; - } +{ + felem in2x2; + felem_scalar(in2x2, in2, 2); + + out[0] = ((uint128_t) in1[0]) * in2[0]; + + out[1] = ((uint128_t) in1[0]) * in2[1] + ((uint128_t) in1[1]) * in2[0]; + + out[2] = ((uint128_t) in1[0]) * in2[2] + + ((uint128_t) in1[1]) * in2[1] + ((uint128_t) in1[2]) * in2[0]; + + out[3] = ((uint128_t) in1[0]) * in2[3] + + ((uint128_t) in1[1]) * in2[2] + + ((uint128_t) in1[2]) * in2[1] + ((uint128_t) in1[3]) * in2[0]; + + out[4] = ((uint128_t) in1[0]) * in2[4] + + ((uint128_t) in1[1]) * in2[3] + + ((uint128_t) in1[2]) * in2[2] + + ((uint128_t) in1[3]) * in2[1] + ((uint128_t) in1[4]) * in2[0]; + + out[5] = ((uint128_t) in1[0]) * in2[5] + + ((uint128_t) in1[1]) * in2[4] + + ((uint128_t) in1[2]) * in2[3] + + ((uint128_t) in1[3]) * in2[2] + + ((uint128_t) in1[4]) * in2[1] + ((uint128_t) in1[5]) * in2[0]; + + out[6] = ((uint128_t) in1[0]) * in2[6] + + ((uint128_t) in1[1]) * in2[5] + + ((uint128_t) in1[2]) * in2[4] + + ((uint128_t) in1[3]) * in2[3] + + ((uint128_t) in1[4]) * in2[2] + + ((uint128_t) in1[5]) * in2[1] + ((uint128_t) in1[6]) * in2[0]; + + out[7] = ((uint128_t) in1[0]) * in2[7] + + ((uint128_t) in1[1]) * in2[6] + + ((uint128_t) in1[2]) * in2[5] + + ((uint128_t) in1[3]) * in2[4] + + ((uint128_t) in1[4]) * in2[3] + + ((uint128_t) in1[5]) * in2[2] + + ((uint128_t) in1[6]) * in2[1] + ((uint128_t) in1[7]) * in2[0]; + + out[8] = ((uint128_t) in1[0]) * in2[8] + + ((uint128_t) in1[1]) * in2[7] + + ((uint128_t) in1[2]) * in2[6] + + ((uint128_t) in1[3]) * in2[5] + + ((uint128_t) in1[4]) * in2[4] + + ((uint128_t) in1[5]) * in2[3] + + ((uint128_t) in1[6]) * in2[2] + + ((uint128_t) in1[7]) * in2[1] + ((uint128_t) in1[8]) * in2[0]; + + /* See comment in felem_square about the use of in2x2 here */ + + out[0] += ((uint128_t) in1[1]) * in2x2[8] + + ((uint128_t) in1[2]) * in2x2[7] + + ((uint128_t) in1[3]) * in2x2[6] + + ((uint128_t) in1[4]) * in2x2[5] + + ((uint128_t) in1[5]) * in2x2[4] + + ((uint128_t) in1[6]) * in2x2[3] + + ((uint128_t) in1[7]) * in2x2[2] + ((uint128_t) in1[8]) * in2x2[1]; + + out[1] += ((uint128_t) in1[2]) * in2x2[8] + + ((uint128_t) in1[3]) * in2x2[7] + + ((uint128_t) in1[4]) * in2x2[6] + + ((uint128_t) in1[5]) * in2x2[5] + + ((uint128_t) in1[6]) * in2x2[4] + + ((uint128_t) in1[7]) * in2x2[3] + ((uint128_t) in1[8]) * in2x2[2]; + + out[2] += ((uint128_t) in1[3]) * in2x2[8] + + ((uint128_t) in1[4]) * in2x2[7] + + ((uint128_t) in1[5]) * in2x2[6] + + ((uint128_t) in1[6]) * in2x2[5] + + ((uint128_t) in1[7]) * in2x2[4] + ((uint128_t) in1[8]) * in2x2[3]; + + out[3] += ((uint128_t) in1[4]) * in2x2[8] + + ((uint128_t) in1[5]) * in2x2[7] + + ((uint128_t) in1[6]) * in2x2[6] + + ((uint128_t) in1[7]) * in2x2[5] + ((uint128_t) in1[8]) * in2x2[4]; + + out[4] += ((uint128_t) in1[5]) * in2x2[8] + + ((uint128_t) in1[6]) * in2x2[7] + + ((uint128_t) in1[7]) * in2x2[6] + ((uint128_t) in1[8]) * in2x2[5]; + + out[5] += ((uint128_t) in1[6]) * in2x2[8] + + ((uint128_t) in1[7]) * in2x2[7] + ((uint128_t) in1[8]) * in2x2[6]; + + out[6] += ((uint128_t) in1[7]) * in2x2[8] + + ((uint128_t) in1[8]) * in2x2[7]; + + out[7] += ((uint128_t) in1[8]) * in2x2[8]; +} static const limb bottom52bits = 0xfffffffffffff; -/* felem_reduce converts a largefelem to an felem. +/*- + * felem_reduce converts a largefelem to an felem. * On entry: * in[i] < 2^128 * On exit: * out[i] < 2^59 + 2^14 */ static void felem_reduce(felem out, const largefelem in) - { - u64 overflow1, overflow2; - - out[0] = ((limb) in[0]) & bottom58bits; - out[1] = ((limb) in[1]) & bottom58bits; - out[2] = ((limb) in[2]) & bottom58bits; - out[3] = ((limb) in[3]) & bottom58bits; - out[4] = ((limb) in[4]) & bottom58bits; - out[5] = ((limb) in[5]) & bottom58bits; - out[6] = ((limb) in[6]) & bottom58bits; - out[7] = ((limb) in[7]) & bottom58bits; - out[8] = ((limb) in[8]) & bottom58bits; - - /* out[i] < 2^58 */ - - out[1] += ((limb) in[0]) >> 58; - out[1] += (((limb) (in[0] >> 64)) & bottom52bits) << 6; - /* out[1] < 2^58 + 2^6 + 2^58 - * = 2^59 + 2^6 */ - out[2] += ((limb) (in[0] >> 64)) >> 52; - - out[2] += ((limb) in[1]) >> 58; - out[2] += (((limb) (in[1] >> 64)) & bottom52bits) << 6; - out[3] += ((limb) (in[1] >> 64)) >> 52; - - out[3] += ((limb) in[2]) >> 58; - out[3] += (((limb) (in[2] >> 64)) & bottom52bits) << 6; - out[4] += ((limb) (in[2] >> 64)) >> 52; - - out[4] += ((limb) in[3]) >> 58; - out[4] += (((limb) (in[3] >> 64)) & bottom52bits) << 6; - out[5] += ((limb) (in[3] >> 64)) >> 52; - - out[5] += ((limb) in[4]) >> 58; - out[5] += (((limb) (in[4] >> 64)) & bottom52bits) << 6; - out[6] += ((limb) (in[4] >> 64)) >> 52; - - out[6] += ((limb) in[5]) >> 58; - out[6] += (((limb) (in[5] >> 64)) & bottom52bits) << 6; - out[7] += ((limb) (in[5] >> 64)) >> 52; - - out[7] += ((limb) in[6]) >> 58; - out[7] += (((limb) (in[6] >> 64)) & bottom52bits) << 6; - out[8] += ((limb) (in[6] >> 64)) >> 52; - - out[8] += ((limb) in[7]) >> 58; - out[8] += (((limb) (in[7] >> 64)) & bottom52bits) << 6; - /* out[x > 1] < 2^58 + 2^6 + 2^58 + 2^12 - * < 2^59 + 2^13 */ - overflow1 = ((limb) (in[7] >> 64)) >> 52; - - overflow1 += ((limb) in[8]) >> 58; - overflow1 += (((limb) (in[8] >> 64)) & bottom52bits) << 6; - overflow2 = ((limb) (in[8] >> 64)) >> 52; - - overflow1 <<= 1; /* overflow1 < 2^13 + 2^7 + 2^59 */ - overflow2 <<= 1; /* overflow2 < 2^13 */ - - out[0] += overflow1; /* out[0] < 2^60 */ - out[1] += overflow2; /* out[1] < 2^59 + 2^6 + 2^13 */ - - out[1] += out[0] >> 58; out[0] &= bottom58bits; - /* out[0] < 2^58 - * out[1] < 2^59 + 2^6 + 2^13 + 2^2 - * < 2^59 + 2^14 */ - } +{ + u64 overflow1, overflow2; + + out[0] = ((limb) in[0]) & bottom58bits; + out[1] = ((limb) in[1]) & bottom58bits; + out[2] = ((limb) in[2]) & bottom58bits; + out[3] = ((limb) in[3]) & bottom58bits; + out[4] = ((limb) in[4]) & bottom58bits; + out[5] = ((limb) in[5]) & bottom58bits; + out[6] = ((limb) in[6]) & bottom58bits; + out[7] = ((limb) in[7]) & bottom58bits; + out[8] = ((limb) in[8]) & bottom58bits; + + /* out[i] < 2^58 */ + + out[1] += ((limb) in[0]) >> 58; + out[1] += (((limb) (in[0] >> 64)) & bottom52bits) << 6; + /*- + * out[1] < 2^58 + 2^6 + 2^58 + * = 2^59 + 2^6 + */ + out[2] += ((limb) (in[0] >> 64)) >> 52; + + out[2] += ((limb) in[1]) >> 58; + out[2] += (((limb) (in[1] >> 64)) & bottom52bits) << 6; + out[3] += ((limb) (in[1] >> 64)) >> 52; + + out[3] += ((limb) in[2]) >> 58; + out[3] += (((limb) (in[2] >> 64)) & bottom52bits) << 6; + out[4] += ((limb) (in[2] >> 64)) >> 52; + + out[4] += ((limb) in[3]) >> 58; + out[4] += (((limb) (in[3] >> 64)) & bottom52bits) << 6; + out[5] += ((limb) (in[3] >> 64)) >> 52; + + out[5] += ((limb) in[4]) >> 58; + out[5] += (((limb) (in[4] >> 64)) & bottom52bits) << 6; + out[6] += ((limb) (in[4] >> 64)) >> 52; + + out[6] += ((limb) in[5]) >> 58; + out[6] += (((limb) (in[5] >> 64)) & bottom52bits) << 6; + out[7] += ((limb) (in[5] >> 64)) >> 52; + + out[7] += ((limb) in[6]) >> 58; + out[7] += (((limb) (in[6] >> 64)) & bottom52bits) << 6; + out[8] += ((limb) (in[6] >> 64)) >> 52; + + out[8] += ((limb) in[7]) >> 58; + out[8] += (((limb) (in[7] >> 64)) & bottom52bits) << 6; + /*- + * out[x > 1] < 2^58 + 2^6 + 2^58 + 2^12 + * < 2^59 + 2^13 + */ + overflow1 = ((limb) (in[7] >> 64)) >> 52; + + overflow1 += ((limb) in[8]) >> 58; + overflow1 += (((limb) (in[8] >> 64)) & bottom52bits) << 6; + overflow2 = ((limb) (in[8] >> 64)) >> 52; + + overflow1 <<= 1; /* overflow1 < 2^13 + 2^7 + 2^59 */ + overflow2 <<= 1; /* overflow2 < 2^13 */ + + out[0] += overflow1; /* out[0] < 2^60 */ + out[1] += overflow2; /* out[1] < 2^59 + 2^6 + 2^13 */ + + out[1] += out[0] >> 58; + out[0] &= bottom58bits; + /*- + * out[0] < 2^58 + * out[1] < 2^59 + 2^6 + 2^13 + 2^2 + * < 2^59 + 2^14 + */ +} static void felem_square_reduce(felem out, const felem in) - { - largefelem tmp; - felem_square(tmp, in); - felem_reduce(out, tmp); - } +{ + largefelem tmp; + felem_square(tmp, in); + felem_reduce(out, tmp); +} static void felem_mul_reduce(felem out, const felem in1, const felem in2) - { - largefelem tmp; - felem_mul(tmp, in1, in2); - felem_reduce(out, tmp); - } +{ + largefelem tmp; + felem_mul(tmp, in1, in2); + felem_reduce(out, tmp); +} -/* felem_inv calculates |out| = |in|^{-1} +/*- + * felem_inv calculates |out| = |in|^{-1} * * Based on Fermat's Little Theorem: * a^p = a (mod p) @@ -685,259 +691,335 @@ static void felem_mul_reduce(felem out, const felem in1, const felem in2) * a^{p-2} = a^{-1} (mod p) */ static void felem_inv(felem out, const felem in) - { - felem ftmp, ftmp2, ftmp3, ftmp4; - largefelem tmp; - unsigned i; - - felem_square(tmp, in); felem_reduce(ftmp, tmp); /* 2^1 */ - felem_mul(tmp, in, ftmp); felem_reduce(ftmp, tmp); /* 2^2 - 2^0 */ - felem_assign(ftmp2, ftmp); - felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^3 - 2^1 */ - felem_mul(tmp, in, ftmp); felem_reduce(ftmp, tmp); /* 2^3 - 2^0 */ - felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^4 - 2^1 */ - - felem_square(tmp, ftmp2); felem_reduce(ftmp3, tmp); /* 2^3 - 2^1 */ - felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^4 - 2^2 */ - felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^4 - 2^0 */ - - felem_assign(ftmp2, ftmp3); - felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^5 - 2^1 */ - felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^6 - 2^2 */ - felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^7 - 2^3 */ - felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^8 - 2^4 */ - felem_assign(ftmp4, ftmp3); - felem_mul(tmp, ftmp3, ftmp); felem_reduce(ftmp4, tmp); /* 2^8 - 2^1 */ - felem_square(tmp, ftmp4); felem_reduce(ftmp4, tmp); /* 2^9 - 2^2 */ - felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^8 - 2^0 */ - felem_assign(ftmp2, ftmp3); - - for (i = 0; i < 8; i++) - { - felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^16 - 2^8 */ - } - felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^16 - 2^0 */ - felem_assign(ftmp2, ftmp3); - - for (i = 0; i < 16; i++) - { - felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^32 - 2^16 */ - } - felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^32 - 2^0 */ - felem_assign(ftmp2, ftmp3); - - for (i = 0; i < 32; i++) - { - felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^64 - 2^32 */ - } - felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^64 - 2^0 */ - felem_assign(ftmp2, ftmp3); - - for (i = 0; i < 64; i++) - { - felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^128 - 2^64 */ - } - felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^128 - 2^0 */ - felem_assign(ftmp2, ftmp3); - - for (i = 0; i < 128; i++) - { - felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^256 - 2^128 */ - } - felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^256 - 2^0 */ - felem_assign(ftmp2, ftmp3); - - for (i = 0; i < 256; i++) - { - felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^512 - 2^256 */ - } - felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^512 - 2^0 */ - - for (i = 0; i < 9; i++) - { - felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^521 - 2^9 */ - } - felem_mul(tmp, ftmp3, ftmp4); felem_reduce(ftmp3, tmp); /* 2^512 - 2^2 */ - felem_mul(tmp, ftmp3, in); felem_reduce(out, tmp); /* 2^512 - 3 */ +{ + felem ftmp, ftmp2, ftmp3, ftmp4; + largefelem tmp; + unsigned i; + + felem_square(tmp, in); + felem_reduce(ftmp, tmp); /* 2^1 */ + felem_mul(tmp, in, ftmp); + felem_reduce(ftmp, tmp); /* 2^2 - 2^0 */ + felem_assign(ftmp2, ftmp); + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^3 - 2^1 */ + felem_mul(tmp, in, ftmp); + felem_reduce(ftmp, tmp); /* 2^3 - 2^0 */ + felem_square(tmp, ftmp); + felem_reduce(ftmp, tmp); /* 2^4 - 2^1 */ + + felem_square(tmp, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^3 - 2^1 */ + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); /* 2^4 - 2^2 */ + felem_mul(tmp, ftmp3, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^4 - 2^0 */ + + felem_assign(ftmp2, ftmp3); + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); /* 2^5 - 2^1 */ + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); /* 2^6 - 2^2 */ + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); /* 2^7 - 2^3 */ + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); /* 2^8 - 2^4 */ + felem_assign(ftmp4, ftmp3); + felem_mul(tmp, ftmp3, ftmp); + felem_reduce(ftmp4, tmp); /* 2^8 - 2^1 */ + felem_square(tmp, ftmp4); + felem_reduce(ftmp4, tmp); /* 2^9 - 2^2 */ + felem_mul(tmp, ftmp3, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^8 - 2^0 */ + felem_assign(ftmp2, ftmp3); + + for (i = 0; i < 8; i++) { + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); /* 2^16 - 2^8 */ + } + felem_mul(tmp, ftmp3, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^16 - 2^0 */ + felem_assign(ftmp2, ftmp3); + + for (i = 0; i < 16; i++) { + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); /* 2^32 - 2^16 */ + } + felem_mul(tmp, ftmp3, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^32 - 2^0 */ + felem_assign(ftmp2, ftmp3); + + for (i = 0; i < 32; i++) { + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); /* 2^64 - 2^32 */ + } + felem_mul(tmp, ftmp3, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^64 - 2^0 */ + felem_assign(ftmp2, ftmp3); + + for (i = 0; i < 64; i++) { + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); /* 2^128 - 2^64 */ + } + felem_mul(tmp, ftmp3, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^128 - 2^0 */ + felem_assign(ftmp2, ftmp3); + + for (i = 0; i < 128; i++) { + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); /* 2^256 - 2^128 */ + } + felem_mul(tmp, ftmp3, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^256 - 2^0 */ + felem_assign(ftmp2, ftmp3); + + for (i = 0; i < 256; i++) { + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); /* 2^512 - 2^256 */ + } + felem_mul(tmp, ftmp3, ftmp2); + felem_reduce(ftmp3, tmp); /* 2^512 - 2^0 */ + + for (i = 0; i < 9; i++) { + felem_square(tmp, ftmp3); + felem_reduce(ftmp3, tmp); /* 2^521 - 2^9 */ + } + felem_mul(tmp, ftmp3, ftmp4); + felem_reduce(ftmp3, tmp); /* 2^512 - 2^2 */ + felem_mul(tmp, ftmp3, in); + felem_reduce(out, tmp); /* 2^512 - 3 */ } /* This is 2^521-1, expressed as an felem */ -static const felem kPrime = - { - 0x03ffffffffffffff, 0x03ffffffffffffff, 0x03ffffffffffffff, - 0x03ffffffffffffff, 0x03ffffffffffffff, 0x03ffffffffffffff, - 0x03ffffffffffffff, 0x03ffffffffffffff, 0x01ffffffffffffff - }; - -/* felem_is_zero returns a limb with all bits set if |in| == 0 (mod p) and 0 +static const felem kPrime = { + 0x03ffffffffffffff, 0x03ffffffffffffff, 0x03ffffffffffffff, + 0x03ffffffffffffff, 0x03ffffffffffffff, 0x03ffffffffffffff, + 0x03ffffffffffffff, 0x03ffffffffffffff, 0x01ffffffffffffff +}; + +/*- + * felem_is_zero returns a limb with all bits set if |in| == 0 (mod p) and 0 * otherwise. * On entry: * in[i] < 2^59 + 2^14 */ static limb felem_is_zero(const felem in) - { - felem ftmp; - limb is_zero, is_p; - felem_assign(ftmp, in); - - ftmp[0] += ftmp[8] >> 57; ftmp[8] &= bottom57bits; - /* ftmp[8] < 2^57 */ - ftmp[1] += ftmp[0] >> 58; ftmp[0] &= bottom58bits; - ftmp[2] += ftmp[1] >> 58; ftmp[1] &= bottom58bits; - ftmp[3] += ftmp[2] >> 58; ftmp[2] &= bottom58bits; - ftmp[4] += ftmp[3] >> 58; ftmp[3] &= bottom58bits; - ftmp[5] += ftmp[4] >> 58; ftmp[4] &= bottom58bits; - ftmp[6] += ftmp[5] >> 58; ftmp[5] &= bottom58bits; - ftmp[7] += ftmp[6] >> 58; ftmp[6] &= bottom58bits; - ftmp[8] += ftmp[7] >> 58; ftmp[7] &= bottom58bits; - /* ftmp[8] < 2^57 + 4 */ - - /* The ninth limb of 2*(2^521-1) is 0x03ffffffffffffff, which is - * greater than our bound for ftmp[8]. Therefore we only have to check - * if the zero is zero or 2^521-1. */ - - is_zero = 0; - is_zero |= ftmp[0]; - is_zero |= ftmp[1]; - is_zero |= ftmp[2]; - is_zero |= ftmp[3]; - is_zero |= ftmp[4]; - is_zero |= ftmp[5]; - is_zero |= ftmp[6]; - is_zero |= ftmp[7]; - is_zero |= ftmp[8]; - - is_zero--; - /* We know that ftmp[i] < 2^63, therefore the only way that the top bit - * can be set is if is_zero was 0 before the decrement. */ - is_zero = ((s64) is_zero) >> 63; - - is_p = ftmp[0] ^ kPrime[0]; - is_p |= ftmp[1] ^ kPrime[1]; - is_p |= ftmp[2] ^ kPrime[2]; - is_p |= ftmp[3] ^ kPrime[3]; - is_p |= ftmp[4] ^ kPrime[4]; - is_p |= ftmp[5] ^ kPrime[5]; - is_p |= ftmp[6] ^ kPrime[6]; - is_p |= ftmp[7] ^ kPrime[7]; - is_p |= ftmp[8] ^ kPrime[8]; - - is_p--; - is_p = ((s64) is_p) >> 63; - - is_zero |= is_p; - return is_zero; - } +{ + felem ftmp; + limb is_zero, is_p; + felem_assign(ftmp, in); + + ftmp[0] += ftmp[8] >> 57; + ftmp[8] &= bottom57bits; + /* ftmp[8] < 2^57 */ + ftmp[1] += ftmp[0] >> 58; + ftmp[0] &= bottom58bits; + ftmp[2] += ftmp[1] >> 58; + ftmp[1] &= bottom58bits; + ftmp[3] += ftmp[2] >> 58; + ftmp[2] &= bottom58bits; + ftmp[4] += ftmp[3] >> 58; + ftmp[3] &= bottom58bits; + ftmp[5] += ftmp[4] >> 58; + ftmp[4] &= bottom58bits; + ftmp[6] += ftmp[5] >> 58; + ftmp[5] &= bottom58bits; + ftmp[7] += ftmp[6] >> 58; + ftmp[6] &= bottom58bits; + ftmp[8] += ftmp[7] >> 58; + ftmp[7] &= bottom58bits; + /* ftmp[8] < 2^57 + 4 */ + + /* + * The ninth limb of 2*(2^521-1) is 0x03ffffffffffffff, which is greater + * than our bound for ftmp[8]. Therefore we only have to check if the + * zero is zero or 2^521-1. + */ + + is_zero = 0; + is_zero |= ftmp[0]; + is_zero |= ftmp[1]; + is_zero |= ftmp[2]; + is_zero |= ftmp[3]; + is_zero |= ftmp[4]; + is_zero |= ftmp[5]; + is_zero |= ftmp[6]; + is_zero |= ftmp[7]; + is_zero |= ftmp[8]; + + is_zero--; + /* + * We know that ftmp[i] < 2^63, therefore the only way that the top bit + * can be set is if is_zero was 0 before the decrement. + */ + is_zero = ((s64) is_zero) >> 63; + + is_p = ftmp[0] ^ kPrime[0]; + is_p |= ftmp[1] ^ kPrime[1]; + is_p |= ftmp[2] ^ kPrime[2]; + is_p |= ftmp[3] ^ kPrime[3]; + is_p |= ftmp[4] ^ kPrime[4]; + is_p |= ftmp[5] ^ kPrime[5]; + is_p |= ftmp[6] ^ kPrime[6]; + is_p |= ftmp[7] ^ kPrime[7]; + is_p |= ftmp[8] ^ kPrime[8]; + + is_p--; + is_p = ((s64) is_p) >> 63; + + is_zero |= is_p; + return is_zero; +} static int felem_is_zero_int(const felem in) - { - return (int) (felem_is_zero(in) & ((limb)1)); - } +{ + return (int)(felem_is_zero(in) & ((limb) 1)); +} -/* felem_contract converts |in| to its unique, minimal representation. +/*- + * felem_contract converts |in| to its unique, minimal representation. * On entry: * in[i] < 2^59 + 2^14 */ static void felem_contract(felem out, const felem in) - { - limb is_p, is_greater, sign; - static const limb two58 = ((limb)1) << 58; - - felem_assign(out, in); - - out[0] += out[8] >> 57; out[8] &= bottom57bits; - /* out[8] < 2^57 */ - out[1] += out[0] >> 58; out[0] &= bottom58bits; - out[2] += out[1] >> 58; out[1] &= bottom58bits; - out[3] += out[2] >> 58; out[2] &= bottom58bits; - out[4] += out[3] >> 58; out[3] &= bottom58bits; - out[5] += out[4] >> 58; out[4] &= bottom58bits; - out[6] += out[5] >> 58; out[5] &= bottom58bits; - out[7] += out[6] >> 58; out[6] &= bottom58bits; - out[8] += out[7] >> 58; out[7] &= bottom58bits; - /* out[8] < 2^57 + 4 */ - - /* If the value is greater than 2^521-1 then we have to subtract - * 2^521-1 out. See the comments in felem_is_zero regarding why we - * don't test for other multiples of the prime. */ - - /* First, if |out| is equal to 2^521-1, we subtract it out to get zero. */ - - is_p = out[0] ^ kPrime[0]; - is_p |= out[1] ^ kPrime[1]; - is_p |= out[2] ^ kPrime[2]; - is_p |= out[3] ^ kPrime[3]; - is_p |= out[4] ^ kPrime[4]; - is_p |= out[5] ^ kPrime[5]; - is_p |= out[6] ^ kPrime[6]; - is_p |= out[7] ^ kPrime[7]; - is_p |= out[8] ^ kPrime[8]; - - is_p--; - is_p &= is_p << 32; - is_p &= is_p << 16; - is_p &= is_p << 8; - is_p &= is_p << 4; - is_p &= is_p << 2; - is_p &= is_p << 1; - is_p = ((s64) is_p) >> 63; - is_p = ~is_p; - - /* is_p is 0 iff |out| == 2^521-1 and all ones otherwise */ - - out[0] &= is_p; - out[1] &= is_p; - out[2] &= is_p; - out[3] &= is_p; - out[4] &= is_p; - out[5] &= is_p; - out[6] &= is_p; - out[7] &= is_p; - out[8] &= is_p; - - /* In order to test that |out| >= 2^521-1 we need only test if out[8] - * >> 57 is greater than zero as (2^521-1) + x >= 2^522 */ - is_greater = out[8] >> 57; - is_greater |= is_greater << 32; - is_greater |= is_greater << 16; - is_greater |= is_greater << 8; - is_greater |= is_greater << 4; - is_greater |= is_greater << 2; - is_greater |= is_greater << 1; - is_greater = ((s64) is_greater) >> 63; - - out[0] -= kPrime[0] & is_greater; - out[1] -= kPrime[1] & is_greater; - out[2] -= kPrime[2] & is_greater; - out[3] -= kPrime[3] & is_greater; - out[4] -= kPrime[4] & is_greater; - out[5] -= kPrime[5] & is_greater; - out[6] -= kPrime[6] & is_greater; - out[7] -= kPrime[7] & is_greater; - out[8] -= kPrime[8] & is_greater; - - /* Eliminate negative coefficients */ - sign = -(out[0] >> 63); out[0] += (two58 & sign); out[1] -= (1 & sign); - sign = -(out[1] >> 63); out[1] += (two58 & sign); out[2] -= (1 & sign); - sign = -(out[2] >> 63); out[2] += (two58 & sign); out[3] -= (1 & sign); - sign = -(out[3] >> 63); out[3] += (two58 & sign); out[4] -= (1 & sign); - sign = -(out[4] >> 63); out[4] += (two58 & sign); out[5] -= (1 & sign); - sign = -(out[0] >> 63); out[5] += (two58 & sign); out[6] -= (1 & sign); - sign = -(out[6] >> 63); out[6] += (two58 & sign); out[7] -= (1 & sign); - sign = -(out[7] >> 63); out[7] += (two58 & sign); out[8] -= (1 & sign); - sign = -(out[5] >> 63); out[5] += (two58 & sign); out[6] -= (1 & sign); - sign = -(out[6] >> 63); out[6] += (two58 & sign); out[7] -= (1 & sign); - sign = -(out[7] >> 63); out[7] += (two58 & sign); out[8] -= (1 & sign); - } - -/* Group operations +{ + limb is_p, is_greater, sign; + static const limb two58 = ((limb) 1) << 58; + + felem_assign(out, in); + + out[0] += out[8] >> 57; + out[8] &= bottom57bits; + /* out[8] < 2^57 */ + out[1] += out[0] >> 58; + out[0] &= bottom58bits; + out[2] += out[1] >> 58; + out[1] &= bottom58bits; + out[3] += out[2] >> 58; + out[2] &= bottom58bits; + out[4] += out[3] >> 58; + out[3] &= bottom58bits; + out[5] += out[4] >> 58; + out[4] &= bottom58bits; + out[6] += out[5] >> 58; + out[5] &= bottom58bits; + out[7] += out[6] >> 58; + out[6] &= bottom58bits; + out[8] += out[7] >> 58; + out[7] &= bottom58bits; + /* out[8] < 2^57 + 4 */ + + /* + * If the value is greater than 2^521-1 then we have to subtract 2^521-1 + * out. See the comments in felem_is_zero regarding why we don't test for + * other multiples of the prime. + */ + + /* + * First, if |out| is equal to 2^521-1, we subtract it out to get zero. + */ + + is_p = out[0] ^ kPrime[0]; + is_p |= out[1] ^ kPrime[1]; + is_p |= out[2] ^ kPrime[2]; + is_p |= out[3] ^ kPrime[3]; + is_p |= out[4] ^ kPrime[4]; + is_p |= out[5] ^ kPrime[5]; + is_p |= out[6] ^ kPrime[6]; + is_p |= out[7] ^ kPrime[7]; + is_p |= out[8] ^ kPrime[8]; + + is_p--; + is_p &= is_p << 32; + is_p &= is_p << 16; + is_p &= is_p << 8; + is_p &= is_p << 4; + is_p &= is_p << 2; + is_p &= is_p << 1; + is_p = ((s64) is_p) >> 63; + is_p = ~is_p; + + /* is_p is 0 iff |out| == 2^521-1 and all ones otherwise */ + + out[0] &= is_p; + out[1] &= is_p; + out[2] &= is_p; + out[3] &= is_p; + out[4] &= is_p; + out[5] &= is_p; + out[6] &= is_p; + out[7] &= is_p; + out[8] &= is_p; + + /* + * In order to test that |out| >= 2^521-1 we need only test if out[8] >> + * 57 is greater than zero as (2^521-1) + x >= 2^522 + */ + is_greater = out[8] >> 57; + is_greater |= is_greater << 32; + is_greater |= is_greater << 16; + is_greater |= is_greater << 8; + is_greater |= is_greater << 4; + is_greater |= is_greater << 2; + is_greater |= is_greater << 1; + is_greater = ((s64) is_greater) >> 63; + + out[0] -= kPrime[0] & is_greater; + out[1] -= kPrime[1] & is_greater; + out[2] -= kPrime[2] & is_greater; + out[3] -= kPrime[3] & is_greater; + out[4] -= kPrime[4] & is_greater; + out[5] -= kPrime[5] & is_greater; + out[6] -= kPrime[6] & is_greater; + out[7] -= kPrime[7] & is_greater; + out[8] -= kPrime[8] & is_greater; + + /* Eliminate negative coefficients */ + sign = -(out[0] >> 63); + out[0] += (two58 & sign); + out[1] -= (1 & sign); + sign = -(out[1] >> 63); + out[1] += (two58 & sign); + out[2] -= (1 & sign); + sign = -(out[2] >> 63); + out[2] += (two58 & sign); + out[3] -= (1 & sign); + sign = -(out[3] >> 63); + out[3] += (two58 & sign); + out[4] -= (1 & sign); + sign = -(out[4] >> 63); + out[4] += (two58 & sign); + out[5] -= (1 & sign); + sign = -(out[0] >> 63); + out[5] += (two58 & sign); + out[6] -= (1 & sign); + sign = -(out[6] >> 63); + out[6] += (two58 & sign); + out[7] -= (1 & sign); + sign = -(out[7] >> 63); + out[7] += (two58 & sign); + out[8] -= (1 & sign); + sign = -(out[5] >> 63); + out[5] += (two58 & sign); + out[6] -= (1 & sign); + sign = -(out[6] >> 63); + out[6] += (two58 & sign); + out[7] -= (1 & sign); + sign = -(out[7] >> 63); + out[7] += (two58 & sign); + out[8] -= (1 & sign); +} + +/*- + * Group operations * ---------------- * * Building on top of the field operations we have the operations on the * elliptic curve group itself. Points on the curve are represented in Jacobian * coordinates */ -/* point_double calcuates 2*(x_in, y_in, z_in) +/*- + * point_double calcuates 2*(x_in, y_in, z_in) * * The method is taken from: * http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b @@ -946,103 +1028,114 @@ static void felem_contract(felem out, const felem in) * while x_out == y_in is not (maybe this works, but it's not tested). */ static void point_double(felem x_out, felem y_out, felem z_out, - const felem x_in, const felem y_in, const felem z_in) - { - largefelem tmp, tmp2; - felem delta, gamma, beta, alpha, ftmp, ftmp2; - - felem_assign(ftmp, x_in); - felem_assign(ftmp2, x_in); - - /* delta = z^2 */ - felem_square(tmp, z_in); - felem_reduce(delta, tmp); /* delta[i] < 2^59 + 2^14 */ - - /* gamma = y^2 */ - felem_square(tmp, y_in); - felem_reduce(gamma, tmp); /* gamma[i] < 2^59 + 2^14 */ - - /* beta = x*gamma */ - felem_mul(tmp, x_in, gamma); - felem_reduce(beta, tmp); /* beta[i] < 2^59 + 2^14 */ - - /* alpha = 3*(x-delta)*(x+delta) */ - felem_diff64(ftmp, delta); - /* ftmp[i] < 2^61 */ - felem_sum64(ftmp2, delta); - /* ftmp2[i] < 2^60 + 2^15 */ - felem_scalar64(ftmp2, 3); - /* ftmp2[i] < 3*2^60 + 3*2^15 */ - felem_mul(tmp, ftmp, ftmp2); - /* tmp[i] < 17(3*2^121 + 3*2^76) - * = 61*2^121 + 61*2^76 - * < 64*2^121 + 64*2^76 - * = 2^127 + 2^82 - * < 2^128 */ - felem_reduce(alpha, tmp); - - /* x' = alpha^2 - 8*beta */ - felem_square(tmp, alpha); - /* tmp[i] < 17*2^120 - * < 2^125 */ - felem_assign(ftmp, beta); - felem_scalar64(ftmp, 8); - /* ftmp[i] < 2^62 + 2^17 */ - felem_diff_128_64(tmp, ftmp); - /* tmp[i] < 2^125 + 2^63 + 2^62 + 2^17 */ - felem_reduce(x_out, tmp); - - /* z' = (y + z)^2 - gamma - delta */ - felem_sum64(delta, gamma); - /* delta[i] < 2^60 + 2^15 */ - felem_assign(ftmp, y_in); - felem_sum64(ftmp, z_in); - /* ftmp[i] < 2^60 + 2^15 */ - felem_square(tmp, ftmp); - /* tmp[i] < 17(2^122) - * < 2^127 */ - felem_diff_128_64(tmp, delta); - /* tmp[i] < 2^127 + 2^63 */ - felem_reduce(z_out, tmp); - - /* y' = alpha*(4*beta - x') - 8*gamma^2 */ - felem_scalar64(beta, 4); - /* beta[i] < 2^61 + 2^16 */ - felem_diff64(beta, x_out); - /* beta[i] < 2^61 + 2^60 + 2^16 */ - felem_mul(tmp, alpha, beta); - /* tmp[i] < 17*((2^59 + 2^14)(2^61 + 2^60 + 2^16)) - * = 17*(2^120 + 2^75 + 2^119 + 2^74 + 2^75 + 2^30) - * = 17*(2^120 + 2^119 + 2^76 + 2^74 + 2^30) - * < 2^128 */ - felem_square(tmp2, gamma); - /* tmp2[i] < 17*(2^59 + 2^14)^2 - * = 17*(2^118 + 2^74 + 2^28) */ - felem_scalar128(tmp2, 8); - /* tmp2[i] < 8*17*(2^118 + 2^74 + 2^28) - * = 2^125 + 2^121 + 2^81 + 2^77 + 2^35 + 2^31 - * < 2^126 */ - felem_diff128(tmp, tmp2); - /* tmp[i] < 2^127 - 2^69 + 17(2^120 + 2^119 + 2^76 + 2^74 + 2^30) - * = 2^127 + 2^124 + 2^122 + 2^120 + 2^118 + 2^80 + 2^78 + 2^76 + - * 2^74 + 2^69 + 2^34 + 2^30 - * < 2^128 */ - felem_reduce(y_out, tmp); - } + const felem x_in, const felem y_in, const felem z_in) +{ + largefelem tmp, tmp2; + felem delta, gamma, beta, alpha, ftmp, ftmp2; + + felem_assign(ftmp, x_in); + felem_assign(ftmp2, x_in); + + /* delta = z^2 */ + felem_square(tmp, z_in); + felem_reduce(delta, tmp); /* delta[i] < 2^59 + 2^14 */ + + /* gamma = y^2 */ + felem_square(tmp, y_in); + felem_reduce(gamma, tmp); /* gamma[i] < 2^59 + 2^14 */ + + /* beta = x*gamma */ + felem_mul(tmp, x_in, gamma); + felem_reduce(beta, tmp); /* beta[i] < 2^59 + 2^14 */ + + /* alpha = 3*(x-delta)*(x+delta) */ + felem_diff64(ftmp, delta); + /* ftmp[i] < 2^61 */ + felem_sum64(ftmp2, delta); + /* ftmp2[i] < 2^60 + 2^15 */ + felem_scalar64(ftmp2, 3); + /* ftmp2[i] < 3*2^60 + 3*2^15 */ + felem_mul(tmp, ftmp, ftmp2); + /*- + * tmp[i] < 17(3*2^121 + 3*2^76) + * = 61*2^121 + 61*2^76 + * < 64*2^121 + 64*2^76 + * = 2^127 + 2^82 + * < 2^128 + */ + felem_reduce(alpha, tmp); + + /* x' = alpha^2 - 8*beta */ + felem_square(tmp, alpha); + /* + * tmp[i] < 17*2^120 < 2^125 + */ + felem_assign(ftmp, beta); + felem_scalar64(ftmp, 8); + /* ftmp[i] < 2^62 + 2^17 */ + felem_diff_128_64(tmp, ftmp); + /* tmp[i] < 2^125 + 2^63 + 2^62 + 2^17 */ + felem_reduce(x_out, tmp); + + /* z' = (y + z)^2 - gamma - delta */ + felem_sum64(delta, gamma); + /* delta[i] < 2^60 + 2^15 */ + felem_assign(ftmp, y_in); + felem_sum64(ftmp, z_in); + /* ftmp[i] < 2^60 + 2^15 */ + felem_square(tmp, ftmp); + /* + * tmp[i] < 17(2^122) < 2^127 + */ + felem_diff_128_64(tmp, delta); + /* tmp[i] < 2^127 + 2^63 */ + felem_reduce(z_out, tmp); + + /* y' = alpha*(4*beta - x') - 8*gamma^2 */ + felem_scalar64(beta, 4); + /* beta[i] < 2^61 + 2^16 */ + felem_diff64(beta, x_out); + /* beta[i] < 2^61 + 2^60 + 2^16 */ + felem_mul(tmp, alpha, beta); + /*- + * tmp[i] < 17*((2^59 + 2^14)(2^61 + 2^60 + 2^16)) + * = 17*(2^120 + 2^75 + 2^119 + 2^74 + 2^75 + 2^30) + * = 17*(2^120 + 2^119 + 2^76 + 2^74 + 2^30) + * < 2^128 + */ + felem_square(tmp2, gamma); + /*- + * tmp2[i] < 17*(2^59 + 2^14)^2 + * = 17*(2^118 + 2^74 + 2^28) + */ + felem_scalar128(tmp2, 8); + /*- + * tmp2[i] < 8*17*(2^118 + 2^74 + 2^28) + * = 2^125 + 2^121 + 2^81 + 2^77 + 2^35 + 2^31 + * < 2^126 + */ + felem_diff128(tmp, tmp2); + /*- + * tmp[i] < 2^127 - 2^69 + 17(2^120 + 2^119 + 2^76 + 2^74 + 2^30) + * = 2^127 + 2^124 + 2^122 + 2^120 + 2^118 + 2^80 + 2^78 + 2^76 + + * 2^74 + 2^69 + 2^34 + 2^30 + * < 2^128 + */ + felem_reduce(y_out, tmp); +} /* copy_conditional copies in to out iff mask is all ones. */ -static void -copy_conditional(felem out, const felem in, limb mask) - { - unsigned i; - for (i = 0; i < NLIMBS; ++i) - { - const limb tmp = mask & (in[i] ^ out[i]); - out[i] ^= tmp; - } - } - -/* point_add calcuates (x1, y1, z1) + (x2, y2, z2) +static void copy_conditional(felem out, const felem in, limb mask) +{ + unsigned i; + for (i = 0; i < NLIMBS; ++i) { + const limb tmp = mask & (in[i] ^ out[i]); + out[i] ^= tmp; + } +} + +/*- + * point_add calcuates (x1, y1, z1) + (x2, y2, z2) * * The method is taken from * http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl, @@ -1053,159 +1146,162 @@ copy_conditional(felem out, const felem in, limb mask) * happens during single point multiplication, so there is no timing leak for * ECDH or ECDSA signing. */ static void point_add(felem x3, felem y3, felem z3, - const felem x1, const felem y1, const felem z1, - const int mixed, const felem x2, const felem y2, const felem z2) - { - felem ftmp, ftmp2, ftmp3, ftmp4, ftmp5, ftmp6, x_out, y_out, z_out; - largefelem tmp, tmp2; - limb x_equal, y_equal, z1_is_zero, z2_is_zero; - - z1_is_zero = felem_is_zero(z1); - z2_is_zero = felem_is_zero(z2); - - /* ftmp = z1z1 = z1**2 */ - felem_square(tmp, z1); - felem_reduce(ftmp, tmp); - - if (!mixed) - { - /* ftmp2 = z2z2 = z2**2 */ - felem_square(tmp, z2); - felem_reduce(ftmp2, tmp); - - /* u1 = ftmp3 = x1*z2z2 */ - felem_mul(tmp, x1, ftmp2); - felem_reduce(ftmp3, tmp); - - /* ftmp5 = z1 + z2 */ - felem_assign(ftmp5, z1); - felem_sum64(ftmp5, z2); - /* ftmp5[i] < 2^61 */ - - /* ftmp5 = (z1 + z2)**2 - z1z1 - z2z2 = 2*z1z2 */ - felem_square(tmp, ftmp5); - /* tmp[i] < 17*2^122 */ - felem_diff_128_64(tmp, ftmp); - /* tmp[i] < 17*2^122 + 2^63 */ - felem_diff_128_64(tmp, ftmp2); - /* tmp[i] < 17*2^122 + 2^64 */ - felem_reduce(ftmp5, tmp); - - /* ftmp2 = z2 * z2z2 */ - felem_mul(tmp, ftmp2, z2); - felem_reduce(ftmp2, tmp); - - /* s1 = ftmp6 = y1 * z2**3 */ - felem_mul(tmp, y1, ftmp2); - felem_reduce(ftmp6, tmp); - } - else - { - /* We'll assume z2 = 1 (special case z2 = 0 is handled later) */ - - /* u1 = ftmp3 = x1*z2z2 */ - felem_assign(ftmp3, x1); - - /* ftmp5 = 2*z1z2 */ - felem_scalar(ftmp5, z1, 2); - - /* s1 = ftmp6 = y1 * z2**3 */ - felem_assign(ftmp6, y1); - } - - /* u2 = x2*z1z1 */ - felem_mul(tmp, x2, ftmp); - /* tmp[i] < 17*2^120 */ - - /* h = ftmp4 = u2 - u1 */ - felem_diff_128_64(tmp, ftmp3); - /* tmp[i] < 17*2^120 + 2^63 */ - felem_reduce(ftmp4, tmp); - - x_equal = felem_is_zero(ftmp4); - - /* z_out = ftmp5 * h */ - felem_mul(tmp, ftmp5, ftmp4); - felem_reduce(z_out, tmp); - - /* ftmp = z1 * z1z1 */ - felem_mul(tmp, ftmp, z1); - felem_reduce(ftmp, tmp); - - /* s2 = tmp = y2 * z1**3 */ - felem_mul(tmp, y2, ftmp); - /* tmp[i] < 17*2^120 */ - - /* r = ftmp5 = (s2 - s1)*2 */ - felem_diff_128_64(tmp, ftmp6); - /* tmp[i] < 17*2^120 + 2^63 */ - felem_reduce(ftmp5, tmp); - y_equal = felem_is_zero(ftmp5); - felem_scalar64(ftmp5, 2); - /* ftmp5[i] < 2^61 */ - - if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) - { - point_double(x3, y3, z3, x1, y1, z1); - return; - } - - /* I = ftmp = (2h)**2 */ - felem_assign(ftmp, ftmp4); - felem_scalar64(ftmp, 2); - /* ftmp[i] < 2^61 */ - felem_square(tmp, ftmp); - /* tmp[i] < 17*2^122 */ - felem_reduce(ftmp, tmp); - - /* J = ftmp2 = h * I */ - felem_mul(tmp, ftmp4, ftmp); - felem_reduce(ftmp2, tmp); - - /* V = ftmp4 = U1 * I */ - felem_mul(tmp, ftmp3, ftmp); - felem_reduce(ftmp4, tmp); - - /* x_out = r**2 - J - 2V */ - felem_square(tmp, ftmp5); - /* tmp[i] < 17*2^122 */ - felem_diff_128_64(tmp, ftmp2); - /* tmp[i] < 17*2^122 + 2^63 */ - felem_assign(ftmp3, ftmp4); - felem_scalar64(ftmp4, 2); - /* ftmp4[i] < 2^61 */ - felem_diff_128_64(tmp, ftmp4); - /* tmp[i] < 17*2^122 + 2^64 */ - felem_reduce(x_out, tmp); - - /* y_out = r(V-x_out) - 2 * s1 * J */ - felem_diff64(ftmp3, x_out); - /* ftmp3[i] < 2^60 + 2^60 - * = 2^61 */ - felem_mul(tmp, ftmp5, ftmp3); - /* tmp[i] < 17*2^122 */ - felem_mul(tmp2, ftmp6, ftmp2); - /* tmp2[i] < 17*2^120 */ - felem_scalar128(tmp2, 2); - /* tmp2[i] < 17*2^121 */ - felem_diff128(tmp, tmp2); - /* tmp[i] < 2^127 - 2^69 + 17*2^122 - * = 2^126 - 2^122 - 2^6 - 2^2 - 1 - * < 2^127 */ - felem_reduce(y_out, tmp); - - copy_conditional(x_out, x2, z1_is_zero); - copy_conditional(x_out, x1, z2_is_zero); - copy_conditional(y_out, y2, z1_is_zero); - copy_conditional(y_out, y1, z2_is_zero); - copy_conditional(z_out, z2, z1_is_zero); - copy_conditional(z_out, z1, z2_is_zero); - felem_assign(x3, x_out); - felem_assign(y3, y_out); - felem_assign(z3, z_out); - } - -/* Base point pre computation + const felem x1, const felem y1, const felem z1, + const int mixed, const felem x2, const felem y2, + const felem z2) +{ + felem ftmp, ftmp2, ftmp3, ftmp4, ftmp5, ftmp6, x_out, y_out, z_out; + largefelem tmp, tmp2; + limb x_equal, y_equal, z1_is_zero, z2_is_zero; + + z1_is_zero = felem_is_zero(z1); + z2_is_zero = felem_is_zero(z2); + + /* ftmp = z1z1 = z1**2 */ + felem_square(tmp, z1); + felem_reduce(ftmp, tmp); + + if (!mixed) { + /* ftmp2 = z2z2 = z2**2 */ + felem_square(tmp, z2); + felem_reduce(ftmp2, tmp); + + /* u1 = ftmp3 = x1*z2z2 */ + felem_mul(tmp, x1, ftmp2); + felem_reduce(ftmp3, tmp); + + /* ftmp5 = z1 + z2 */ + felem_assign(ftmp5, z1); + felem_sum64(ftmp5, z2); + /* ftmp5[i] < 2^61 */ + + /* ftmp5 = (z1 + z2)**2 - z1z1 - z2z2 = 2*z1z2 */ + felem_square(tmp, ftmp5); + /* tmp[i] < 17*2^122 */ + felem_diff_128_64(tmp, ftmp); + /* tmp[i] < 17*2^122 + 2^63 */ + felem_diff_128_64(tmp, ftmp2); + /* tmp[i] < 17*2^122 + 2^64 */ + felem_reduce(ftmp5, tmp); + + /* ftmp2 = z2 * z2z2 */ + felem_mul(tmp, ftmp2, z2); + felem_reduce(ftmp2, tmp); + + /* s1 = ftmp6 = y1 * z2**3 */ + felem_mul(tmp, y1, ftmp2); + felem_reduce(ftmp6, tmp); + } else { + /* + * We'll assume z2 = 1 (special case z2 = 0 is handled later) + */ + + /* u1 = ftmp3 = x1*z2z2 */ + felem_assign(ftmp3, x1); + + /* ftmp5 = 2*z1z2 */ + felem_scalar(ftmp5, z1, 2); + + /* s1 = ftmp6 = y1 * z2**3 */ + felem_assign(ftmp6, y1); + } + + /* u2 = x2*z1z1 */ + felem_mul(tmp, x2, ftmp); + /* tmp[i] < 17*2^120 */ + + /* h = ftmp4 = u2 - u1 */ + felem_diff_128_64(tmp, ftmp3); + /* tmp[i] < 17*2^120 + 2^63 */ + felem_reduce(ftmp4, tmp); + + x_equal = felem_is_zero(ftmp4); + + /* z_out = ftmp5 * h */ + felem_mul(tmp, ftmp5, ftmp4); + felem_reduce(z_out, tmp); + + /* ftmp = z1 * z1z1 */ + felem_mul(tmp, ftmp, z1); + felem_reduce(ftmp, tmp); + + /* s2 = tmp = y2 * z1**3 */ + felem_mul(tmp, y2, ftmp); + /* tmp[i] < 17*2^120 */ + + /* r = ftmp5 = (s2 - s1)*2 */ + felem_diff_128_64(tmp, ftmp6); + /* tmp[i] < 17*2^120 + 2^63 */ + felem_reduce(ftmp5, tmp); + y_equal = felem_is_zero(ftmp5); + felem_scalar64(ftmp5, 2); + /* ftmp5[i] < 2^61 */ + + if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) { + point_double(x3, y3, z3, x1, y1, z1); + return; + } + + /* I = ftmp = (2h)**2 */ + felem_assign(ftmp, ftmp4); + felem_scalar64(ftmp, 2); + /* ftmp[i] < 2^61 */ + felem_square(tmp, ftmp); + /* tmp[i] < 17*2^122 */ + felem_reduce(ftmp, tmp); + + /* J = ftmp2 = h * I */ + felem_mul(tmp, ftmp4, ftmp); + felem_reduce(ftmp2, tmp); + + /* V = ftmp4 = U1 * I */ + felem_mul(tmp, ftmp3, ftmp); + felem_reduce(ftmp4, tmp); + + /* x_out = r**2 - J - 2V */ + felem_square(tmp, ftmp5); + /* tmp[i] < 17*2^122 */ + felem_diff_128_64(tmp, ftmp2); + /* tmp[i] < 17*2^122 + 2^63 */ + felem_assign(ftmp3, ftmp4); + felem_scalar64(ftmp4, 2); + /* ftmp4[i] < 2^61 */ + felem_diff_128_64(tmp, ftmp4); + /* tmp[i] < 17*2^122 + 2^64 */ + felem_reduce(x_out, tmp); + + /* y_out = r(V-x_out) - 2 * s1 * J */ + felem_diff64(ftmp3, x_out); + /* + * ftmp3[i] < 2^60 + 2^60 = 2^61 + */ + felem_mul(tmp, ftmp5, ftmp3); + /* tmp[i] < 17*2^122 */ + felem_mul(tmp2, ftmp6, ftmp2); + /* tmp2[i] < 17*2^120 */ + felem_scalar128(tmp2, 2); + /* tmp2[i] < 17*2^121 */ + felem_diff128(tmp, tmp2); + /*- + * tmp[i] < 2^127 - 2^69 + 17*2^122 + * = 2^126 - 2^122 - 2^6 - 2^2 - 1 + * < 2^127 + */ + felem_reduce(y_out, tmp); + + copy_conditional(x_out, x2, z1_is_zero); + copy_conditional(x_out, x1, z2_is_zero); + copy_conditional(y_out, y2, z1_is_zero); + copy_conditional(y_out, y1, z2_is_zero); + copy_conditional(z_out, z2, z1_is_zero); + copy_conditional(z_out, z1, z2_is_zero); + felem_assign(x3, x_out); + felem_assign(y3, y_out); + felem_assign(z3, z_out); +} + +/*- + * Base point pre computation * -------------------------- * * Two different sorts of precomputed tables are used in the following code. @@ -1239,787 +1335,814 @@ static void point_add(felem x3, felem y3, felem z3, * Tables for other points have table[i] = iG for i in 0 .. 16. */ /* gmul is the table of precomputed base points */ -static const felem gmul[16][3] = - {{{0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 0}}, - {{0x017e7e31c2e5bd66, 0x022cf0615a90a6fe, 0x00127a2ffa8de334, - 0x01dfbf9d64a3f877, 0x006b4d3dbaa14b5e, 0x014fed487e0a2bd8, - 0x015b4429c6481390, 0x03a73678fb2d988e, 0x00c6858e06b70404}, - {0x00be94769fd16650, 0x031c21a89cb09022, 0x039013fad0761353, - 0x02657bd099031542, 0x03273e662c97ee72, 0x01e6d11a05ebef45, - 0x03d1bd998f544495, 0x03001172297ed0b1, 0x011839296a789a3b}, - {1, 0, 0, 0, 0, 0, 0, 0, 0}}, - {{0x0373faacbc875bae, 0x00f325023721c671, 0x00f666fd3dbde5ad, - 0x01a6932363f88ea7, 0x01fc6d9e13f9c47b, 0x03bcbffc2bbf734e, - 0x013ee3c3647f3a92, 0x029409fefe75d07d, 0x00ef9199963d85e5}, - {0x011173743ad5b178, 0x02499c7c21bf7d46, 0x035beaeabb8b1a58, - 0x00f989c4752ea0a3, 0x0101e1de48a9c1a3, 0x01a20076be28ba6c, - 0x02f8052e5eb2de95, 0x01bfe8f82dea117c, 0x0160074d3c36ddb7}, - {1, 0, 0, 0, 0, 0, 0, 0, 0}}, - {{0x012f3fc373393b3b, 0x03d3d6172f1419fa, 0x02adc943c0b86873, - 0x00d475584177952b, 0x012a4d1673750ee2, 0x00512517a0f13b0c, - 0x02b184671a7b1734, 0x0315b84236f1a50a, 0x00a4afc472edbdb9}, - {0x00152a7077f385c4, 0x03044007d8d1c2ee, 0x0065829d61d52b52, - 0x00494ff6b6631d0d, 0x00a11d94d5f06bcf, 0x02d2f89474d9282e, - 0x0241c5727c06eeb9, 0x0386928710fbdb9d, 0x01f883f727b0dfbe}, - {1, 0, 0, 0, 0, 0, 0, 0, 0}}, - {{0x019b0c3c9185544d, 0x006243a37c9d97db, 0x02ee3cbe030a2ad2, - 0x00cfdd946bb51e0d, 0x0271c00932606b91, 0x03f817d1ec68c561, - 0x03f37009806a369c, 0x03c1f30baf184fd5, 0x01091022d6d2f065}, - {0x0292c583514c45ed, 0x0316fca51f9a286c, 0x00300af507c1489a, - 0x0295f69008298cf1, 0x02c0ed8274943d7b, 0x016509b9b47a431e, - 0x02bc9de9634868ce, 0x005b34929bffcb09, 0x000c1a0121681524}, - {1, 0, 0, 0, 0, 0, 0, 0, 0}}, - {{0x0286abc0292fb9f2, 0x02665eee9805b3f7, 0x01ed7455f17f26d6, - 0x0346355b83175d13, 0x006284944cd0a097, 0x0191895bcdec5e51, - 0x02e288370afda7d9, 0x03b22312bfefa67a, 0x01d104d3fc0613fe}, - {0x0092421a12f7e47f, 0x0077a83fa373c501, 0x03bd25c5f696bd0d, - 0x035c41e4d5459761, 0x01ca0d1742b24f53, 0x00aaab27863a509c, - 0x018b6de47df73917, 0x025c0b771705cd01, 0x01fd51d566d760a7}, - {1, 0, 0, 0, 0, 0, 0, 0, 0}}, - {{0x01dd92ff6b0d1dbd, 0x039c5e2e8f8afa69, 0x0261ed13242c3b27, - 0x0382c6e67026e6a0, 0x01d60b10be2089f9, 0x03c15f3dce86723f, - 0x03c764a32d2a062d, 0x017307eac0fad056, 0x018207c0b96c5256}, - {0x0196a16d60e13154, 0x03e6ce74c0267030, 0x00ddbf2b4e52a5aa, - 0x012738241bbf31c8, 0x00ebe8dc04685a28, 0x024c2ad6d380d4a2, - 0x035ee062a6e62d0e, 0x0029ed74af7d3a0f, 0x00eef32aec142ebd}, - {1, 0, 0, 0, 0, 0, 0, 0, 0}}, - {{0x00c31ec398993b39, 0x03a9f45bcda68253, 0x00ac733c24c70890, - 0x00872b111401ff01, 0x01d178c23195eafb, 0x03bca2c816b87f74, - 0x0261a9af46fbad7a, 0x0324b2a8dd3d28f9, 0x00918121d8f24e23}, - {0x032bc8c1ca983cd7, 0x00d869dfb08fc8c6, 0x01693cb61fce1516, - 0x012a5ea68f4e88a8, 0x010869cab88d7ae3, 0x009081ad277ceee1, - 0x033a77166d064cdc, 0x03955235a1fb3a95, 0x01251a4a9b25b65e}, - {1, 0, 0, 0, 0, 0, 0, 0, 0}}, - {{0x00148a3a1b27f40b, 0x0123186df1b31fdc, 0x00026e7beaad34ce, - 0x01db446ac1d3dbba, 0x0299c1a33437eaec, 0x024540610183cbb7, - 0x0173bb0e9ce92e46, 0x02b937e43921214b, 0x01ab0436a9bf01b5}, - {0x0383381640d46948, 0x008dacbf0e7f330f, 0x03602122bcc3f318, - 0x01ee596b200620d6, 0x03bd0585fda430b3, 0x014aed77fd123a83, - 0x005ace749e52f742, 0x0390fe041da2b842, 0x0189a8ceb3299242}, - {1, 0, 0, 0, 0, 0, 0, 0, 0}}, - {{0x012a19d6b3282473, 0x00c0915918b423ce, 0x023a954eb94405ae, - 0x00529f692be26158, 0x0289fa1b6fa4b2aa, 0x0198ae4ceea346ef, - 0x0047d8cdfbdedd49, 0x00cc8c8953f0f6b8, 0x001424abbff49203}, - {0x0256732a1115a03a, 0x0351bc38665c6733, 0x03f7b950fb4a6447, - 0x000afffa94c22155, 0x025763d0a4dab540, 0x000511e92d4fc283, - 0x030a7e9eda0ee96c, 0x004c3cd93a28bf0a, 0x017edb3a8719217f}, - {1, 0, 0, 0, 0, 0, 0, 0, 0}}, - {{0x011de5675a88e673, 0x031d7d0f5e567fbe, 0x0016b2062c970ae5, - 0x03f4a2be49d90aa7, 0x03cef0bd13822866, 0x03f0923dcf774a6c, - 0x0284bebc4f322f72, 0x016ab2645302bb2c, 0x01793f95dace0e2a}, - {0x010646e13527a28f, 0x01ca1babd59dc5e7, 0x01afedfd9a5595df, - 0x01f15785212ea6b1, 0x0324e5d64f6ae3f4, 0x02d680f526d00645, - 0x0127920fadf627a7, 0x03b383f75df4f684, 0x0089e0057e783b0a}, - {1, 0, 0, 0, 0, 0, 0, 0, 0}}, - {{0x00f334b9eb3c26c6, 0x0298fdaa98568dce, 0x01c2d24843a82292, - 0x020bcb24fa1b0711, 0x02cbdb3d2b1875e6, 0x0014907598f89422, - 0x03abe3aa43b26664, 0x02cbf47f720bc168, 0x0133b5e73014b79b}, - {0x034aab5dab05779d, 0x00cdc5d71fee9abb, 0x0399f16bd4bd9d30, - 0x03582fa592d82647, 0x02be1cdfb775b0e9, 0x0034f7cea32e94cb, - 0x0335a7f08f56f286, 0x03b707e9565d1c8b, 0x0015c946ea5b614f}, - {1, 0, 0, 0, 0, 0, 0, 0, 0}}, - {{0x024676f6cff72255, 0x00d14625cac96378, 0x00532b6008bc3767, - 0x01fc16721b985322, 0x023355ea1b091668, 0x029de7afdc0317c3, - 0x02fc8a7ca2da037c, 0x02de1217d74a6f30, 0x013f7173175b73bf}, - {0x0344913f441490b5, 0x0200f9e272b61eca, 0x0258a246b1dd55d2, - 0x03753db9ea496f36, 0x025e02937a09c5ef, 0x030cbd3d14012692, - 0x01793a67e70dc72a, 0x03ec1d37048a662e, 0x006550f700c32a8d}, - {1, 0, 0, 0, 0, 0, 0, 0, 0}}, - {{0x00d3f48a347eba27, 0x008e636649b61bd8, 0x00d3b93716778fb3, - 0x004d1915757bd209, 0x019d5311a3da44e0, 0x016d1afcbbe6aade, - 0x0241bf5f73265616, 0x0384672e5d50d39b, 0x005009fee522b684}, - {0x029b4fab064435fe, 0x018868ee095bbb07, 0x01ea3d6936cc92b8, - 0x000608b00f78a2f3, 0x02db911073d1c20f, 0x018205938470100a, - 0x01f1e4964cbe6ff2, 0x021a19a29eed4663, 0x01414485f42afa81}, - {1, 0, 0, 0, 0, 0, 0, 0, 0}}, - {{0x01612b3a17f63e34, 0x03813992885428e6, 0x022b3c215b5a9608, - 0x029b4057e19f2fcb, 0x0384059a587af7e6, 0x02d6400ace6fe610, - 0x029354d896e8e331, 0x00c047ee6dfba65e, 0x0037720542e9d49d}, - {0x02ce9eed7c5e9278, 0x0374ed703e79643b, 0x01316c54c4072006, - 0x005aaa09054b2ee8, 0x002824000c840d57, 0x03d4eba24771ed86, - 0x0189c50aabc3bdae, 0x0338c01541e15510, 0x00466d56e38eed42}, - {1, 0, 0, 0, 0, 0, 0, 0, 0}}, - {{0x007efd8330ad8bd6, 0x02465ed48047710b, 0x0034c6606b215e0c, - 0x016ae30c53cbf839, 0x01fa17bd37161216, 0x018ead4e61ce8ab9, - 0x005482ed5f5dee46, 0x037543755bba1d7f, 0x005e5ac7e70a9d0f}, - {0x0117e1bb2fdcb2a2, 0x03deea36249f40c4, 0x028d09b4a6246cb7, - 0x03524b8855bcf756, 0x023d7d109d5ceb58, 0x0178e43e3223ef9c, - 0x0154536a0c6e966a, 0x037964d1286ee9fe, 0x0199bcd90e125055}, - {1, 0, 0, 0, 0, 0, 0, 0, 0}}}; - -/* select_point selects the |idx|th point from a precomputation table and - * copies it to out. */ -static void select_point(const limb idx, unsigned int size, const felem pre_comp[/* size */][3], - felem out[3]) - { - unsigned i, j; - limb *outlimbs = &out[0][0]; - memset(outlimbs, 0, 3 * sizeof(felem)); - - for (i = 0; i < size; i++) - { - const limb *inlimbs = &pre_comp[i][0][0]; - limb mask = i ^ idx; - mask |= mask >> 4; - mask |= mask >> 2; - mask |= mask >> 1; - mask &= 1; - mask--; - for (j = 0; j < NLIMBS * 3; j++) - outlimbs[j] |= inlimbs[j] & mask; - } - } +static const felem gmul[16][3] = { {{0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x017e7e31c2e5bd66, 0x022cf0615a90a6fe, 0x00127a2ffa8de334, + 0x01dfbf9d64a3f877, 0x006b4d3dbaa14b5e, 0x014fed487e0a2bd8, + 0x015b4429c6481390, 0x03a73678fb2d988e, 0x00c6858e06b70404}, + {0x00be94769fd16650, 0x031c21a89cb09022, 0x039013fad0761353, + 0x02657bd099031542, 0x03273e662c97ee72, 0x01e6d11a05ebef45, + 0x03d1bd998f544495, 0x03001172297ed0b1, 0x011839296a789a3b}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x0373faacbc875bae, 0x00f325023721c671, 0x00f666fd3dbde5ad, + 0x01a6932363f88ea7, 0x01fc6d9e13f9c47b, 0x03bcbffc2bbf734e, + 0x013ee3c3647f3a92, 0x029409fefe75d07d, 0x00ef9199963d85e5}, + {0x011173743ad5b178, 0x02499c7c21bf7d46, 0x035beaeabb8b1a58, + 0x00f989c4752ea0a3, 0x0101e1de48a9c1a3, 0x01a20076be28ba6c, + 0x02f8052e5eb2de95, 0x01bfe8f82dea117c, 0x0160074d3c36ddb7}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x012f3fc373393b3b, 0x03d3d6172f1419fa, 0x02adc943c0b86873, + 0x00d475584177952b, 0x012a4d1673750ee2, 0x00512517a0f13b0c, + 0x02b184671a7b1734, 0x0315b84236f1a50a, 0x00a4afc472edbdb9}, + {0x00152a7077f385c4, 0x03044007d8d1c2ee, 0x0065829d61d52b52, + 0x00494ff6b6631d0d, 0x00a11d94d5f06bcf, 0x02d2f89474d9282e, + 0x0241c5727c06eeb9, 0x0386928710fbdb9d, 0x01f883f727b0dfbe}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x019b0c3c9185544d, 0x006243a37c9d97db, 0x02ee3cbe030a2ad2, + 0x00cfdd946bb51e0d, 0x0271c00932606b91, 0x03f817d1ec68c561, + 0x03f37009806a369c, 0x03c1f30baf184fd5, 0x01091022d6d2f065}, + {0x0292c583514c45ed, 0x0316fca51f9a286c, 0x00300af507c1489a, + 0x0295f69008298cf1, 0x02c0ed8274943d7b, 0x016509b9b47a431e, + 0x02bc9de9634868ce, 0x005b34929bffcb09, 0x000c1a0121681524}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x0286abc0292fb9f2, 0x02665eee9805b3f7, 0x01ed7455f17f26d6, + 0x0346355b83175d13, 0x006284944cd0a097, 0x0191895bcdec5e51, + 0x02e288370afda7d9, 0x03b22312bfefa67a, 0x01d104d3fc0613fe}, + {0x0092421a12f7e47f, 0x0077a83fa373c501, 0x03bd25c5f696bd0d, + 0x035c41e4d5459761, 0x01ca0d1742b24f53, 0x00aaab27863a509c, + 0x018b6de47df73917, 0x025c0b771705cd01, 0x01fd51d566d760a7}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x01dd92ff6b0d1dbd, 0x039c5e2e8f8afa69, 0x0261ed13242c3b27, + 0x0382c6e67026e6a0, 0x01d60b10be2089f9, 0x03c15f3dce86723f, + 0x03c764a32d2a062d, 0x017307eac0fad056, 0x018207c0b96c5256}, + {0x0196a16d60e13154, 0x03e6ce74c0267030, 0x00ddbf2b4e52a5aa, + 0x012738241bbf31c8, 0x00ebe8dc04685a28, 0x024c2ad6d380d4a2, + 0x035ee062a6e62d0e, 0x0029ed74af7d3a0f, 0x00eef32aec142ebd}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x00c31ec398993b39, 0x03a9f45bcda68253, 0x00ac733c24c70890, + 0x00872b111401ff01, 0x01d178c23195eafb, 0x03bca2c816b87f74, + 0x0261a9af46fbad7a, 0x0324b2a8dd3d28f9, 0x00918121d8f24e23}, + {0x032bc8c1ca983cd7, 0x00d869dfb08fc8c6, 0x01693cb61fce1516, + 0x012a5ea68f4e88a8, 0x010869cab88d7ae3, 0x009081ad277ceee1, + 0x033a77166d064cdc, 0x03955235a1fb3a95, 0x01251a4a9b25b65e}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x00148a3a1b27f40b, 0x0123186df1b31fdc, 0x00026e7beaad34ce, + 0x01db446ac1d3dbba, 0x0299c1a33437eaec, 0x024540610183cbb7, + 0x0173bb0e9ce92e46, 0x02b937e43921214b, 0x01ab0436a9bf01b5}, + {0x0383381640d46948, 0x008dacbf0e7f330f, 0x03602122bcc3f318, + 0x01ee596b200620d6, 0x03bd0585fda430b3, 0x014aed77fd123a83, + 0x005ace749e52f742, 0x0390fe041da2b842, 0x0189a8ceb3299242}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x012a19d6b3282473, 0x00c0915918b423ce, 0x023a954eb94405ae, + 0x00529f692be26158, 0x0289fa1b6fa4b2aa, 0x0198ae4ceea346ef, + 0x0047d8cdfbdedd49, 0x00cc8c8953f0f6b8, 0x001424abbff49203}, + {0x0256732a1115a03a, 0x0351bc38665c6733, 0x03f7b950fb4a6447, + 0x000afffa94c22155, 0x025763d0a4dab540, 0x000511e92d4fc283, + 0x030a7e9eda0ee96c, 0x004c3cd93a28bf0a, 0x017edb3a8719217f}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x011de5675a88e673, 0x031d7d0f5e567fbe, 0x0016b2062c970ae5, + 0x03f4a2be49d90aa7, 0x03cef0bd13822866, 0x03f0923dcf774a6c, + 0x0284bebc4f322f72, 0x016ab2645302bb2c, 0x01793f95dace0e2a}, + {0x010646e13527a28f, 0x01ca1babd59dc5e7, 0x01afedfd9a5595df, + 0x01f15785212ea6b1, 0x0324e5d64f6ae3f4, 0x02d680f526d00645, + 0x0127920fadf627a7, 0x03b383f75df4f684, 0x0089e0057e783b0a}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x00f334b9eb3c26c6, 0x0298fdaa98568dce, 0x01c2d24843a82292, + 0x020bcb24fa1b0711, 0x02cbdb3d2b1875e6, 0x0014907598f89422, + 0x03abe3aa43b26664, 0x02cbf47f720bc168, 0x0133b5e73014b79b}, + {0x034aab5dab05779d, 0x00cdc5d71fee9abb, 0x0399f16bd4bd9d30, + 0x03582fa592d82647, 0x02be1cdfb775b0e9, 0x0034f7cea32e94cb, + 0x0335a7f08f56f286, 0x03b707e9565d1c8b, 0x0015c946ea5b614f}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x024676f6cff72255, 0x00d14625cac96378, 0x00532b6008bc3767, + 0x01fc16721b985322, 0x023355ea1b091668, 0x029de7afdc0317c3, + 0x02fc8a7ca2da037c, 0x02de1217d74a6f30, 0x013f7173175b73bf}, + {0x0344913f441490b5, 0x0200f9e272b61eca, 0x0258a246b1dd55d2, + 0x03753db9ea496f36, 0x025e02937a09c5ef, 0x030cbd3d14012692, + 0x01793a67e70dc72a, 0x03ec1d37048a662e, 0x006550f700c32a8d}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x00d3f48a347eba27, 0x008e636649b61bd8, 0x00d3b93716778fb3, + 0x004d1915757bd209, 0x019d5311a3da44e0, 0x016d1afcbbe6aade, + 0x0241bf5f73265616, 0x0384672e5d50d39b, 0x005009fee522b684}, + {0x029b4fab064435fe, 0x018868ee095bbb07, 0x01ea3d6936cc92b8, + 0x000608b00f78a2f3, 0x02db911073d1c20f, 0x018205938470100a, + 0x01f1e4964cbe6ff2, 0x021a19a29eed4663, 0x01414485f42afa81}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x01612b3a17f63e34, 0x03813992885428e6, 0x022b3c215b5a9608, + 0x029b4057e19f2fcb, 0x0384059a587af7e6, 0x02d6400ace6fe610, + 0x029354d896e8e331, 0x00c047ee6dfba65e, 0x0037720542e9d49d}, + {0x02ce9eed7c5e9278, 0x0374ed703e79643b, 0x01316c54c4072006, + 0x005aaa09054b2ee8, 0x002824000c840d57, 0x03d4eba24771ed86, + 0x0189c50aabc3bdae, 0x0338c01541e15510, 0x00466d56e38eed42}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}}, +{{0x007efd8330ad8bd6, 0x02465ed48047710b, 0x0034c6606b215e0c, + 0x016ae30c53cbf839, 0x01fa17bd37161216, 0x018ead4e61ce8ab9, + 0x005482ed5f5dee46, 0x037543755bba1d7f, 0x005e5ac7e70a9d0f}, + {0x0117e1bb2fdcb2a2, 0x03deea36249f40c4, 0x028d09b4a6246cb7, + 0x03524b8855bcf756, 0x023d7d109d5ceb58, 0x0178e43e3223ef9c, + 0x0154536a0c6e966a, 0x037964d1286ee9fe, 0x0199bcd90e125055}, + {1, 0, 0, 0, 0, 0, 0, 0, 0}} +}; + +/* + * select_point selects the |idx|th point from a precomputation table and + * copies it to out. + */ + /* pre_comp below is of the size provided in |size| */ +static void select_point(const limb idx, unsigned int size, + const felem pre_comp[][3], felem out[3]) +{ + unsigned i, j; + limb *outlimbs = &out[0][0]; + memset(outlimbs, 0, 3 * sizeof(felem)); + + for (i = 0; i < size; i++) { + const limb *inlimbs = &pre_comp[i][0][0]; + limb mask = i ^ idx; + mask |= mask >> 4; + mask |= mask >> 2; + mask |= mask >> 1; + mask &= 1; + mask--; + for (j = 0; j < NLIMBS * 3; j++) + outlimbs[j] |= inlimbs[j] & mask; + } +} /* get_bit returns the |i|th bit in |in| */ static char get_bit(const felem_bytearray in, int i) - { - if (i < 0) - return 0; - return (in[i >> 3] >> (i & 7)) & 1; - } - -/* Interleaved point multiplication using precomputed point multiples: - * The small point multiples 0*P, 1*P, ..., 16*P are in pre_comp[], - * the scalars in scalars[]. If g_scalar is non-NULL, we also add this multiple - * of the generator, using certain (large) precomputed multiples in g_pre_comp. - * Output point (X, Y, Z) is stored in x_out, y_out, z_out */ -static void batch_mul(felem x_out, felem y_out, felem z_out, - const felem_bytearray scalars[], const unsigned num_points, const u8 *g_scalar, - const int mixed, const felem pre_comp[][17][3], const felem g_pre_comp[16][3]) - { - int i, skip; - unsigned num, gen_mul = (g_scalar != NULL); - felem nq[3], tmp[4]; - limb bits; - u8 sign, digit; - - /* set nq to the point at infinity */ - memset(nq, 0, 3 * sizeof(felem)); - - /* Loop over all scalars msb-to-lsb, interleaving additions - * of multiples of the generator (last quarter of rounds) - * and additions of other points multiples (every 5th round). - */ - skip = 1; /* save two point operations in the first round */ - for (i = (num_points ? 520 : 130); i >= 0; --i) - { - /* double */ - if (!skip) - point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]); - - /* add multiples of the generator */ - if (gen_mul && (i <= 130)) - { - bits = get_bit(g_scalar, i + 390) << 3; - if (i < 130) - { - bits |= get_bit(g_scalar, i + 260) << 2; - bits |= get_bit(g_scalar, i + 130) << 1; - bits |= get_bit(g_scalar, i); - } - /* select the point to add, in constant time */ - select_point(bits, 16, g_pre_comp, tmp); - if (!skip) - { - point_add(nq[0], nq[1], nq[2], - nq[0], nq[1], nq[2], - 1 /* mixed */, tmp[0], tmp[1], tmp[2]); - } - else - { - memcpy(nq, tmp, 3 * sizeof(felem)); - skip = 0; - } - } - - /* do other additions every 5 doublings */ - if (num_points && (i % 5 == 0)) - { - /* loop over all scalars */ - for (num = 0; num < num_points; ++num) - { - bits = get_bit(scalars[num], i + 4) << 5; - bits |= get_bit(scalars[num], i + 3) << 4; - bits |= get_bit(scalars[num], i + 2) << 3; - bits |= get_bit(scalars[num], i + 1) << 2; - bits |= get_bit(scalars[num], i) << 1; - bits |= get_bit(scalars[num], i - 1); - ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits); - - /* select the point to add or subtract, in constant time */ - select_point(digit, 17, pre_comp[num], tmp); - felem_neg(tmp[3], tmp[1]); /* (X, -Y, Z) is the negative point */ - copy_conditional(tmp[1], tmp[3], (-(limb) sign)); - - if (!skip) - { - point_add(nq[0], nq[1], nq[2], - nq[0], nq[1], nq[2], - mixed, tmp[0], tmp[1], tmp[2]); - } - else - { - memcpy(nq, tmp, 3 * sizeof(felem)); - skip = 0; - } - } - } - } - felem_assign(x_out, nq[0]); - felem_assign(y_out, nq[1]); - felem_assign(z_out, nq[2]); - } +{ + if (i < 0) + return 0; + return (in[i >> 3] >> (i & 7)) & 1; +} +/* + * Interleaved point multiplication using precomputed point multiples: The + * small point multiples 0*P, 1*P, ..., 16*P are in pre_comp[], the scalars + * in scalars[]. If g_scalar is non-NULL, we also add this multiple of the + * generator, using certain (large) precomputed multiples in g_pre_comp. + * Output point (X, Y, Z) is stored in x_out, y_out, z_out + */ +static void batch_mul(felem x_out, felem y_out, felem z_out, + const felem_bytearray scalars[], + const unsigned num_points, const u8 *g_scalar, + const int mixed, const felem pre_comp[][17][3], + const felem g_pre_comp[16][3]) +{ + int i, skip; + unsigned num, gen_mul = (g_scalar != NULL); + felem nq[3], tmp[4]; + limb bits; + u8 sign, digit; + + /* set nq to the point at infinity */ + memset(nq, 0, 3 * sizeof(felem)); + + /* + * Loop over all scalars msb-to-lsb, interleaving additions of multiples + * of the generator (last quarter of rounds) and additions of other + * points multiples (every 5th round). + */ + skip = 1; /* save two point operations in the first + * round */ + for (i = (num_points ? 520 : 130); i >= 0; --i) { + /* double */ + if (!skip) + point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]); + + /* add multiples of the generator */ + if (gen_mul && (i <= 130)) { + bits = get_bit(g_scalar, i + 390) << 3; + if (i < 130) { + bits |= get_bit(g_scalar, i + 260) << 2; + bits |= get_bit(g_scalar, i + 130) << 1; + bits |= get_bit(g_scalar, i); + } + /* select the point to add, in constant time */ + select_point(bits, 16, g_pre_comp, tmp); + if (!skip) { + /* The 1 argument below is for "mixed" */ + point_add(nq[0], nq[1], nq[2], + nq[0], nq[1], nq[2], 1, tmp[0], tmp[1], tmp[2]); + } else { + memcpy(nq, tmp, 3 * sizeof(felem)); + skip = 0; + } + } + + /* do other additions every 5 doublings */ + if (num_points && (i % 5 == 0)) { + /* loop over all scalars */ + for (num = 0; num < num_points; ++num) { + bits = get_bit(scalars[num], i + 4) << 5; + bits |= get_bit(scalars[num], i + 3) << 4; + bits |= get_bit(scalars[num], i + 2) << 3; + bits |= get_bit(scalars[num], i + 1) << 2; + bits |= get_bit(scalars[num], i) << 1; + bits |= get_bit(scalars[num], i - 1); + ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits); + + /* + * select the point to add or subtract, in constant time + */ + select_point(digit, 17, pre_comp[num], tmp); + felem_neg(tmp[3], tmp[1]); /* (X, -Y, Z) is the negative + * point */ + copy_conditional(tmp[1], tmp[3], (-(limb) sign)); + + if (!skip) { + point_add(nq[0], nq[1], nq[2], + nq[0], nq[1], nq[2], + mixed, tmp[0], tmp[1], tmp[2]); + } else { + memcpy(nq, tmp, 3 * sizeof(felem)); + skip = 0; + } + } + } + } + felem_assign(x_out, nq[0]); + felem_assign(y_out, nq[1]); + felem_assign(z_out, nq[2]); +} /* Precomputation for the group generator. */ typedef struct { - felem g_pre_comp[16][3]; - int references; + felem g_pre_comp[16][3]; + int references; } NISTP521_PRE_COMP; const EC_METHOD *EC_GFp_nistp521_method(void) - { - static const EC_METHOD ret = { - EC_FLAGS_DEFAULT_OCT, - NID_X9_62_prime_field, - ec_GFp_nistp521_group_init, - ec_GFp_simple_group_finish, - ec_GFp_simple_group_clear_finish, - ec_GFp_nist_group_copy, - ec_GFp_nistp521_group_set_curve, - ec_GFp_simple_group_get_curve, - ec_GFp_simple_group_get_degree, - ec_GFp_simple_group_check_discriminant, - ec_GFp_simple_point_init, - ec_GFp_simple_point_finish, - ec_GFp_simple_point_clear_finish, - ec_GFp_simple_point_copy, - ec_GFp_simple_point_set_to_infinity, - ec_GFp_simple_set_Jprojective_coordinates_GFp, - ec_GFp_simple_get_Jprojective_coordinates_GFp, - ec_GFp_simple_point_set_affine_coordinates, - ec_GFp_nistp521_point_get_affine_coordinates, - 0 /* point_set_compressed_coordinates */, - 0 /* point2oct */, - 0 /* oct2point */, - ec_GFp_simple_add, - ec_GFp_simple_dbl, - ec_GFp_simple_invert, - 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, - ec_GFp_nistp521_points_mul, - ec_GFp_nistp521_precompute_mult, - ec_GFp_nistp521_have_precompute_mult, - ec_GFp_nist_field_mul, - ec_GFp_nist_field_sqr, - 0 /* field_div */, - 0 /* field_encode */, - 0 /* field_decode */, - 0 /* field_set_to_one */ }; - - return &ret; - } - +{ + static const EC_METHOD ret = { + EC_FLAGS_DEFAULT_OCT, + NID_X9_62_prime_field, + ec_GFp_nistp521_group_init, + ec_GFp_simple_group_finish, + ec_GFp_simple_group_clear_finish, + ec_GFp_nist_group_copy, + ec_GFp_nistp521_group_set_curve, + ec_GFp_simple_group_get_curve, + ec_GFp_simple_group_get_degree, + ec_GFp_simple_group_check_discriminant, + ec_GFp_simple_point_init, + ec_GFp_simple_point_finish, + ec_GFp_simple_point_clear_finish, + ec_GFp_simple_point_copy, + ec_GFp_simple_point_set_to_infinity, + ec_GFp_simple_set_Jprojective_coordinates_GFp, + ec_GFp_simple_get_Jprojective_coordinates_GFp, + ec_GFp_simple_point_set_affine_coordinates, + ec_GFp_nistp521_point_get_affine_coordinates, + 0 /* point_set_compressed_coordinates */ , + 0 /* point2oct */ , + 0 /* oct2point */ , + ec_GFp_simple_add, + ec_GFp_simple_dbl, + ec_GFp_simple_invert, + 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, + ec_GFp_nistp521_points_mul, + ec_GFp_nistp521_precompute_mult, + ec_GFp_nistp521_have_precompute_mult, + ec_GFp_nist_field_mul, + ec_GFp_nist_field_sqr, + 0 /* field_div */ , + 0 /* field_encode */ , + 0 /* field_decode */ , + 0 /* field_set_to_one */ + }; + + return &ret; +} /******************************************************************************/ -/* FUNCTIONS TO MANAGE PRECOMPUTATION +/* + * FUNCTIONS TO MANAGE PRECOMPUTATION */ static NISTP521_PRE_COMP *nistp521_pre_comp_new() - { - NISTP521_PRE_COMP *ret = NULL; - ret = (NISTP521_PRE_COMP *)OPENSSL_malloc(sizeof(NISTP521_PRE_COMP)); - if (!ret) - { - ECerr(EC_F_NISTP521_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); - return ret; - } - memset(ret->g_pre_comp, 0, sizeof(ret->g_pre_comp)); - ret->references = 1; - return ret; - } +{ + NISTP521_PRE_COMP *ret = NULL; + ret = (NISTP521_PRE_COMP *) OPENSSL_malloc(sizeof(NISTP521_PRE_COMP)); + if (!ret) { + ECerr(EC_F_NISTP521_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + return ret; + } + memset(ret->g_pre_comp, 0, sizeof(ret->g_pre_comp)); + ret->references = 1; + return ret; +} static void *nistp521_pre_comp_dup(void *src_) - { - NISTP521_PRE_COMP *src = src_; +{ + NISTP521_PRE_COMP *src = src_; - /* no need to actually copy, these objects never change! */ - CRYPTO_add(&src->references, 1, CRYPTO_LOCK_EC_PRE_COMP); + /* no need to actually copy, these objects never change! */ + CRYPTO_add(&src->references, 1, CRYPTO_LOCK_EC_PRE_COMP); - return src_; - } + return src_; +} static void nistp521_pre_comp_free(void *pre_) - { - int i; - NISTP521_PRE_COMP *pre = pre_; +{ + int i; + NISTP521_PRE_COMP *pre = pre_; - if (!pre) - return; + if (!pre) + return; - i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP); - if (i > 0) - return; + i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP); + if (i > 0) + return; - OPENSSL_free(pre); - } + OPENSSL_free(pre); +} static void nistp521_pre_comp_clear_free(void *pre_) - { - int i; - NISTP521_PRE_COMP *pre = pre_; +{ + int i; + NISTP521_PRE_COMP *pre = pre_; - if (!pre) - return; + if (!pre) + return; - i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP); - if (i > 0) - return; + i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP); + if (i > 0) + return; - OPENSSL_cleanse(pre, sizeof(*pre)); - OPENSSL_free(pre); - } + OPENSSL_cleanse(pre, sizeof(*pre)); + OPENSSL_free(pre); +} /******************************************************************************/ -/* OPENSSL EC_METHOD FUNCTIONS +/* + * OPENSSL EC_METHOD FUNCTIONS */ int ec_GFp_nistp521_group_init(EC_GROUP *group) - { - int ret; - ret = ec_GFp_simple_group_init(group); - group->a_is_minus3 = 1; - return ret; - } +{ + int ret; + ret = ec_GFp_simple_group_init(group); + group->a_is_minus3 = 1; + return ret; +} int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p, - const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) - { - int ret = 0; - BN_CTX *new_ctx = NULL; - BIGNUM *curve_p, *curve_a, *curve_b; - - if (ctx == NULL) - if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0; - BN_CTX_start(ctx); - if (((curve_p = BN_CTX_get(ctx)) == NULL) || - ((curve_a = BN_CTX_get(ctx)) == NULL) || - ((curve_b = BN_CTX_get(ctx)) == NULL)) goto err; - BN_bin2bn(nistp521_curve_params[0], sizeof(felem_bytearray), curve_p); - BN_bin2bn(nistp521_curve_params[1], sizeof(felem_bytearray), curve_a); - BN_bin2bn(nistp521_curve_params[2], sizeof(felem_bytearray), curve_b); - if ((BN_cmp(curve_p, p)) || (BN_cmp(curve_a, a)) || - (BN_cmp(curve_b, b))) - { - ECerr(EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE, - EC_R_WRONG_CURVE_PARAMETERS); - goto err; - } - group->field_mod_func = BN_nist_mod_521; - ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); -err: - BN_CTX_end(ctx); - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - return ret; - } - -/* Takes the Jacobian coordinates (X, Y, Z) of a point and returns - * (X', Y') = (X/Z^2, Y/Z^3) */ + const BIGNUM *a, const BIGNUM *b, + BN_CTX *ctx) +{ + int ret = 0; + BN_CTX *new_ctx = NULL; + BIGNUM *curve_p, *curve_a, *curve_b; + + if (ctx == NULL) + if ((ctx = new_ctx = BN_CTX_new()) == NULL) + return 0; + BN_CTX_start(ctx); + if (((curve_p = BN_CTX_get(ctx)) == NULL) || + ((curve_a = BN_CTX_get(ctx)) == NULL) || + ((curve_b = BN_CTX_get(ctx)) == NULL)) + goto err; + BN_bin2bn(nistp521_curve_params[0], sizeof(felem_bytearray), curve_p); + BN_bin2bn(nistp521_curve_params[1], sizeof(felem_bytearray), curve_a); + BN_bin2bn(nistp521_curve_params[2], sizeof(felem_bytearray), curve_b); + if ((BN_cmp(curve_p, p)) || (BN_cmp(curve_a, a)) || (BN_cmp(curve_b, b))) { + ECerr(EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE, + EC_R_WRONG_CURVE_PARAMETERS); + goto err; + } + group->field_mod_func = BN_nist_mod_521; + ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); + err: + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; +} + +/* + * Takes the Jacobian coordinates (X, Y, Z) of a point and returns (X', Y') = + * (X/Z^2, Y/Z^3) + */ int ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group, - const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx) - { - felem z1, z2, x_in, y_in, x_out, y_out; - largefelem tmp; - - if (EC_POINT_is_at_infinity(group, point)) - { - ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES, - EC_R_POINT_AT_INFINITY); - return 0; - } - if ((!BN_to_felem(x_in, &point->X)) || (!BN_to_felem(y_in, &point->Y)) || - (!BN_to_felem(z1, &point->Z))) return 0; - felem_inv(z2, z1); - felem_square(tmp, z2); felem_reduce(z1, tmp); - felem_mul(tmp, x_in, z1); felem_reduce(x_in, tmp); - felem_contract(x_out, x_in); - if (x != NULL) - { - if (!felem_to_BN(x, x_out)) - { - ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES, ERR_R_BN_LIB); - return 0; - } - } - felem_mul(tmp, z1, z2); felem_reduce(z1, tmp); - felem_mul(tmp, y_in, z1); felem_reduce(y_in, tmp); - felem_contract(y_out, y_in); - if (y != NULL) - { - if (!felem_to_BN(y, y_out)) - { - ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES, ERR_R_BN_LIB); - return 0; - } - } - return 1; - } - -static void make_points_affine(size_t num, felem points[/* num */][3], felem tmp_felems[/* num+1 */]) - { - /* Runs in constant time, unless an input is the point at infinity - * (which normally shouldn't happen). */ - ec_GFp_nistp_points_make_affine_internal( - num, - points, - sizeof(felem), - tmp_felems, - (void (*)(void *)) felem_one, - (int (*)(const void *)) felem_is_zero_int, - (void (*)(void *, const void *)) felem_assign, - (void (*)(void *, const void *)) felem_square_reduce, - (void (*)(void *, const void *, const void *)) felem_mul_reduce, - (void (*)(void *, const void *)) felem_inv, - (void (*)(void *, const void *)) felem_contract); - } - -/* Computes scalar*generator + \sum scalars[i]*points[i], ignoring NULL values - * Result is stored in r (r can equal one of the inputs). */ + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx) +{ + felem z1, z2, x_in, y_in, x_out, y_out; + largefelem tmp; + + if (EC_POINT_is_at_infinity(group, point)) { + ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES, + EC_R_POINT_AT_INFINITY); + return 0; + } + if ((!BN_to_felem(x_in, &point->X)) || (!BN_to_felem(y_in, &point->Y)) || + (!BN_to_felem(z1, &point->Z))) + return 0; + felem_inv(z2, z1); + felem_square(tmp, z2); + felem_reduce(z1, tmp); + felem_mul(tmp, x_in, z1); + felem_reduce(x_in, tmp); + felem_contract(x_out, x_in); + if (x != NULL) { + if (!felem_to_BN(x, x_out)) { + ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES, + ERR_R_BN_LIB); + return 0; + } + } + felem_mul(tmp, z1, z2); + felem_reduce(z1, tmp); + felem_mul(tmp, y_in, z1); + felem_reduce(y_in, tmp); + felem_contract(y_out, y_in); + if (y != NULL) { + if (!felem_to_BN(y, y_out)) { + ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES, + ERR_R_BN_LIB); + return 0; + } + } + return 1; +} + +/* points below is of size |num|, and tmp_felems is of size |num+1/ */ +static void make_points_affine(size_t num, felem points[][3], + felem tmp_felems[]) +{ + /* + * Runs in constant time, unless an input is the point at infinity (which + * normally shouldn't happen). + */ + ec_GFp_nistp_points_make_affine_internal(num, + points, + sizeof(felem), + tmp_felems, + (void (*)(void *))felem_one, + (int (*)(const void *)) + felem_is_zero_int, + (void (*)(void *, const void *)) + felem_assign, + (void (*)(void *, const void *)) + felem_square_reduce, (void (*) + (void *, + const void + *, + const void + *)) + felem_mul_reduce, + (void (*)(void *, const void *)) + felem_inv, + (void (*)(void *, const void *)) + felem_contract); +} + +/* + * Computes scalar*generator + \sum scalars[i]*points[i], ignoring NULL + * values Result is stored in r (r can equal one of the inputs). + */ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, - const BIGNUM *scalar, size_t num, const EC_POINT *points[], - const BIGNUM *scalars[], BN_CTX *ctx) - { - int ret = 0; - int j; - int mixed = 0; - BN_CTX *new_ctx = NULL; - BIGNUM *x, *y, *z, *tmp_scalar; - felem_bytearray g_secret; - felem_bytearray *secrets = NULL; - felem (*pre_comp)[17][3] = NULL; - felem *tmp_felems = NULL; - felem_bytearray tmp; - unsigned i, num_bytes; - int have_pre_comp = 0; - size_t num_points = num; - felem x_in, y_in, z_in, x_out, y_out, z_out; - NISTP521_PRE_COMP *pre = NULL; - felem (*g_pre_comp)[3] = NULL; - EC_POINT *generator = NULL; - const EC_POINT *p = NULL; - const BIGNUM *p_scalar = NULL; - - if (ctx == NULL) - if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0; - BN_CTX_start(ctx); - if (((x = BN_CTX_get(ctx)) == NULL) || - ((y = BN_CTX_get(ctx)) == NULL) || - ((z = BN_CTX_get(ctx)) == NULL) || - ((tmp_scalar = BN_CTX_get(ctx)) == NULL)) - goto err; - - if (scalar != NULL) - { - pre = EC_EX_DATA_get_data(group->extra_data, - nistp521_pre_comp_dup, nistp521_pre_comp_free, - nistp521_pre_comp_clear_free); - if (pre) - /* we have precomputation, try to use it */ - g_pre_comp = &pre->g_pre_comp[0]; - else - /* try to use the standard precomputation */ - g_pre_comp = (felem (*)[3]) gmul; - generator = EC_POINT_new(group); - if (generator == NULL) - goto err; - /* get the generator from precomputation */ - if (!felem_to_BN(x, g_pre_comp[1][0]) || - !felem_to_BN(y, g_pre_comp[1][1]) || - !felem_to_BN(z, g_pre_comp[1][2])) - { - ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB); - goto err; - } - if (!EC_POINT_set_Jprojective_coordinates_GFp(group, - generator, x, y, z, ctx)) - goto err; - if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) - /* precomputation matches generator */ - have_pre_comp = 1; - else - /* we don't have valid precomputation: - * treat the generator as a random point */ - num_points++; - } - - if (num_points > 0) - { - if (num_points >= 2) - { - /* unless we precompute multiples for just one point, - * converting those into affine form is time well spent */ - mixed = 1; - } - secrets = OPENSSL_malloc(num_points * sizeof(felem_bytearray)); - pre_comp = OPENSSL_malloc(num_points * 17 * 3 * sizeof(felem)); - if (mixed) - tmp_felems = OPENSSL_malloc((num_points * 17 + 1) * sizeof(felem)); - if ((secrets == NULL) || (pre_comp == NULL) || (mixed && (tmp_felems == NULL))) - { - ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_MALLOC_FAILURE); - goto err; - } - - /* we treat NULL scalars as 0, and NULL points as points at infinity, - * i.e., they contribute nothing to the linear combination */ - memset(secrets, 0, num_points * sizeof(felem_bytearray)); - memset(pre_comp, 0, num_points * 17 * 3 * sizeof(felem)); - for (i = 0; i < num_points; ++i) - { - if (i == num) - /* we didn't have a valid precomputation, so we pick - * the generator */ - { - p = EC_GROUP_get0_generator(group); - p_scalar = scalar; - } - else - /* the i^th point */ - { - p = points[i]; - p_scalar = scalars[i]; - } - if ((p_scalar != NULL) && (p != NULL)) - { - /* reduce scalar to 0 <= scalar < 2^521 */ - if ((BN_num_bits(p_scalar) > 521) || (BN_is_negative(p_scalar))) - { - /* this is an unusual input, and we don't guarantee - * constant-timeness */ - if (!BN_nnmod(tmp_scalar, p_scalar, &group->order, ctx)) - { - ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB); - goto err; - } - num_bytes = BN_bn2bin(tmp_scalar, tmp); - } - else - num_bytes = BN_bn2bin(p_scalar, tmp); - flip_endian(secrets[i], tmp, num_bytes); - /* precompute multiples */ - if ((!BN_to_felem(x_out, &p->X)) || - (!BN_to_felem(y_out, &p->Y)) || - (!BN_to_felem(z_out, &p->Z))) goto err; - memcpy(pre_comp[i][1][0], x_out, sizeof(felem)); - memcpy(pre_comp[i][1][1], y_out, sizeof(felem)); - memcpy(pre_comp[i][1][2], z_out, sizeof(felem)); - for (j = 2; j <= 16; ++j) - { - if (j & 1) - { - point_add( - pre_comp[i][j][0], pre_comp[i][j][1], pre_comp[i][j][2], - pre_comp[i][1][0], pre_comp[i][1][1], pre_comp[i][1][2], - 0, pre_comp[i][j-1][0], pre_comp[i][j-1][1], pre_comp[i][j-1][2]); - } - else - { - point_double( - pre_comp[i][j][0], pre_comp[i][j][1], pre_comp[i][j][2], - pre_comp[i][j/2][0], pre_comp[i][j/2][1], pre_comp[i][j/2][2]); - } - } - } - } - if (mixed) - make_points_affine(num_points * 17, pre_comp[0], tmp_felems); - } - - /* the scalar for the generator */ - if ((scalar != NULL) && (have_pre_comp)) - { - memset(g_secret, 0, sizeof(g_secret)); - /* reduce scalar to 0 <= scalar < 2^521 */ - if ((BN_num_bits(scalar) > 521) || (BN_is_negative(scalar))) - { - /* this is an unusual input, and we don't guarantee - * constant-timeness */ - if (!BN_nnmod(tmp_scalar, scalar, &group->order, ctx)) - { - ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB); - goto err; - } - num_bytes = BN_bn2bin(tmp_scalar, tmp); - } - else - num_bytes = BN_bn2bin(scalar, tmp); - flip_endian(g_secret, tmp, num_bytes); - /* do the multiplication with generator precomputation*/ - batch_mul(x_out, y_out, z_out, - (const felem_bytearray (*)) secrets, num_points, - g_secret, - mixed, (const felem (*)[17][3]) pre_comp, - (const felem (*)[3]) g_pre_comp); - } - else - /* do the multiplication without generator precomputation */ - batch_mul(x_out, y_out, z_out, - (const felem_bytearray (*)) secrets, num_points, - NULL, mixed, (const felem (*)[17][3]) pre_comp, NULL); - /* reduce the output to its unique minimal representation */ - felem_contract(x_in, x_out); - felem_contract(y_in, y_out); - felem_contract(z_in, z_out); - if ((!felem_to_BN(x, x_in)) || (!felem_to_BN(y, y_in)) || - (!felem_to_BN(z, z_in))) - { - ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB); - goto err; - } - ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx); - -err: - BN_CTX_end(ctx); - if (generator != NULL) - EC_POINT_free(generator); - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - if (secrets != NULL) - OPENSSL_free(secrets); - if (pre_comp != NULL) - OPENSSL_free(pre_comp); - if (tmp_felems != NULL) - OPENSSL_free(tmp_felems); - return ret; - } + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], + const BIGNUM *scalars[], BN_CTX *ctx) +{ + int ret = 0; + int j; + int mixed = 0; + BN_CTX *new_ctx = NULL; + BIGNUM *x, *y, *z, *tmp_scalar; + felem_bytearray g_secret; + felem_bytearray *secrets = NULL; + felem(*pre_comp)[17][3] = NULL; + felem *tmp_felems = NULL; + felem_bytearray tmp; + unsigned i, num_bytes; + int have_pre_comp = 0; + size_t num_points = num; + felem x_in, y_in, z_in, x_out, y_out, z_out; + NISTP521_PRE_COMP *pre = NULL; + felem(*g_pre_comp)[3] = NULL; + EC_POINT *generator = NULL; + const EC_POINT *p = NULL; + const BIGNUM *p_scalar = NULL; + + if (ctx == NULL) + if ((ctx = new_ctx = BN_CTX_new()) == NULL) + return 0; + BN_CTX_start(ctx); + if (((x = BN_CTX_get(ctx)) == NULL) || + ((y = BN_CTX_get(ctx)) == NULL) || + ((z = BN_CTX_get(ctx)) == NULL) || + ((tmp_scalar = BN_CTX_get(ctx)) == NULL)) + goto err; + + if (scalar != NULL) { + pre = EC_EX_DATA_get_data(group->extra_data, + nistp521_pre_comp_dup, + nistp521_pre_comp_free, + nistp521_pre_comp_clear_free); + if (pre) + /* we have precomputation, try to use it */ + g_pre_comp = &pre->g_pre_comp[0]; + else + /* try to use the standard precomputation */ + g_pre_comp = (felem(*)[3]) gmul; + generator = EC_POINT_new(group); + if (generator == NULL) + goto err; + /* get the generator from precomputation */ + if (!felem_to_BN(x, g_pre_comp[1][0]) || + !felem_to_BN(y, g_pre_comp[1][1]) || + !felem_to_BN(z, g_pre_comp[1][2])) { + ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB); + goto err; + } + if (!EC_POINT_set_Jprojective_coordinates_GFp(group, + generator, x, y, z, + ctx)) + goto err; + if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) + /* precomputation matches generator */ + have_pre_comp = 1; + else + /* + * we don't have valid precomputation: treat the generator as a + * random point + */ + num_points++; + } + + if (num_points > 0) { + if (num_points >= 2) { + /* + * unless we precompute multiples for just one point, converting + * those into affine form is time well spent + */ + mixed = 1; + } + secrets = OPENSSL_malloc(num_points * sizeof(felem_bytearray)); + pre_comp = OPENSSL_malloc(num_points * 17 * 3 * sizeof(felem)); + if (mixed) + tmp_felems = + OPENSSL_malloc((num_points * 17 + 1) * sizeof(felem)); + if ((secrets == NULL) || (pre_comp == NULL) + || (mixed && (tmp_felems == NULL))) { + ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* + * we treat NULL scalars as 0, and NULL points as points at infinity, + * i.e., they contribute nothing to the linear combination + */ + memset(secrets, 0, num_points * sizeof(felem_bytearray)); + memset(pre_comp, 0, num_points * 17 * 3 * sizeof(felem)); + for (i = 0; i < num_points; ++i) { + if (i == num) + /* + * we didn't have a valid precomputation, so we pick the + * generator + */ + { + p = EC_GROUP_get0_generator(group); + p_scalar = scalar; + } else + /* the i^th point */ + { + p = points[i]; + p_scalar = scalars[i]; + } + if ((p_scalar != NULL) && (p != NULL)) { + /* reduce scalar to 0 <= scalar < 2^521 */ + if ((BN_num_bits(p_scalar) > 521) + || (BN_is_negative(p_scalar))) { + /* + * this is an unusual input, and we don't guarantee + * constant-timeness + */ + if (!BN_nnmod(tmp_scalar, p_scalar, &group->order, ctx)) { + ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB); + goto err; + } + num_bytes = BN_bn2bin(tmp_scalar, tmp); + } else + num_bytes = BN_bn2bin(p_scalar, tmp); + flip_endian(secrets[i], tmp, num_bytes); + /* precompute multiples */ + if ((!BN_to_felem(x_out, &p->X)) || + (!BN_to_felem(y_out, &p->Y)) || + (!BN_to_felem(z_out, &p->Z))) + goto err; + memcpy(pre_comp[i][1][0], x_out, sizeof(felem)); + memcpy(pre_comp[i][1][1], y_out, sizeof(felem)); + memcpy(pre_comp[i][1][2], z_out, sizeof(felem)); + for (j = 2; j <= 16; ++j) { + if (j & 1) { + point_add(pre_comp[i][j][0], pre_comp[i][j][1], + pre_comp[i][j][2], pre_comp[i][1][0], + pre_comp[i][1][1], pre_comp[i][1][2], 0, + pre_comp[i][j - 1][0], + pre_comp[i][j - 1][1], + pre_comp[i][j - 1][2]); + } else { + point_double(pre_comp[i][j][0], pre_comp[i][j][1], + pre_comp[i][j][2], pre_comp[i][j / 2][0], + pre_comp[i][j / 2][1], + pre_comp[i][j / 2][2]); + } + } + } + } + if (mixed) + make_points_affine(num_points * 17, pre_comp[0], tmp_felems); + } + + /* the scalar for the generator */ + if ((scalar != NULL) && (have_pre_comp)) { + memset(g_secret, 0, sizeof(g_secret)); + /* reduce scalar to 0 <= scalar < 2^521 */ + if ((BN_num_bits(scalar) > 521) || (BN_is_negative(scalar))) { + /* + * this is an unusual input, and we don't guarantee + * constant-timeness + */ + if (!BN_nnmod(tmp_scalar, scalar, &group->order, ctx)) { + ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB); + goto err; + } + num_bytes = BN_bn2bin(tmp_scalar, tmp); + } else + num_bytes = BN_bn2bin(scalar, tmp); + flip_endian(g_secret, tmp, num_bytes); + /* do the multiplication with generator precomputation */ + batch_mul(x_out, y_out, z_out, + (const felem_bytearray(*))secrets, num_points, + g_secret, + mixed, (const felem(*)[17][3])pre_comp, + (const felem(*)[3])g_pre_comp); + } else + /* do the multiplication without generator precomputation */ + batch_mul(x_out, y_out, z_out, + (const felem_bytearray(*))secrets, num_points, + NULL, mixed, (const felem(*)[17][3])pre_comp, NULL); + /* reduce the output to its unique minimal representation */ + felem_contract(x_in, x_out); + felem_contract(y_in, y_out); + felem_contract(z_in, z_out); + if ((!felem_to_BN(x, x_in)) || (!felem_to_BN(y, y_in)) || + (!felem_to_BN(z, z_in))) { + ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB); + goto err; + } + ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx); + + err: + BN_CTX_end(ctx); + if (generator != NULL) + EC_POINT_free(generator); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + if (secrets != NULL) + OPENSSL_free(secrets); + if (pre_comp != NULL) + OPENSSL_free(pre_comp); + if (tmp_felems != NULL) + OPENSSL_free(tmp_felems); + return ret; +} int ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx) - { - int ret = 0; - NISTP521_PRE_COMP *pre = NULL; - int i, j; - BN_CTX *new_ctx = NULL; - BIGNUM *x, *y; - EC_POINT *generator = NULL; - felem tmp_felems[16]; - - /* throw away old precomputation */ - EC_EX_DATA_free_data(&group->extra_data, nistp521_pre_comp_dup, - nistp521_pre_comp_free, nistp521_pre_comp_clear_free); - if (ctx == NULL) - if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0; - BN_CTX_start(ctx); - if (((x = BN_CTX_get(ctx)) == NULL) || - ((y = BN_CTX_get(ctx)) == NULL)) - goto err; - /* get the generator */ - if (group->generator == NULL) goto err; - generator = EC_POINT_new(group); - if (generator == NULL) - goto err; - BN_bin2bn(nistp521_curve_params[3], sizeof (felem_bytearray), x); - BN_bin2bn(nistp521_curve_params[4], sizeof (felem_bytearray), y); - if (!EC_POINT_set_affine_coordinates_GFp(group, generator, x, y, ctx)) - goto err; - if ((pre = nistp521_pre_comp_new()) == NULL) - goto err; - /* if the generator is the standard one, use built-in precomputation */ - if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) - { - memcpy(pre->g_pre_comp, gmul, sizeof(pre->g_pre_comp)); - ret = 1; - goto err; - } - if ((!BN_to_felem(pre->g_pre_comp[1][0], &group->generator->X)) || - (!BN_to_felem(pre->g_pre_comp[1][1], &group->generator->Y)) || - (!BN_to_felem(pre->g_pre_comp[1][2], &group->generator->Z))) - goto err; - /* compute 2^130*G, 2^260*G, 2^390*G */ - for (i = 1; i <= 4; i <<= 1) - { - point_double(pre->g_pre_comp[2*i][0], pre->g_pre_comp[2*i][1], - pre->g_pre_comp[2*i][2], pre->g_pre_comp[i][0], - pre->g_pre_comp[i][1], pre->g_pre_comp[i][2]); - for (j = 0; j < 129; ++j) - { - point_double(pre->g_pre_comp[2*i][0], - pre->g_pre_comp[2*i][1], - pre->g_pre_comp[2*i][2], - pre->g_pre_comp[2*i][0], - pre->g_pre_comp[2*i][1], - pre->g_pre_comp[2*i][2]); - } - } - /* g_pre_comp[0] is the point at infinity */ - memset(pre->g_pre_comp[0], 0, sizeof(pre->g_pre_comp[0])); - /* the remaining multiples */ - /* 2^130*G + 2^260*G */ - point_add(pre->g_pre_comp[6][0], pre->g_pre_comp[6][1], - pre->g_pre_comp[6][2], pre->g_pre_comp[4][0], - pre->g_pre_comp[4][1], pre->g_pre_comp[4][2], - 0, pre->g_pre_comp[2][0], pre->g_pre_comp[2][1], - pre->g_pre_comp[2][2]); - /* 2^130*G + 2^390*G */ - point_add(pre->g_pre_comp[10][0], pre->g_pre_comp[10][1], - pre->g_pre_comp[10][2], pre->g_pre_comp[8][0], - pre->g_pre_comp[8][1], pre->g_pre_comp[8][2], - 0, pre->g_pre_comp[2][0], pre->g_pre_comp[2][1], - pre->g_pre_comp[2][2]); - /* 2^260*G + 2^390*G */ - point_add(pre->g_pre_comp[12][0], pre->g_pre_comp[12][1], - pre->g_pre_comp[12][2], pre->g_pre_comp[8][0], - pre->g_pre_comp[8][1], pre->g_pre_comp[8][2], - 0, pre->g_pre_comp[4][0], pre->g_pre_comp[4][1], - pre->g_pre_comp[4][2]); - /* 2^130*G + 2^260*G + 2^390*G */ - point_add(pre->g_pre_comp[14][0], pre->g_pre_comp[14][1], - pre->g_pre_comp[14][2], pre->g_pre_comp[12][0], - pre->g_pre_comp[12][1], pre->g_pre_comp[12][2], - 0, pre->g_pre_comp[2][0], pre->g_pre_comp[2][1], - pre->g_pre_comp[2][2]); - for (i = 1; i < 8; ++i) - { - /* odd multiples: add G */ - point_add(pre->g_pre_comp[2*i+1][0], pre->g_pre_comp[2*i+1][1], - pre->g_pre_comp[2*i+1][2], pre->g_pre_comp[2*i][0], - pre->g_pre_comp[2*i][1], pre->g_pre_comp[2*i][2], - 0, pre->g_pre_comp[1][0], pre->g_pre_comp[1][1], - pre->g_pre_comp[1][2]); - } - make_points_affine(15, &(pre->g_pre_comp[1]), tmp_felems); - - if (!EC_EX_DATA_set_data(&group->extra_data, pre, nistp521_pre_comp_dup, - nistp521_pre_comp_free, nistp521_pre_comp_clear_free)) - goto err; - ret = 1; - pre = NULL; +{ + int ret = 0; + NISTP521_PRE_COMP *pre = NULL; + int i, j; + BN_CTX *new_ctx = NULL; + BIGNUM *x, *y; + EC_POINT *generator = NULL; + felem tmp_felems[16]; + + /* throw away old precomputation */ + EC_EX_DATA_free_data(&group->extra_data, nistp521_pre_comp_dup, + nistp521_pre_comp_free, + nistp521_pre_comp_clear_free); + if (ctx == NULL) + if ((ctx = new_ctx = BN_CTX_new()) == NULL) + return 0; + BN_CTX_start(ctx); + if (((x = BN_CTX_get(ctx)) == NULL) || ((y = BN_CTX_get(ctx)) == NULL)) + goto err; + /* get the generator */ + if (group->generator == NULL) + goto err; + generator = EC_POINT_new(group); + if (generator == NULL) + goto err; + BN_bin2bn(nistp521_curve_params[3], sizeof(felem_bytearray), x); + BN_bin2bn(nistp521_curve_params[4], sizeof(felem_bytearray), y); + if (!EC_POINT_set_affine_coordinates_GFp(group, generator, x, y, ctx)) + goto err; + if ((pre = nistp521_pre_comp_new()) == NULL) + goto err; + /* + * if the generator is the standard one, use built-in precomputation + */ + if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) { + memcpy(pre->g_pre_comp, gmul, sizeof(pre->g_pre_comp)); + ret = 1; + goto err; + } + if ((!BN_to_felem(pre->g_pre_comp[1][0], &group->generator->X)) || + (!BN_to_felem(pre->g_pre_comp[1][1], &group->generator->Y)) || + (!BN_to_felem(pre->g_pre_comp[1][2], &group->generator->Z))) + goto err; + /* compute 2^130*G, 2^260*G, 2^390*G */ + for (i = 1; i <= 4; i <<= 1) { + point_double(pre->g_pre_comp[2 * i][0], pre->g_pre_comp[2 * i][1], + pre->g_pre_comp[2 * i][2], pre->g_pre_comp[i][0], + pre->g_pre_comp[i][1], pre->g_pre_comp[i][2]); + for (j = 0; j < 129; ++j) { + point_double(pre->g_pre_comp[2 * i][0], + pre->g_pre_comp[2 * i][1], + pre->g_pre_comp[2 * i][2], + pre->g_pre_comp[2 * i][0], + pre->g_pre_comp[2 * i][1], + pre->g_pre_comp[2 * i][2]); + } + } + /* g_pre_comp[0] is the point at infinity */ + memset(pre->g_pre_comp[0], 0, sizeof(pre->g_pre_comp[0])); + /* the remaining multiples */ + /* 2^130*G + 2^260*G */ + point_add(pre->g_pre_comp[6][0], pre->g_pre_comp[6][1], + pre->g_pre_comp[6][2], pre->g_pre_comp[4][0], + pre->g_pre_comp[4][1], pre->g_pre_comp[4][2], + 0, pre->g_pre_comp[2][0], pre->g_pre_comp[2][1], + pre->g_pre_comp[2][2]); + /* 2^130*G + 2^390*G */ + point_add(pre->g_pre_comp[10][0], pre->g_pre_comp[10][1], + pre->g_pre_comp[10][2], pre->g_pre_comp[8][0], + pre->g_pre_comp[8][1], pre->g_pre_comp[8][2], + 0, pre->g_pre_comp[2][0], pre->g_pre_comp[2][1], + pre->g_pre_comp[2][2]); + /* 2^260*G + 2^390*G */ + point_add(pre->g_pre_comp[12][0], pre->g_pre_comp[12][1], + pre->g_pre_comp[12][2], pre->g_pre_comp[8][0], + pre->g_pre_comp[8][1], pre->g_pre_comp[8][2], + 0, pre->g_pre_comp[4][0], pre->g_pre_comp[4][1], + pre->g_pre_comp[4][2]); + /* 2^130*G + 2^260*G + 2^390*G */ + point_add(pre->g_pre_comp[14][0], pre->g_pre_comp[14][1], + pre->g_pre_comp[14][2], pre->g_pre_comp[12][0], + pre->g_pre_comp[12][1], pre->g_pre_comp[12][2], + 0, pre->g_pre_comp[2][0], pre->g_pre_comp[2][1], + pre->g_pre_comp[2][2]); + for (i = 1; i < 8; ++i) { + /* odd multiples: add G */ + point_add(pre->g_pre_comp[2 * i + 1][0], + pre->g_pre_comp[2 * i + 1][1], + pre->g_pre_comp[2 * i + 1][2], pre->g_pre_comp[2 * i][0], + pre->g_pre_comp[2 * i][1], pre->g_pre_comp[2 * i][2], 0, + pre->g_pre_comp[1][0], pre->g_pre_comp[1][1], + pre->g_pre_comp[1][2]); + } + make_points_affine(15, &(pre->g_pre_comp[1]), tmp_felems); + + if (!EC_EX_DATA_set_data(&group->extra_data, pre, nistp521_pre_comp_dup, + nistp521_pre_comp_free, + nistp521_pre_comp_clear_free)) + goto err; + ret = 1; + pre = NULL; err: - BN_CTX_end(ctx); - if (generator != NULL) - EC_POINT_free(generator); - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - if (pre) - nistp521_pre_comp_free(pre); - return ret; - } + BN_CTX_end(ctx); + if (generator != NULL) + EC_POINT_free(generator); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + if (pre) + nistp521_pre_comp_free(pre); + return ret; +} int ec_GFp_nistp521_have_precompute_mult(const EC_GROUP *group) - { - if (EC_EX_DATA_get_data(group->extra_data, nistp521_pre_comp_dup, - nistp521_pre_comp_free, nistp521_pre_comp_clear_free) - != NULL) - return 1; - else - return 0; - } +{ + if (EC_EX_DATA_get_data(group->extra_data, nistp521_pre_comp_dup, + nistp521_pre_comp_free, + nistp521_pre_comp_clear_free) + != NULL) + return 1; + else + return 0; +} #else -static void *dummy=&dummy; +static void *dummy = &dummy; #endif diff --git a/openssl/crypto/ec/ecp_nistputil.c b/openssl/crypto/ec/ecp_nistputil.c index c8140c807..8ba2a25e9 100644 --- a/openssl/crypto/ec/ecp_nistputil.c +++ b/openssl/crypto/ec/ecp_nistputil.c @@ -25,89 +25,108 @@ * Common utility functions for ecp_nistp224.c, ecp_nistp256.c, ecp_nistp521.c. */ -#include <stddef.h> -#include "ec_lcl.h" +# include <stddef.h> +# include "ec_lcl.h" -/* Convert an array of points into affine coordinates. - * (If the point at infinity is found (Z = 0), it remains unchanged.) - * This function is essentially an equivalent to EC_POINTs_make_affine(), but - * works with the internal representation of points as used by ecp_nistp###.c - * rather than with (BIGNUM-based) EC_POINT data structures. - * - * point_array is the input/output buffer ('num' points in projective form, - * i.e. three coordinates each), based on an internal representation of - * field elements of size 'felem_size'. - * - * tmp_felems needs to point to a temporary array of 'num'+1 field elements - * for storage of intermediate values. +/* + * Convert an array of points into affine coordinates. (If the point at + * infinity is found (Z = 0), it remains unchanged.) This function is + * essentially an equivalent to EC_POINTs_make_affine(), but works with the + * internal representation of points as used by ecp_nistp###.c rather than + * with (BIGNUM-based) EC_POINT data structures. point_array is the + * input/output buffer ('num' points in projective form, i.e. three + * coordinates each), based on an internal representation of field elements + * of size 'felem_size'. tmp_felems needs to point to a temporary array of + * 'num'+1 field elements for storage of intermediate values. */ void ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array, - size_t felem_size, void *tmp_felems, - void (*felem_one)(void *out), - int (*felem_is_zero)(const void *in), - void (*felem_assign)(void *out, const void *in), - void (*felem_square)(void *out, const void *in), - void (*felem_mul)(void *out, const void *in1, const void *in2), - void (*felem_inv)(void *out, const void *in), - void (*felem_contract)(void *out, const void *in)) - { - int i = 0; + size_t felem_size, + void *tmp_felems, + void (*felem_one) (void *out), + int (*felem_is_zero) (const void + *in), + void (*felem_assign) (void *out, + const void + *in), + void (*felem_square) (void *out, + const void + *in), + void (*felem_mul) (void *out, + const void + *in1, + const void + *in2), + void (*felem_inv) (void *out, + const void + *in), + void (*felem_contract) (void + *out, + const + void + *in)) +{ + int i = 0; -#define tmp_felem(I) (&((char *)tmp_felems)[(I) * felem_size]) -#define X(I) (&((char *)point_array)[3*(I) * felem_size]) -#define Y(I) (&((char *)point_array)[(3*(I) + 1) * felem_size]) -#define Z(I) (&((char *)point_array)[(3*(I) + 2) * felem_size]) +# define tmp_felem(I) (&((char *)tmp_felems)[(I) * felem_size]) +# define X(I) (&((char *)point_array)[3*(I) * felem_size]) +# define Y(I) (&((char *)point_array)[(3*(I) + 1) * felem_size]) +# define Z(I) (&((char *)point_array)[(3*(I) + 2) * felem_size]) - if (!felem_is_zero(Z(0))) - felem_assign(tmp_felem(0), Z(0)); - else - felem_one(tmp_felem(0)); - for (i = 1; i < (int)num; i++) - { - if (!felem_is_zero(Z(i))) - felem_mul(tmp_felem(i), tmp_felem(i-1), Z(i)); - else - felem_assign(tmp_felem(i), tmp_felem(i-1)); - } - /* Now each tmp_felem(i) is the product of Z(0) .. Z(i), skipping any zero-valued factors: - * if Z(i) = 0, we essentially pretend that Z(i) = 1 */ + if (!felem_is_zero(Z(0))) + felem_assign(tmp_felem(0), Z(0)); + else + felem_one(tmp_felem(0)); + for (i = 1; i < (int)num; i++) { + if (!felem_is_zero(Z(i))) + felem_mul(tmp_felem(i), tmp_felem(i - 1), Z(i)); + else + felem_assign(tmp_felem(i), tmp_felem(i - 1)); + } + /* + * Now each tmp_felem(i) is the product of Z(0) .. Z(i), skipping any + * zero-valued factors: if Z(i) = 0, we essentially pretend that Z(i) = 1 + */ - felem_inv(tmp_felem(num-1), tmp_felem(num-1)); - for (i = num - 1; i >= 0; i--) - { - if (i > 0) - /* tmp_felem(i-1) is the product of Z(0) .. Z(i-1), - * tmp_felem(i) is the inverse of the product of Z(0) .. Z(i) - */ - felem_mul(tmp_felem(num), tmp_felem(i-1), tmp_felem(i)); /* 1/Z(i) */ - else - felem_assign(tmp_felem(num), tmp_felem(0)); /* 1/Z(0) */ + felem_inv(tmp_felem(num - 1), tmp_felem(num - 1)); + for (i = num - 1; i >= 0; i--) { + if (i > 0) + /* + * tmp_felem(i-1) is the product of Z(0) .. Z(i-1), tmp_felem(i) + * is the inverse of the product of Z(0) .. Z(i) + */ + /* 1/Z(i) */ + felem_mul(tmp_felem(num), tmp_felem(i - 1), tmp_felem(i)); + else + felem_assign(tmp_felem(num), tmp_felem(0)); /* 1/Z(0) */ - if (!felem_is_zero(Z(i))) - { - if (i > 0) - /* For next iteration, replace tmp_felem(i-1) by its inverse */ - felem_mul(tmp_felem(i-1), tmp_felem(i), Z(i)); + if (!felem_is_zero(Z(i))) { + if (i > 0) + /* + * For next iteration, replace tmp_felem(i-1) by its inverse + */ + felem_mul(tmp_felem(i - 1), tmp_felem(i), Z(i)); - /* Convert point (X, Y, Z) into affine form (X/(Z^2), Y/(Z^3), 1) */ - felem_square(Z(i), tmp_felem(num)); /* 1/(Z^2) */ - felem_mul(X(i), X(i), Z(i)); /* X/(Z^2) */ - felem_mul(Z(i), Z(i), tmp_felem(num)); /* 1/(Z^3) */ - felem_mul(Y(i), Y(i), Z(i)); /* Y/(Z^3) */ - felem_contract(X(i), X(i)); - felem_contract(Y(i), Y(i)); - felem_one(Z(i)); - } - else - { - if (i > 0) - /* For next iteration, replace tmp_felem(i-1) by its inverse */ - felem_assign(tmp_felem(i-1), tmp_felem(i)); - } - } - } + /* + * Convert point (X, Y, Z) into affine form (X/(Z^2), Y/(Z^3), 1) + */ + felem_square(Z(i), tmp_felem(num)); /* 1/(Z^2) */ + felem_mul(X(i), X(i), Z(i)); /* X/(Z^2) */ + felem_mul(Z(i), Z(i), tmp_felem(num)); /* 1/(Z^3) */ + felem_mul(Y(i), Y(i), Z(i)); /* Y/(Z^3) */ + felem_contract(X(i), X(i)); + felem_contract(Y(i), Y(i)); + felem_one(Z(i)); + } else { + if (i > 0) + /* + * For next iteration, replace tmp_felem(i-1) by its inverse + */ + felem_assign(tmp_felem(i - 1), tmp_felem(i)); + } + } +} -/* +/*- * This function looks at 5+1 scalar bits (5 current, 1 adjacent less * significant bit), and recodes them into a signed digit for use in fast point * multiplication: the use of signed rather than unsigned digits means that @@ -180,18 +199,20 @@ void ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array, * has to be b_4 b_3 b_2 b_1 b_0 0. * */ -void ec_GFp_nistp_recode_scalar_bits(unsigned char *sign, unsigned char *digit, unsigned char in) - { - unsigned char s, d; +void ec_GFp_nistp_recode_scalar_bits(unsigned char *sign, + unsigned char *digit, unsigned char in) +{ + unsigned char s, d; - s = ~((in >> 5) - 1); /* sets all bits to MSB(in), 'in' seen as 6-bit value */ - d = (1 << 6) - in - 1; - d = (d & s) | (in & ~s); - d = (d >> 1) + (d & 1); + s = ~((in >> 5) - 1); /* sets all bits to MSB(in), 'in' seen as + * 6-bit value */ + d = (1 << 6) - in - 1; + d = (d & s) | (in & ~s); + d = (d >> 1) + (d & 1); - *sign = s & 1; - *digit = d; - } + *sign = s & 1; + *digit = d; +} #else -static void *dummy=&dummy; +static void *dummy = &dummy; #endif diff --git a/openssl/crypto/ec/ecp_oct.c b/openssl/crypto/ec/ecp_oct.c index 374a0ee73..e5cec8be8 100644 --- a/openssl/crypto/ec/ecp_oct.c +++ b/openssl/crypto/ec/ecp_oct.c @@ -1,8 +1,9 @@ /* crypto/ec/ecp_oct.c */ -/* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de> - * for the OpenSSL project. - * Includes code written by Bodo Moeller for the OpenSSL project. -*/ +/* + * Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de> + * for the OpenSSL project. Includes code written by Bodo Moeller for the + * OpenSSL project. + */ /* ==================================================================== * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. * @@ -11,7 +12,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -67,367 +68,361 @@ #include "ec_lcl.h" -int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point, - const BIGNUM *x_, int y_bit, BN_CTX *ctx) - { - BN_CTX *new_ctx = NULL; - BIGNUM *tmp1, *tmp2, *x, *y; - int ret = 0; - - /* clear error queue*/ - ERR_clear_error(); - - if (ctx == NULL) - { - ctx = new_ctx = BN_CTX_new(); - if (ctx == NULL) - return 0; - } - - y_bit = (y_bit != 0); - - BN_CTX_start(ctx); - tmp1 = BN_CTX_get(ctx); - tmp2 = BN_CTX_get(ctx); - x = BN_CTX_get(ctx); - y = BN_CTX_get(ctx); - if (y == NULL) goto err; - - /* 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. - */ - - /* tmp1 := x^3 */ - if (!BN_nnmod(x, x_, &group->field,ctx)) goto err; - if (group->meth->field_decode == 0) - { - /* field_{sqr,mul} work on standard representation */ - if (!group->meth->field_sqr(group, tmp2, x_, ctx)) goto err; - if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx)) goto err; - } - else - { - 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 (group->meth->field_decode) - { - if (!group->meth->field_decode(group, tmp2, &group->a, ctx)) goto err; - if (!BN_mod_mul(tmp2, tmp2, x, &group->field, ctx)) goto err; - } - else - { - /* field_mul works on standard representation */ - if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx)) goto err; - } - - if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err; - } - - /* tmp1 := tmp1 + b */ - if (group->meth->field_decode) - { - if (!group->meth->field_decode(group, tmp2, &group->b, ctx)) goto err; - if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err; - } - else - { - if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field)) goto err; - } - - if (!BN_mod_sqrt(y, tmp1, &group->field, ctx)) - { - unsigned long err = ERR_peek_last_error(); - - if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE) - { - ERR_clear_error(); - ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT); - } - else - ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB); - goto err; - } - - if (y_bit != BN_is_odd(y)) - { - if (BN_is_zero(y)) - { - int kron; - - kron = BN_kronecker(x, &group->field, ctx); - if (kron == -2) goto err; - - if (kron == 1) - ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSION_BIT); - else - /* BN_mod_sqrt() should have cought this error (not a square) */ - ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT); - goto err; - } - if (!BN_usub(y, &group->field, y)) goto err; - } - if (y_bit != BN_is_odd(y)) - { - ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_INTERNAL_ERROR); - goto err; - } - - if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err; - - ret = 1; +int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, + EC_POINT *point, + const BIGNUM *x_, int y_bit, + BN_CTX *ctx) +{ + BN_CTX *new_ctx = NULL; + BIGNUM *tmp1, *tmp2, *x, *y; + int ret = 0; + + /* clear error queue */ + ERR_clear_error(); + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + y_bit = (y_bit != 0); + + BN_CTX_start(ctx); + tmp1 = BN_CTX_get(ctx); + tmp2 = BN_CTX_get(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) + goto err; + + /*- + * 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. + */ + + /* tmp1 := x^3 */ + if (!BN_nnmod(x, x_, &group->field, ctx)) + goto err; + if (group->meth->field_decode == 0) { + /* field_{sqr,mul} work on standard representation */ + if (!group->meth->field_sqr(group, tmp2, x_, ctx)) + goto err; + if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx)) + goto err; + } else { + 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 (group->meth->field_decode) { + if (!group->meth->field_decode(group, tmp2, &group->a, ctx)) + goto err; + if (!BN_mod_mul(tmp2, tmp2, x, &group->field, ctx)) + goto err; + } else { + /* field_mul works on standard representation */ + if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx)) + goto err; + } + + if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) + goto err; + } + + /* tmp1 := tmp1 + b */ + if (group->meth->field_decode) { + if (!group->meth->field_decode(group, tmp2, &group->b, ctx)) + goto err; + if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) + goto err; + } else { + if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field)) + goto err; + } + + if (!BN_mod_sqrt(y, tmp1, &group->field, ctx)) { + unsigned long err = ERR_peek_last_error(); + + if (ERR_GET_LIB(err) == ERR_LIB_BN + && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE) { + ERR_clear_error(); + ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, + EC_R_INVALID_COMPRESSED_POINT); + } else + ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, + ERR_R_BN_LIB); + goto err; + } + + if (y_bit != BN_is_odd(y)) { + if (BN_is_zero(y)) { + int kron; + + kron = BN_kronecker(x, &group->field, ctx); + if (kron == -2) + goto err; + + if (kron == 1) + ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, + EC_R_INVALID_COMPRESSION_BIT); + else + /* + * BN_mod_sqrt() should have cought this error (not a square) + */ + ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, + EC_R_INVALID_COMPRESSED_POINT); + goto err; + } + if (!BN_usub(y, &group->field, y)) + goto err; + } + if (y_bit != BN_is_odd(y)) { + ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, + ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) + goto err; + + ret = 1; err: - BN_CTX_end(ctx); - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - return ret; - } - - -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) - { - 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_odd(y)) - 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; + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; +} + +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) +{ + 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_odd(y)) + 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; - } - + 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 *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 & ~1U; - 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 (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx)) goto err; - } - else - { - 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_odd(y)) - { - ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); - 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; - } + 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 & ~1U; + 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 (!EC_POINT_set_compressed_coordinates_GFp + (group, point, x, y_bit, ctx)) + goto err; + } else { + 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_odd(y)) { + ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); + goto err; + } + } + + if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) + goto err; + } + + /* test required by X9.62 */ + if (!EC_POINT_is_on_curve(group, point, ctx)) { + 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; +} diff --git a/openssl/crypto/ec/ecp_smpl.c b/openssl/crypto/ec/ecp_smpl.c index 2d1f35768..2b848216d 100644 --- a/openssl/crypto/ec/ecp_smpl.c +++ b/openssl/crypto/ec/ecp_smpl.c @@ -1,8 +1,9 @@ /* crypto/ec/ecp_smpl.c */ -/* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de> - * for the OpenSSL project. - * Includes code written by Bodo Moeller for the OpenSSL project. -*/ +/* + * Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de> + * for the OpenSSL project. Includes code written by Bodo Moeller for the + * OpenSSL project. + */ /* ==================================================================== * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. * @@ -11,7 +12,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -66,1274 +67,1352 @@ #include <openssl/symhacks.h> #ifdef OPENSSL_FIPS -#include <openssl/fips.h> +# include <openssl/fips.h> #endif #include "ec_lcl.h" const EC_METHOD *EC_GFp_simple_method(void) - { - static const EC_METHOD ret = { - EC_FLAGS_DEFAULT_OCT, - NID_X9_62_prime_field, - ec_GFp_simple_group_init, - ec_GFp_simple_group_finish, - ec_GFp_simple_group_clear_finish, - ec_GFp_simple_group_copy, - ec_GFp_simple_group_set_curve, - ec_GFp_simple_group_get_curve, - ec_GFp_simple_group_get_degree, - ec_GFp_simple_group_check_discriminant, - ec_GFp_simple_point_init, - ec_GFp_simple_point_finish, - ec_GFp_simple_point_clear_finish, - ec_GFp_simple_point_copy, - ec_GFp_simple_point_set_to_infinity, - ec_GFp_simple_set_Jprojective_coordinates_GFp, - ec_GFp_simple_get_Jprojective_coordinates_GFp, - ec_GFp_simple_point_set_affine_coordinates, - ec_GFp_simple_point_get_affine_coordinates, - 0,0,0, - ec_GFp_simple_add, - ec_GFp_simple_dbl, - ec_GFp_simple_invert, - 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 */, - 0 /* field_encode */, - 0 /* field_decode */, - 0 /* field_set_to_one */ }; +{ + static const EC_METHOD ret = { + EC_FLAGS_DEFAULT_OCT, + NID_X9_62_prime_field, + ec_GFp_simple_group_init, + ec_GFp_simple_group_finish, + ec_GFp_simple_group_clear_finish, + ec_GFp_simple_group_copy, + ec_GFp_simple_group_set_curve, + ec_GFp_simple_group_get_curve, + ec_GFp_simple_group_get_degree, + ec_GFp_simple_group_check_discriminant, + ec_GFp_simple_point_init, + ec_GFp_simple_point_finish, + ec_GFp_simple_point_clear_finish, + ec_GFp_simple_point_copy, + ec_GFp_simple_point_set_to_infinity, + ec_GFp_simple_set_Jprojective_coordinates_GFp, + ec_GFp_simple_get_Jprojective_coordinates_GFp, + ec_GFp_simple_point_set_affine_coordinates, + ec_GFp_simple_point_get_affine_coordinates, + 0, 0, 0, + ec_GFp_simple_add, + ec_GFp_simple_dbl, + ec_GFp_simple_invert, + 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 */ , + 0 /* field_encode */ , + 0 /* field_decode */ , + 0 /* field_set_to_one */ + }; #ifdef OPENSSL_FIPS - if (FIPS_mode()) - return fips_ec_gfp_simple_method(); + if (FIPS_mode()) + return fips_ec_gfp_simple_method(); #endif - return &ret; - } - + return &ret; +} -/* Most method functions in this file are designed to work with +/* + * 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); - BN_init(&group->a); - BN_init(&group->b); - group->a_is_minus3 = 0; - return 1; - } - +{ + BN_init(&group->field); + BN_init(&group->a); + BN_init(&group->b); + group->a_is_minus3 = 0; + return 1; +} void ec_GFp_simple_group_finish(EC_GROUP *group) - { - BN_free(&group->field); - BN_free(&group->a); - BN_free(&group->b); - } - +{ + BN_free(&group->field); + BN_free(&group->a); + BN_free(&group->b); +} void ec_GFp_simple_group_clear_finish(EC_GROUP *group) - { - BN_clear_free(&group->field); - BN_clear_free(&group->a); - BN_clear_free(&group->b); - } - +{ + BN_clear_free(&group->field); + BN_clear_free(&group->a); + BN_clear_free(&group->b); +} int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) - { - if (!BN_copy(&dest->field, &src->field)) return 0; - if (!BN_copy(&dest->a, &src->a)) return 0; - if (!BN_copy(&dest->b, &src->b)) return 0; - - dest->a_is_minus3 = src->a_is_minus3; +{ + if (!BN_copy(&dest->field, &src->field)) + return 0; + if (!BN_copy(&dest->a, &src->a)) + return 0; + if (!BN_copy(&dest->b, &src->b)) + return 0; - return 1; - } + dest->a_is_minus3 = src->a_is_minus3; + return 1; +} int ec_GFp_simple_group_set_curve(EC_GROUP *group, - const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) - { - int ret = 0; - BN_CTX *new_ctx = NULL; - BIGNUM *tmp_a; - - /* p must be a prime > 3 */ - if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) - { - ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, EC_R_INVALID_FIELD); - return 0; - } - - if (ctx == NULL) - { - ctx = new_ctx = BN_CTX_new(); - if (ctx == NULL) - return 0; - } - - BN_CTX_start(ctx); - tmp_a = BN_CTX_get(ctx); - if (tmp_a == NULL) goto err; - - /* group->field */ - if (!BN_copy(&group->field, p)) goto err; - BN_set_negative(&group->field, 0); - - /* group->a */ - if (!BN_nnmod(tmp_a, a, p, ctx)) goto err; - if (group->meth->field_encode) - { if (!group->meth->field_encode(group, &group->a, tmp_a, ctx)) goto err; } - else - if (!BN_copy(&group->a, tmp_a)) goto err; - - /* group->b */ - if (!BN_nnmod(&group->b, b, p, ctx)) goto err; - if (group->meth->field_encode) - if (!group->meth->field_encode(group, &group->b, &group->b, ctx)) goto err; - - /* group->a_is_minus3 */ - if (!BN_add_word(tmp_a, 3)) goto err; - group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field)); - - ret = 1; + const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx) +{ + int ret = 0; + BN_CTX *new_ctx = NULL; + BIGNUM *tmp_a; + + /* p must be a prime > 3 */ + if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) { + ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, EC_R_INVALID_FIELD); + return 0; + } + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + tmp_a = BN_CTX_get(ctx); + if (tmp_a == NULL) + goto err; + + /* group->field */ + if (!BN_copy(&group->field, p)) + goto err; + BN_set_negative(&group->field, 0); + + /* group->a */ + if (!BN_nnmod(tmp_a, a, p, ctx)) + goto err; + if (group->meth->field_encode) { + if (!group->meth->field_encode(group, &group->a, tmp_a, ctx)) + goto err; + } else if (!BN_copy(&group->a, tmp_a)) + goto err; + + /* group->b */ + if (!BN_nnmod(&group->b, b, p, ctx)) + goto err; + if (group->meth->field_encode) + if (!group->meth->field_encode(group, &group->b, &group->b, ctx)) + goto err; + + /* group->a_is_minus3 */ + if (!BN_add_word(tmp_a, 3)) + goto err; + group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field)); + + ret = 1; err: - BN_CTX_end(ctx); - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - return ret; - } - - -int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx) - { - int ret = 0; - BN_CTX *new_ctx = NULL; - - if (p != NULL) - { - if (!BN_copy(p, &group->field)) return 0; - } - - if (a != NULL || b != NULL) - { - if (group->meth->field_decode) - { - if (ctx == NULL) - { - ctx = new_ctx = BN_CTX_new(); - if (ctx == NULL) - return 0; - } - if (a != NULL) - { - if (!group->meth->field_decode(group, a, &group->a, ctx)) goto err; - } - if (b != NULL) - { - if (!group->meth->field_decode(group, b, &group->b, ctx)) goto err; - } - } - else - { - if (a != NULL) - { - if (!BN_copy(a, &group->a)) goto err; - } - if (b != NULL) - { - if (!BN_copy(b, &group->b)) goto err; - } - } - } - - ret = 1; - - err: - if (new_ctx) - BN_CTX_free(new_ctx); - return ret; - } + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, + BIGNUM *b, BN_CTX *ctx) +{ + int ret = 0; + BN_CTX *new_ctx = NULL; + + if (p != NULL) { + if (!BN_copy(p, &group->field)) + return 0; + } + + if (a != NULL || b != NULL) { + if (group->meth->field_decode) { + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + if (a != NULL) { + if (!group->meth->field_decode(group, a, &group->a, ctx)) + goto err; + } + if (b != NULL) { + if (!group->meth->field_decode(group, b, &group->b, ctx)) + goto err; + } + } else { + if (a != NULL) { + if (!BN_copy(a, &group->a)) + goto err; + } + if (b != NULL) { + if (!BN_copy(b, &group->b)) + goto err; + } + } + } + + ret = 1; + err: + if (new_ctx) + BN_CTX_free(new_ctx); + return ret; +} int ec_GFp_simple_group_get_degree(const EC_GROUP *group) - { - return BN_num_bits(&group->field); - } - +{ + return BN_num_bits(&group->field); +} int ec_GFp_simple_group_check_discriminant(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; - - if (ctx == NULL) - { - ctx = new_ctx = BN_CTX_new(); - if (ctx == NULL) - { - ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT, 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)) 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)) goto err; - } - ret = 1; - -err: - if (ctx != NULL) - BN_CTX_end(ctx); - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - return ret; - } +{ + int ret = 0; + BIGNUM *a, *b, *order, *tmp_1, *tmp_2; + const BIGNUM *p = &group->field; + BN_CTX *new_ctx = NULL; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) { + ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT, + 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)) + 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)) + goto err; + } + ret = 1; + err: + if (ctx != NULL) + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; +} int ec_GFp_simple_point_init(EC_POINT *point) - { - BN_init(&point->X); - BN_init(&point->Y); - BN_init(&point->Z); - point->Z_is_one = 0; - - return 1; - } +{ + BN_init(&point->X); + BN_init(&point->Y); + BN_init(&point->Z); + point->Z_is_one = 0; + return 1; +} void ec_GFp_simple_point_finish(EC_POINT *point) - { - BN_free(&point->X); - BN_free(&point->Y); - BN_free(&point->Z); - } - +{ + BN_free(&point->X); + BN_free(&point->Y); + BN_free(&point->Z); +} void ec_GFp_simple_point_clear_finish(EC_POINT *point) - { - BN_clear_free(&point->X); - BN_clear_free(&point->Y); - BN_clear_free(&point->Z); - point->Z_is_one = 0; - } - +{ + BN_clear_free(&point->X); + BN_clear_free(&point->Y); + BN_clear_free(&point->Z); + point->Z_is_one = 0; +} int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src) - { - if (!BN_copy(&dest->X, &src->X)) return 0; - if (!BN_copy(&dest->Y, &src->Y)) return 0; - if (!BN_copy(&dest->Z, &src->Z)) return 0; - dest->Z_is_one = src->Z_is_one; - - return 1; - } - - -int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point) - { - point->Z_is_one = 0; - BN_zero(&point->Z); - return 1; - } - - -int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, - const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx) - { - BN_CTX *new_ctx = NULL; - int ret = 0; - - if (ctx == NULL) - { - ctx = new_ctx = BN_CTX_new(); - if (ctx == NULL) - return 0; - } - - if (x != NULL) - { - if (!BN_nnmod(&point->X, x, &group->field, ctx)) goto err; - if (group->meth->field_encode) - { - if (!group->meth->field_encode(group, &point->X, &point->X, ctx)) goto err; - } - } - - if (y != NULL) - { - if (!BN_nnmod(&point->Y, y, &group->field, ctx)) goto err; - if (group->meth->field_encode) - { - if (!group->meth->field_encode(group, &point->Y, &point->Y, ctx)) goto err; - } - } - - if (z != NULL) - { - int Z_is_one; - - if (!BN_nnmod(&point->Z, z, &group->field, ctx)) goto err; - Z_is_one = BN_is_one(&point->Z); - if (group->meth->field_encode) - { - if (Z_is_one && (group->meth->field_set_to_one != 0)) - { - if (!group->meth->field_set_to_one(group, &point->Z, ctx)) goto err; - } - else - { - if (!group->meth->field_encode(group, &point->Z, &point->Z, ctx)) goto err; - } - } - point->Z_is_one = Z_is_one; - } - - ret = 1; - +{ + if (!BN_copy(&dest->X, &src->X)) + return 0; + if (!BN_copy(&dest->Y, &src->Y)) + return 0; + if (!BN_copy(&dest->Z, &src->Z)) + return 0; + dest->Z_is_one = src->Z_is_one; + + return 1; +} + +int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, + EC_POINT *point) +{ + point->Z_is_one = 0; + BN_zero(&point->Z); + return 1; +} + +int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *group, + EC_POINT *point, + const BIGNUM *x, + const BIGNUM *y, + const BIGNUM *z, + BN_CTX *ctx) +{ + BN_CTX *new_ctx = NULL; + int ret = 0; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + if (x != NULL) { + if (!BN_nnmod(&point->X, x, &group->field, ctx)) + goto err; + if (group->meth->field_encode) { + if (!group->meth->field_encode(group, &point->X, &point->X, ctx)) + goto err; + } + } + + if (y != NULL) { + if (!BN_nnmod(&point->Y, y, &group->field, ctx)) + goto err; + if (group->meth->field_encode) { + if (!group->meth->field_encode(group, &point->Y, &point->Y, ctx)) + goto err; + } + } + + if (z != NULL) { + int Z_is_one; + + if (!BN_nnmod(&point->Z, z, &group->field, ctx)) + goto err; + Z_is_one = BN_is_one(&point->Z); + if (group->meth->field_encode) { + if (Z_is_one && (group->meth->field_set_to_one != 0)) { + if (!group->meth->field_set_to_one(group, &point->Z, ctx)) + goto err; + } else { + if (!group-> + meth->field_encode(group, &point->Z, &point->Z, ctx)) + goto err; + } + } + point->Z_is_one = Z_is_one; + } + + ret = 1; + err: - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - return ret; - } - - -int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point, - BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx) - { - BN_CTX *new_ctx = NULL; - int ret = 0; - - if (group->meth->field_decode != 0) - { - if (ctx == NULL) - { - ctx = new_ctx = BN_CTX_new(); - if (ctx == NULL) - return 0; - } - - 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 (z != NULL) - { - if (!group->meth->field_decode(group, z, &point->Z, ctx)) goto err; - } - } - else - { - if (x != NULL) - { - if (!BN_copy(x, &point->X)) goto err; - } - if (y != NULL) - { - if (!BN_copy(y, &point->Y)) goto err; - } - if (z != NULL) - { - if (!BN_copy(z, &point->Z)) goto err; - } - } - - ret = 1; + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BIGNUM *z, BN_CTX *ctx) +{ + BN_CTX *new_ctx = NULL; + int ret = 0; + + if (group->meth->field_decode != 0) { + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + 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 (z != NULL) { + if (!group->meth->field_decode(group, z, &point->Z, ctx)) + goto err; + } + } else { + if (x != NULL) { + if (!BN_copy(x, &point->X)) + goto err; + } + if (y != NULL) { + if (!BN_copy(y, &point->Y)) + goto err; + } + if (z != NULL) { + if (!BN_copy(z, &point->Z)) + goto err; + } + } + + ret = 1; err: - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - return ret; - } - - -int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point, - const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) - { - if (x == NULL || y == NULL) - { - /* unlike for projective coordinates, we do not tolerate this */ - ECerr(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - - return EC_POINT_set_Jprojective_coordinates_GFp(group, point, x, y, BN_value_one(), ctx); - } - - -int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point, - BIGNUM *x, BIGNUM *y, BN_CTX *ctx) - { - BN_CTX *new_ctx = NULL; - BIGNUM *Z, *Z_1, *Z_2, *Z_3; - const BIGNUM *Z_; - int ret = 0; - - if (EC_POINT_is_at_infinity(group, point)) - { - ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, 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); - 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, Z, &point->Z, ctx)) goto err; - Z_ = Z; - } - else - { - Z_ = &point->Z; - } - - if (BN_is_one(Z_)) - { - if (group->meth->field_decode) - { - 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; - } - } - else - { - if (x != NULL) - { - if (!BN_copy(x, &point->X)) goto err; - } - if (y != NULL) - { - if (!BN_copy(y, &point->Y)) goto err; - } - } - } - else - { - if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx)) - { - ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_BN_LIB); - goto err; - } - - if (group->meth->field_encode == 0) - { - /* field_sqr works on standard representation */ - if (!group->meth->field_sqr(group, Z_2, Z_1, ctx)) goto err; - } - else - { - if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) goto err; - } - - if (x != NULL) - { - /* 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) - { - if (group->meth->field_encode == 0) - { - /* field_mul works on standard representation */ - if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) goto err; - } - else - { - if (!BN_mod_mul(Z_3, Z_2, Z_1, &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; - } - } - - ret = 1; + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group, + EC_POINT *point, + const BIGNUM *x, + const BIGNUM *y, BN_CTX *ctx) +{ + if (x == NULL || y == NULL) { + /* + * unlike for projective coordinates, we do not tolerate this + */ + ECerr(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + return EC_POINT_set_Jprojective_coordinates_GFp(group, point, x, y, + BN_value_one(), ctx); +} + +int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx) +{ + BN_CTX *new_ctx = NULL; + BIGNUM *Z, *Z_1, *Z_2, *Z_3; + const BIGNUM *Z_; + int ret = 0; + + if (EC_POINT_is_at_infinity(group, point)) { + ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, + 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); + 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, Z, &point->Z, ctx)) + goto err; + Z_ = Z; + } else { + Z_ = &point->Z; + } + + if (BN_is_one(Z_)) { + if (group->meth->field_decode) { + 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; + } + } else { + if (x != NULL) { + if (!BN_copy(x, &point->X)) + goto err; + } + if (y != NULL) { + if (!BN_copy(y, &point->Y)) + goto err; + } + } + } else { + if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx)) { + ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, + ERR_R_BN_LIB); + goto err; + } + + if (group->meth->field_encode == 0) { + /* field_sqr works on standard representation */ + if (!group->meth->field_sqr(group, Z_2, Z_1, ctx)) + goto err; + } else { + if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) + goto err; + } + + if (x != NULL) { + /* + * 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) { + if (group->meth->field_encode == 0) { + /* + * field_mul works on standard representation + */ + if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) + goto err; + } else { + if (!BN_mod_mul(Z_3, Z_2, Z_1, &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; + } + } + + 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) - { - int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); - int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); - const BIGNUM *p; - BN_CTX *new_ctx = NULL; - BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6; - int ret = 0; - - if (a == b) - return EC_POINT_dbl(group, r, a, ctx); - if (EC_POINT_is_at_infinity(group, a)) - return EC_POINT_copy(r, b); - if (EC_POINT_is_at_infinity(group, b)) - return EC_POINT_copy(r, a); - - field_mul = group->meth->field_mul; - field_sqr = group->meth->field_sqr; - p = &group->field; - - if (ctx == NULL) - { - ctx = new_ctx = BN_CTX_new(); - if (ctx == NULL) - return 0; - } - - BN_CTX_start(ctx); - n0 = BN_CTX_get(ctx); - n1 = BN_CTX_get(ctx); - n2 = BN_CTX_get(ctx); - n3 = BN_CTX_get(ctx); - n4 = BN_CTX_get(ctx); - n5 = BN_CTX_get(ctx); - n6 = BN_CTX_get(ctx); - if (n6 == NULL) goto end; - - /* Note that in this function we must not read components of 'a' or 'b' - * once we have written the corresponding components of 'r'. - * ('r' might be one of 'a' or 'b'.) - */ - - /* n1, n2 */ - if (b->Z_is_one) - { - if (!BN_copy(n1, &a->X)) goto end; - if (!BN_copy(n2, &a->Y)) goto end; - /* n1 = X_a */ - /* n2 = Y_a */ - } - else - { - if (!field_sqr(group, n0, &b->Z, ctx)) goto end; - if (!field_mul(group, n1, &a->X, n0, ctx)) goto end; - /* n1 = X_a * Z_b^2 */ - - if (!field_mul(group, n0, n0, &b->Z, ctx)) goto end; - if (!field_mul(group, n2, &a->Y, n0, ctx)) goto end; - /* n2 = Y_a * Z_b^3 */ - } - - /* n3, n4 */ - if (a->Z_is_one) - { - if (!BN_copy(n3, &b->X)) goto end; - if (!BN_copy(n4, &b->Y)) goto end; - /* n3 = X_b */ - /* n4 = Y_b */ - } - else - { - if (!field_sqr(group, n0, &a->Z, ctx)) goto end; - if (!field_mul(group, n3, &b->X, n0, ctx)) goto end; - /* n3 = X_b * Z_a^2 */ - - if (!field_mul(group, n0, n0, &a->Z, ctx)) goto end; - if (!field_mul(group, n4, &b->Y, n0, ctx)) goto end; - /* n4 = Y_b * Z_a^3 */ - } - - /* n5, n6 */ - if (!BN_mod_sub_quick(n5, n1, n3, p)) goto end; - if (!BN_mod_sub_quick(n6, n2, n4, p)) goto end; - /* n5 = n1 - n3 */ - /* n6 = n2 - n4 */ - - if (BN_is_zero(n5)) - { - if (BN_is_zero(n6)) - { - /* a is the same point as b */ - BN_CTX_end(ctx); - ret = EC_POINT_dbl(group, r, a, ctx); - ctx = NULL; - goto end; - } - else - { - /* a is the inverse of b */ - BN_zero(&r->Z); - r->Z_is_one = 0; - ret = 1; - goto end; - } - } - - /* 'n7', 'n8' */ - if (!BN_mod_add_quick(n1, n1, n3, p)) goto end; - if (!BN_mod_add_quick(n2, n2, n4, p)) goto end; - /* 'n7' = n1 + n3 */ - /* 'n8' = n2 + n4 */ - - /* Z_r */ - if (a->Z_is_one && b->Z_is_one) - { - if (!BN_copy(&r->Z, n5)) goto end; - } - else - { - if (a->Z_is_one) - { if (!BN_copy(n0, &b->Z)) goto end; } - else if (b->Z_is_one) - { if (!BN_copy(n0, &a->Z)) goto end; } - else - { if (!field_mul(group, n0, &a->Z, &b->Z, ctx)) goto end; } - if (!field_mul(group, &r->Z, n0, n5, ctx)) goto end; - } - r->Z_is_one = 0; - /* Z_r = Z_a * Z_b * n5 */ - - /* X_r */ - if (!field_sqr(group, n0, n6, ctx)) goto end; - if (!field_sqr(group, n4, n5, ctx)) goto end; - if (!field_mul(group, n3, n1, n4, ctx)) goto end; - if (!BN_mod_sub_quick(&r->X, n0, n3, p)) goto end; - /* X_r = n6^2 - n5^2 * 'n7' */ - - /* 'n9' */ - if (!BN_mod_lshift1_quick(n0, &r->X, p)) goto end; - if (!BN_mod_sub_quick(n0, n3, n0, p)) goto end; - /* n9 = n5^2 * 'n7' - 2 * X_r */ - - /* Y_r */ - if (!field_mul(group, n0, n0, n6, ctx)) goto end; - if (!field_mul(group, n5, n4, n5, ctx)) goto end; /* now n5 is n5^3 */ - if (!field_mul(group, n1, n2, n5, ctx)) goto end; - if (!BN_mod_sub_quick(n0, n0, n1, p)) goto end; - if (BN_is_odd(n0)) - if (!BN_add(n0, n0, p)) goto end; - /* now 0 <= n0 < 2*p, and n0 is even */ - if (!BN_rshift1(&r->Y, n0)) goto end; - /* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */ - - ret = 1; + 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) +{ + int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, + const BIGNUM *, BN_CTX *); + int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); + const BIGNUM *p; + BN_CTX *new_ctx = NULL; + BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6; + int ret = 0; + + if (a == b) + return EC_POINT_dbl(group, r, a, ctx); + if (EC_POINT_is_at_infinity(group, a)) + return EC_POINT_copy(r, b); + if (EC_POINT_is_at_infinity(group, b)) + return EC_POINT_copy(r, a); + + field_mul = group->meth->field_mul; + field_sqr = group->meth->field_sqr; + p = &group->field; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + n0 = BN_CTX_get(ctx); + n1 = BN_CTX_get(ctx); + n2 = BN_CTX_get(ctx); + n3 = BN_CTX_get(ctx); + n4 = BN_CTX_get(ctx); + n5 = BN_CTX_get(ctx); + n6 = BN_CTX_get(ctx); + if (n6 == NULL) + goto end; + + /* + * Note that in this function we must not read components of 'a' or 'b' + * once we have written the corresponding components of 'r'. ('r' might + * be one of 'a' or 'b'.) + */ + + /* n1, n2 */ + if (b->Z_is_one) { + if (!BN_copy(n1, &a->X)) + goto end; + if (!BN_copy(n2, &a->Y)) + goto end; + /* n1 = X_a */ + /* n2 = Y_a */ + } else { + if (!field_sqr(group, n0, &b->Z, ctx)) + goto end; + if (!field_mul(group, n1, &a->X, n0, ctx)) + goto end; + /* n1 = X_a * Z_b^2 */ + + if (!field_mul(group, n0, n0, &b->Z, ctx)) + goto end; + if (!field_mul(group, n2, &a->Y, n0, ctx)) + goto end; + /* n2 = Y_a * Z_b^3 */ + } + + /* n3, n4 */ + if (a->Z_is_one) { + if (!BN_copy(n3, &b->X)) + goto end; + if (!BN_copy(n4, &b->Y)) + goto end; + /* n3 = X_b */ + /* n4 = Y_b */ + } else { + if (!field_sqr(group, n0, &a->Z, ctx)) + goto end; + if (!field_mul(group, n3, &b->X, n0, ctx)) + goto end; + /* n3 = X_b * Z_a^2 */ + + if (!field_mul(group, n0, n0, &a->Z, ctx)) + goto end; + if (!field_mul(group, n4, &b->Y, n0, ctx)) + goto end; + /* n4 = Y_b * Z_a^3 */ + } + + /* n5, n6 */ + if (!BN_mod_sub_quick(n5, n1, n3, p)) + goto end; + if (!BN_mod_sub_quick(n6, n2, n4, p)) + goto end; + /* n5 = n1 - n3 */ + /* n6 = n2 - n4 */ + + if (BN_is_zero(n5)) { + if (BN_is_zero(n6)) { + /* a is the same point as b */ + BN_CTX_end(ctx); + ret = EC_POINT_dbl(group, r, a, ctx); + ctx = NULL; + goto end; + } else { + /* a is the inverse of b */ + BN_zero(&r->Z); + r->Z_is_one = 0; + ret = 1; + goto end; + } + } + + /* 'n7', 'n8' */ + if (!BN_mod_add_quick(n1, n1, n3, p)) + goto end; + if (!BN_mod_add_quick(n2, n2, n4, p)) + goto end; + /* 'n7' = n1 + n3 */ + /* 'n8' = n2 + n4 */ + + /* Z_r */ + if (a->Z_is_one && b->Z_is_one) { + if (!BN_copy(&r->Z, n5)) + goto end; + } else { + if (a->Z_is_one) { + if (!BN_copy(n0, &b->Z)) + goto end; + } else if (b->Z_is_one) { + if (!BN_copy(n0, &a->Z)) + goto end; + } else { + if (!field_mul(group, n0, &a->Z, &b->Z, ctx)) + goto end; + } + if (!field_mul(group, &r->Z, n0, n5, ctx)) + goto end; + } + r->Z_is_one = 0; + /* Z_r = Z_a * Z_b * n5 */ + + /* X_r */ + if (!field_sqr(group, n0, n6, ctx)) + goto end; + if (!field_sqr(group, n4, n5, ctx)) + goto end; + if (!field_mul(group, n3, n1, n4, ctx)) + goto end; + if (!BN_mod_sub_quick(&r->X, n0, n3, p)) + goto end; + /* X_r = n6^2 - n5^2 * 'n7' */ + + /* 'n9' */ + if (!BN_mod_lshift1_quick(n0, &r->X, p)) + goto end; + if (!BN_mod_sub_quick(n0, n3, n0, p)) + goto end; + /* n9 = n5^2 * 'n7' - 2 * X_r */ + + /* Y_r */ + if (!field_mul(group, n0, n0, n6, ctx)) + goto end; + if (!field_mul(group, n5, n4, n5, ctx)) + goto end; /* now n5 is n5^3 */ + if (!field_mul(group, n1, n2, n5, ctx)) + goto end; + if (!BN_mod_sub_quick(n0, n0, n1, p)) + goto end; + if (BN_is_odd(n0)) + if (!BN_add(n0, n0, p)) + goto end; + /* now 0 <= n0 < 2*p, and n0 is even */ + if (!BN_rshift1(&r->Y, n0)) + goto end; + /* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */ + + ret = 1; end: - if (ctx) /* otherwise we already called BN_CTX_end */ - BN_CTX_end(ctx); - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - return ret; - } - - -int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx) - { - int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); - int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); - const BIGNUM *p; - BN_CTX *new_ctx = NULL; - BIGNUM *n0, *n1, *n2, *n3; - int ret = 0; - - if (EC_POINT_is_at_infinity(group, a)) - { - BN_zero(&r->Z); - r->Z_is_one = 0; - return 1; - } - - field_mul = group->meth->field_mul; - field_sqr = group->meth->field_sqr; - p = &group->field; - - if (ctx == NULL) - { - ctx = new_ctx = BN_CTX_new(); - if (ctx == NULL) - return 0; - } - - BN_CTX_start(ctx); - n0 = BN_CTX_get(ctx); - n1 = BN_CTX_get(ctx); - n2 = BN_CTX_get(ctx); - n3 = BN_CTX_get(ctx); - if (n3 == NULL) goto err; - - /* Note that in this function we must not read components of 'a' - * once we have written the corresponding components of 'r'. - * ('r' might the same as 'a'.) - */ - - /* n1 */ - if (a->Z_is_one) - { - if (!field_sqr(group, n0, &a->X, ctx)) goto err; - if (!BN_mod_lshift1_quick(n1, n0, p)) goto err; - if (!BN_mod_add_quick(n0, n0, n1, p)) goto err; - if (!BN_mod_add_quick(n1, n0, &group->a, p)) goto err; - /* n1 = 3 * X_a^2 + a_curve */ - } - else if (group->a_is_minus3) - { - if (!field_sqr(group, n1, &a->Z, ctx)) goto err; - if (!BN_mod_add_quick(n0, &a->X, n1, p)) goto err; - if (!BN_mod_sub_quick(n2, &a->X, n1, p)) goto err; - if (!field_mul(group, n1, n0, n2, ctx)) goto err; - if (!BN_mod_lshift1_quick(n0, n1, p)) goto err; - if (!BN_mod_add_quick(n1, n0, n1, p)) goto err; - /* n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2) - * = 3 * X_a^2 - 3 * Z_a^4 */ - } - else - { - if (!field_sqr(group, n0, &a->X, ctx)) goto err; - if (!BN_mod_lshift1_quick(n1, n0, p)) goto err; - if (!BN_mod_add_quick(n0, n0, n1, p)) goto err; - if (!field_sqr(group, n1, &a->Z, ctx)) goto err; - if (!field_sqr(group, n1, n1, ctx)) goto err; - if (!field_mul(group, n1, n1, &group->a, ctx)) goto err; - if (!BN_mod_add_quick(n1, n1, n0, p)) goto err; - /* n1 = 3 * X_a^2 + a_curve * Z_a^4 */ - } - - /* Z_r */ - if (a->Z_is_one) - { - if (!BN_copy(n0, &a->Y)) goto err; - } - else - { - if (!field_mul(group, n0, &a->Y, &a->Z, ctx)) goto err; - } - if (!BN_mod_lshift1_quick(&r->Z, n0, p)) goto err; - r->Z_is_one = 0; - /* Z_r = 2 * Y_a * Z_a */ - - /* n2 */ - if (!field_sqr(group, n3, &a->Y, ctx)) goto err; - if (!field_mul(group, n2, &a->X, n3, ctx)) goto err; - if (!BN_mod_lshift_quick(n2, n2, 2, p)) goto err; - /* n2 = 4 * X_a * Y_a^2 */ - - /* X_r */ - if (!BN_mod_lshift1_quick(n0, n2, p)) goto err; - if (!field_sqr(group, &r->X, n1, ctx)) goto err; - if (!BN_mod_sub_quick(&r->X, &r->X, n0, p)) goto err; - /* X_r = n1^2 - 2 * n2 */ - - /* n3 */ - if (!field_sqr(group, n0, n3, ctx)) goto err; - if (!BN_mod_lshift_quick(n3, n0, 3, p)) goto err; - /* n3 = 8 * Y_a^4 */ - - /* Y_r */ - if (!BN_mod_sub_quick(n0, n2, &r->X, p)) goto err; - if (!field_mul(group, n0, n1, n0, ctx)) goto err; - if (!BN_mod_sub_quick(&r->Y, n0, n3, p)) goto err; - /* Y_r = n1 * (n2 - X_r) - n3 */ - - ret = 1; + if (ctx) /* otherwise we already called BN_CTX_end */ + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, + BN_CTX *ctx) +{ + int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, + const BIGNUM *, BN_CTX *); + int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); + const BIGNUM *p; + BN_CTX *new_ctx = NULL; + BIGNUM *n0, *n1, *n2, *n3; + int ret = 0; + + if (EC_POINT_is_at_infinity(group, a)) { + BN_zero(&r->Z); + r->Z_is_one = 0; + return 1; + } + + field_mul = group->meth->field_mul; + field_sqr = group->meth->field_sqr; + p = &group->field; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + n0 = BN_CTX_get(ctx); + n1 = BN_CTX_get(ctx); + n2 = BN_CTX_get(ctx); + n3 = BN_CTX_get(ctx); + if (n3 == NULL) + goto err; + + /* + * Note that in this function we must not read components of 'a' once we + * have written the corresponding components of 'r'. ('r' might the same + * as 'a'.) + */ + + /* n1 */ + if (a->Z_is_one) { + if (!field_sqr(group, n0, &a->X, ctx)) + goto err; + if (!BN_mod_lshift1_quick(n1, n0, p)) + goto err; + if (!BN_mod_add_quick(n0, n0, n1, p)) + goto err; + if (!BN_mod_add_quick(n1, n0, &group->a, p)) + goto err; + /* n1 = 3 * X_a^2 + a_curve */ + } else if (group->a_is_minus3) { + if (!field_sqr(group, n1, &a->Z, ctx)) + goto err; + if (!BN_mod_add_quick(n0, &a->X, n1, p)) + goto err; + if (!BN_mod_sub_quick(n2, &a->X, n1, p)) + goto err; + if (!field_mul(group, n1, n0, n2, ctx)) + goto err; + if (!BN_mod_lshift1_quick(n0, n1, p)) + goto err; + if (!BN_mod_add_quick(n1, n0, n1, p)) + goto err; + /*- + * n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2) + * = 3 * X_a^2 - 3 * Z_a^4 + */ + } else { + if (!field_sqr(group, n0, &a->X, ctx)) + goto err; + if (!BN_mod_lshift1_quick(n1, n0, p)) + goto err; + if (!BN_mod_add_quick(n0, n0, n1, p)) + goto err; + if (!field_sqr(group, n1, &a->Z, ctx)) + goto err; + if (!field_sqr(group, n1, n1, ctx)) + goto err; + if (!field_mul(group, n1, n1, &group->a, ctx)) + goto err; + if (!BN_mod_add_quick(n1, n1, n0, p)) + goto err; + /* n1 = 3 * X_a^2 + a_curve * Z_a^4 */ + } + + /* Z_r */ + if (a->Z_is_one) { + if (!BN_copy(n0, &a->Y)) + goto err; + } else { + if (!field_mul(group, n0, &a->Y, &a->Z, ctx)) + goto err; + } + if (!BN_mod_lshift1_quick(&r->Z, n0, p)) + goto err; + r->Z_is_one = 0; + /* Z_r = 2 * Y_a * Z_a */ + + /* n2 */ + if (!field_sqr(group, n3, &a->Y, ctx)) + goto err; + if (!field_mul(group, n2, &a->X, n3, ctx)) + goto err; + if (!BN_mod_lshift_quick(n2, n2, 2, p)) + goto err; + /* n2 = 4 * X_a * Y_a^2 */ + + /* X_r */ + if (!BN_mod_lshift1_quick(n0, n2, p)) + goto err; + if (!field_sqr(group, &r->X, n1, ctx)) + goto err; + if (!BN_mod_sub_quick(&r->X, &r->X, n0, p)) + goto err; + /* X_r = n1^2 - 2 * n2 */ + + /* n3 */ + if (!field_sqr(group, n0, n3, ctx)) + goto err; + if (!BN_mod_lshift_quick(n3, n0, 3, p)) + goto err; + /* n3 = 8 * Y_a^4 */ + + /* Y_r */ + if (!BN_mod_sub_quick(n0, n2, &r->X, p)) + goto err; + if (!field_mul(group, n0, n1, n0, ctx)) + goto err; + if (!BN_mod_sub_quick(&r->Y, n0, n3, p)) + goto err; + /* Y_r = n1 * (n2 - X_r) - n3 */ + + ret = 1; err: - BN_CTX_end(ctx); - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - return ret; - } - + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; +} int ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) - { - if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y)) - /* point is its own inverse */ - return 1; - - return BN_usub(&point->Y, &group->field, &point->Y); - } +{ + if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y)) + /* point is its own inverse */ + return 1; + return BN_usub(&point->Y, &group->field, &point->Y); +} int ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) - { - return BN_is_zero(&point->Z); - } - - -int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx) - { - int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); - int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); - const BIGNUM *p; - BN_CTX *new_ctx = NULL; - BIGNUM *rh, *tmp, *Z4, *Z6; - int ret = -1; - - if (EC_POINT_is_at_infinity(group, point)) - return 1; - - field_mul = group->meth->field_mul; - field_sqr = group->meth->field_sqr; - p = &group->field; - - if (ctx == NULL) - { - ctx = new_ctx = BN_CTX_new(); - if (ctx == NULL) - return -1; - } - - BN_CTX_start(ctx); - rh = BN_CTX_get(ctx); - tmp = BN_CTX_get(ctx); - Z4 = BN_CTX_get(ctx); - Z6 = BN_CTX_get(ctx); - if (Z6 == NULL) goto err; - - /* We have a curve defined by a Weierstrass equation - * y^2 = x^3 + a*x + b. - * The point to consider is given in Jacobian projective coordinates - * where (X, Y, Z) represents (x, y) = (X/Z^2, Y/Z^3). - * Substituting this and multiplying by Z^6 transforms the above equation into - * Y^2 = X^3 + a*X*Z^4 + b*Z^6. - * To test this, we add up the right-hand side in 'rh'. - */ - - /* rh := X^2 */ - if (!field_sqr(group, rh, &point->X, ctx)) goto err; - - if (!point->Z_is_one) - { - 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*Z^4)*X */ - if (group->a_is_minus3) - { - 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, 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, 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 (!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, tmp, &point->Y, ctx)) goto err; - - ret = (0 == BN_ucmp(tmp, rh)); +{ + return BN_is_zero(&point->Z); +} + +int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, + BN_CTX *ctx) +{ + int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, + const BIGNUM *, BN_CTX *); + int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); + const BIGNUM *p; + BN_CTX *new_ctx = NULL; + BIGNUM *rh, *tmp, *Z4, *Z6; + int ret = -1; + + if (EC_POINT_is_at_infinity(group, point)) + return 1; + + field_mul = group->meth->field_mul; + field_sqr = group->meth->field_sqr; + p = &group->field; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return -1; + } + + BN_CTX_start(ctx); + rh = BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + Z4 = BN_CTX_get(ctx); + Z6 = BN_CTX_get(ctx); + if (Z6 == NULL) + goto err; + + /*- + * We have a curve defined by a Weierstrass equation + * y^2 = x^3 + a*x + b. + * The point to consider is given in Jacobian projective coordinates + * where (X, Y, Z) represents (x, y) = (X/Z^2, Y/Z^3). + * Substituting this and multiplying by Z^6 transforms the above equation into + * Y^2 = X^3 + a*X*Z^4 + b*Z^6. + * To test this, we add up the right-hand side in 'rh'. + */ + + /* rh := X^2 */ + if (!field_sqr(group, rh, &point->X, ctx)) + goto err; + + if (!point->Z_is_one) { + 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*Z^4)*X */ + if (group->a_is_minus3) { + 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, 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, 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 (!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, tmp, &point->Y, ctx)) + goto err; + + ret = (0 == BN_ucmp(tmp, rh)); err: - BN_CTX_end(ctx); - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - return ret; - } - - -int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) - { - /* return values: - * -1 error - * 0 equal (in affine coordinates) - * 1 not equal - */ - - int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); - int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); - BN_CTX *new_ctx = NULL; - BIGNUM *tmp1, *tmp2, *Za23, *Zb23; - const BIGNUM *tmp1_, *tmp2_; - int ret = -1; - - if (EC_POINT_is_at_infinity(group, a)) - { - 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) - { - return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1; - } - - field_mul = group->meth->field_mul; - field_sqr = group->meth->field_sqr; - - if (ctx == NULL) - { - ctx = new_ctx = BN_CTX_new(); - if (ctx == NULL) - return -1; - } - - BN_CTX_start(ctx); - tmp1 = BN_CTX_get(ctx); - tmp2 = BN_CTX_get(ctx); - Za23 = BN_CTX_get(ctx); - Zb23 = BN_CTX_get(ctx); - if (Zb23 == NULL) goto end; - - /* We have to decide whether - * (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2, Y_b/Z_b^3), - * or equivalently, whether - * (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3). - */ - - if (!b->Z_is_one) - { - if (!field_sqr(group, Zb23, &b->Z, ctx)) goto end; - if (!field_mul(group, tmp1, &a->X, Zb23, ctx)) goto end; - tmp1_ = tmp1; - } - else - tmp1_ = &a->X; - if (!a->Z_is_one) - { - if (!field_sqr(group, Za23, &a->Z, ctx)) goto end; - if (!field_mul(group, tmp2, &b->X, Za23, ctx)) goto end; - tmp2_ = tmp2; - } - else - tmp2_ = &b->X; - - /* compare X_a*Z_b^2 with X_b*Z_a^2 */ - if (BN_cmp(tmp1_, tmp2_) != 0) - { - ret = 1; /* points differ */ - goto end; - } - - - if (!b->Z_is_one) - { - if (!field_mul(group, Zb23, Zb23, &b->Z, ctx)) goto end; - if (!field_mul(group, tmp1, &a->Y, Zb23, ctx)) goto end; - /* tmp1_ = tmp1 */ - } - else - tmp1_ = &a->Y; - if (!a->Z_is_one) - { - if (!field_mul(group, Za23, Za23, &a->Z, ctx)) goto end; - if (!field_mul(group, tmp2, &b->Y, Za23, ctx)) goto end; - /* tmp2_ = tmp2 */ - } - else - tmp2_ = &b->Y; - - /* compare Y_a*Z_b^3 with Y_b*Z_a^3 */ - if (BN_cmp(tmp1_, tmp2_) != 0) - { - ret = 1; /* points differ */ - goto end; - } - - /* points are equal */ - ret = 0; + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, + const EC_POINT *b, BN_CTX *ctx) +{ + /*- + * return values: + * -1 error + * 0 equal (in affine coordinates) + * 1 not equal + */ + + int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, + const BIGNUM *, BN_CTX *); + int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); + BN_CTX *new_ctx = NULL; + BIGNUM *tmp1, *tmp2, *Za23, *Zb23; + const BIGNUM *tmp1_, *tmp2_; + int ret = -1; + + if (EC_POINT_is_at_infinity(group, a)) { + 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) { + return ((BN_cmp(&a->X, &b->X) == 0) + && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1; + } + + field_mul = group->meth->field_mul; + field_sqr = group->meth->field_sqr; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return -1; + } + + BN_CTX_start(ctx); + tmp1 = BN_CTX_get(ctx); + tmp2 = BN_CTX_get(ctx); + Za23 = BN_CTX_get(ctx); + Zb23 = BN_CTX_get(ctx); + if (Zb23 == NULL) + goto end; + + /*- + * We have to decide whether + * (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2, Y_b/Z_b^3), + * or equivalently, whether + * (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3). + */ + + if (!b->Z_is_one) { + if (!field_sqr(group, Zb23, &b->Z, ctx)) + goto end; + if (!field_mul(group, tmp1, &a->X, Zb23, ctx)) + goto end; + tmp1_ = tmp1; + } else + tmp1_ = &a->X; + if (!a->Z_is_one) { + if (!field_sqr(group, Za23, &a->Z, ctx)) + goto end; + if (!field_mul(group, tmp2, &b->X, Za23, ctx)) + goto end; + tmp2_ = tmp2; + } else + tmp2_ = &b->X; + + /* compare X_a*Z_b^2 with X_b*Z_a^2 */ + if (BN_cmp(tmp1_, tmp2_) != 0) { + ret = 1; /* points differ */ + goto end; + } + + if (!b->Z_is_one) { + if (!field_mul(group, Zb23, Zb23, &b->Z, ctx)) + goto end; + if (!field_mul(group, tmp1, &a->Y, Zb23, ctx)) + goto end; + /* tmp1_ = tmp1 */ + } else + tmp1_ = &a->Y; + if (!a->Z_is_one) { + if (!field_mul(group, Za23, Za23, &a->Z, ctx)) + goto end; + if (!field_mul(group, tmp2, &b->Y, Za23, ctx)) + goto end; + /* tmp2_ = tmp2 */ + } else + tmp2_ = &b->Y; + + /* compare Y_a*Z_b^3 with Y_b*Z_a^3 */ + if (BN_cmp(tmp1_, tmp2_) != 0) { + ret = 1; /* points differ */ + goto end; + } + + /* points are equal */ + ret = 0; end: - BN_CTX_end(ctx); - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - return ret; - } - - -int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) - { - BN_CTX *new_ctx = NULL; - BIGNUM *x, *y; - int ret = 0; - - if (point->Z_is_one || EC_POINT_is_at_infinity(group, point)) - return 1; - - 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 (!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_INTERNAL_ERROR); - goto err; - } - - ret = 1; + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, + BN_CTX *ctx) +{ + BN_CTX *new_ctx = NULL; + BIGNUM *x, *y; + int ret = 0; + + if (point->Z_is_one || EC_POINT_is_at_infinity(group, point)) + return 1; + + 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 (!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_INTERNAL_ERROR); + goto err; + } + + ret = 1; err: - BN_CTX_end(ctx); - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - return ret; - } - - -int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx) - { - BN_CTX *new_ctx = NULL; - BIGNUM *tmp, *tmp_Z; - BIGNUM **prod_Z = NULL; - size_t i; - int ret = 0; - - if (num == 0) - return 1; - - if (ctx == NULL) - { - ctx = new_ctx = BN_CTX_new(); - if (ctx == NULL) - return 0; - } - - BN_CTX_start(ctx); - tmp = BN_CTX_get(ctx); - tmp_Z = BN_CTX_get(ctx); - if (tmp == NULL || tmp_Z == NULL) goto err; - - prod_Z = OPENSSL_malloc(num * sizeof prod_Z[0]); - if (prod_Z == NULL) goto err; - for (i = 0; i < num; i++) - { - prod_Z[i] = BN_new(); - if (prod_Z[i] == NULL) goto err; - } - - /* Set each prod_Z[i] to the product of points[0]->Z .. points[i]->Z, - * skipping any zero-valued inputs (pretend that they're 1). */ - - if (!BN_is_zero(&points[0]->Z)) - { - if (!BN_copy(prod_Z[0], &points[0]->Z)) goto err; - } - else - { - if (group->meth->field_set_to_one != 0) - { - if (!group->meth->field_set_to_one(group, prod_Z[0], ctx)) goto err; - } - else - { - if (!BN_one(prod_Z[0])) goto err; - } - } - - for (i = 1; i < num; i++) - { - if (!BN_is_zero(&points[i]->Z)) - { - if (!group->meth->field_mul(group, prod_Z[i], prod_Z[i - 1], &points[i]->Z, ctx)) goto err; - } - else - { - if (!BN_copy(prod_Z[i], prod_Z[i - 1])) goto err; - } - } - - /* Now use a single explicit inversion to replace every - * non-zero points[i]->Z by its inverse. */ - - if (!BN_mod_inverse(tmp, prod_Z[num - 1], &group->field, ctx)) - { - ECerr(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, ERR_R_BN_LIB); - goto err; - } - if (group->meth->field_encode != 0) - { - /* In the Montgomery case, we just turned R*H (representing H) - * into 1/(R*H), but we need R*(1/H) (representing 1/H); - * i.e. we need to multiply by the Montgomery factor twice. */ - if (!group->meth->field_encode(group, tmp, tmp, ctx)) goto err; - if (!group->meth->field_encode(group, tmp, tmp, ctx)) goto err; - } - - for (i = num - 1; i > 0; --i) - { - /* Loop invariant: tmp is the product of the inverses of - * points[0]->Z .. points[i]->Z (zero-valued inputs skipped). */ - if (!BN_is_zero(&points[i]->Z)) - { - /* Set tmp_Z to the inverse of points[i]->Z (as product - * of Z inverses 0 .. i, Z values 0 .. i - 1). */ - if (!group->meth->field_mul(group, tmp_Z, prod_Z[i - 1], tmp, ctx)) goto err; - /* Update tmp to satisfy the loop invariant for i - 1. */ - if (!group->meth->field_mul(group, tmp, tmp, &points[i]->Z, ctx)) goto err; - /* Replace points[i]->Z by its inverse. */ - if (!BN_copy(&points[i]->Z, tmp_Z)) goto err; - } - } - - if (!BN_is_zero(&points[0]->Z)) - { - /* Replace points[0]->Z by its inverse. */ - if (!BN_copy(&points[0]->Z, tmp)) goto err; - } - - /* Finally, fix up the X and Y coordinates for all points. */ - - for (i = 0; i < num; i++) - { - EC_POINT *p = points[i]; - - if (!BN_is_zero(&p->Z)) - { - /* turn (X, Y, 1/Z) into (X/Z^2, Y/Z^3, 1) */ - - if (!group->meth->field_sqr(group, tmp, &p->Z, ctx)) goto err; - if (!group->meth->field_mul(group, &p->X, &p->X, tmp, ctx)) goto err; - - if (!group->meth->field_mul(group, tmp, tmp, &p->Z, ctx)) goto err; - if (!group->meth->field_mul(group, &p->Y, &p->Y, tmp, ctx)) goto err; - - if (group->meth->field_set_to_one != 0) - { - if (!group->meth->field_set_to_one(group, &p->Z, ctx)) goto err; - } - else - { - if (!BN_one(&p->Z)) goto err; - } - p->Z_is_one = 1; - } - } - - ret = 1; + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + return ret; +} + +int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, + EC_POINT *points[], BN_CTX *ctx) +{ + BN_CTX *new_ctx = NULL; + BIGNUM *tmp, *tmp_Z; + BIGNUM **prod_Z = NULL; + size_t i; + int ret = 0; + + if (num == 0) + return 1; + + if (ctx == NULL) { + ctx = new_ctx = BN_CTX_new(); + if (ctx == NULL) + return 0; + } + + BN_CTX_start(ctx); + tmp = BN_CTX_get(ctx); + tmp_Z = BN_CTX_get(ctx); + if (tmp == NULL || tmp_Z == NULL) + goto err; + + prod_Z = OPENSSL_malloc(num * sizeof prod_Z[0]); + if (prod_Z == NULL) + goto err; + for (i = 0; i < num; i++) { + prod_Z[i] = BN_new(); + if (prod_Z[i] == NULL) + goto err; + } + + /* + * Set each prod_Z[i] to the product of points[0]->Z .. points[i]->Z, + * skipping any zero-valued inputs (pretend that they're 1). + */ + + if (!BN_is_zero(&points[0]->Z)) { + if (!BN_copy(prod_Z[0], &points[0]->Z)) + goto err; + } else { + if (group->meth->field_set_to_one != 0) { + if (!group->meth->field_set_to_one(group, prod_Z[0], ctx)) + goto err; + } else { + if (!BN_one(prod_Z[0])) + goto err; + } + } + + for (i = 1; i < num; i++) { + if (!BN_is_zero(&points[i]->Z)) { + if (!group->meth->field_mul(group, prod_Z[i], prod_Z[i - 1], + &points[i]->Z, ctx)) + goto err; + } else { + if (!BN_copy(prod_Z[i], prod_Z[i - 1])) + goto err; + } + } + + /* + * Now use a single explicit inversion to replace every non-zero + * points[i]->Z by its inverse. + */ + + if (!BN_mod_inverse(tmp, prod_Z[num - 1], &group->field, ctx)) { + ECerr(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, ERR_R_BN_LIB); + goto err; + } + if (group->meth->field_encode != 0) { + /* + * In the Montgomery case, we just turned R*H (representing H) into + * 1/(R*H), but we need R*(1/H) (representing 1/H); i.e. we need to + * multiply by the Montgomery factor twice. + */ + if (!group->meth->field_encode(group, tmp, tmp, ctx)) + goto err; + if (!group->meth->field_encode(group, tmp, tmp, ctx)) + goto err; + } + + for (i = num - 1; i > 0; --i) { + /* + * Loop invariant: tmp is the product of the inverses of points[0]->Z + * .. points[i]->Z (zero-valued inputs skipped). + */ + if (!BN_is_zero(&points[i]->Z)) { + /* + * Set tmp_Z to the inverse of points[i]->Z (as product of Z + * inverses 0 .. i, Z values 0 .. i - 1). + */ + if (!group-> + meth->field_mul(group, tmp_Z, prod_Z[i - 1], tmp, ctx)) + goto err; + /* + * Update tmp to satisfy the loop invariant for i - 1. + */ + if (!group->meth->field_mul(group, tmp, tmp, &points[i]->Z, ctx)) + goto err; + /* Replace points[i]->Z by its inverse. */ + if (!BN_copy(&points[i]->Z, tmp_Z)) + goto err; + } + } + + if (!BN_is_zero(&points[0]->Z)) { + /* Replace points[0]->Z by its inverse. */ + if (!BN_copy(&points[0]->Z, tmp)) + goto err; + } + + /* Finally, fix up the X and Y coordinates for all points. */ + + for (i = 0; i < num; i++) { + EC_POINT *p = points[i]; + + if (!BN_is_zero(&p->Z)) { + /* turn (X, Y, 1/Z) into (X/Z^2, Y/Z^3, 1) */ + + if (!group->meth->field_sqr(group, tmp, &p->Z, ctx)) + goto err; + if (!group->meth->field_mul(group, &p->X, &p->X, tmp, ctx)) + goto err; + + if (!group->meth->field_mul(group, tmp, tmp, &p->Z, ctx)) + goto err; + if (!group->meth->field_mul(group, &p->Y, &p->Y, tmp, ctx)) + goto err; + + if (group->meth->field_set_to_one != 0) { + if (!group->meth->field_set_to_one(group, &p->Z, ctx)) + goto err; + } else { + if (!BN_one(&p->Z)) + goto err; + } + p->Z_is_one = 1; + } + } + + ret = 1; err: - BN_CTX_end(ctx); - if (new_ctx != NULL) - BN_CTX_free(new_ctx); - if (prod_Z != NULL) - { - for (i = 0; i < num; i++) - { - if (prod_Z[i] == NULL) break; - BN_clear_free(prod_Z[i]); - } - OPENSSL_free(prod_Z); - } - return ret; - } - - -int ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) - { - return BN_mod_mul(r, a, b, &group->field, ctx); - } - - -int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) - { - return BN_mod_sqr(r, a, &group->field, ctx); - } + BN_CTX_end(ctx); + if (new_ctx != NULL) + BN_CTX_free(new_ctx); + if (prod_Z != NULL) { + for (i = 0; i < num; i++) { + if (prod_Z[i] == NULL) + break; + BN_clear_free(prod_Z[i]); + } + OPENSSL_free(prod_Z); + } + return ret; +} + +int ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx) +{ + return BN_mod_mul(r, a, b, &group->field, ctx); +} + +int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, + BN_CTX *ctx) +{ + return BN_mod_sqr(r, a, &group->field, ctx); +} diff --git a/openssl/crypto/ec/ectest.c b/openssl/crypto/ec/ectest.c index 8e4154d86..a18b32761 100644 --- a/openssl/crypto/ec/ectest.c +++ b/openssl/crypto/ec/ectest.c @@ -10,7 +10,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in @@ -58,13 +58,13 @@ /* ==================================================================== * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. * - * Portions of the attached software ("Contribution") are developed by + * Portions of the attached software ("Contribution") are developed by * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. * * The Contribution is licensed pursuant to the OpenSSL open source * license provided above. * - * The elliptic curve binary polynomial software is originally written by + * The elliptic curve binary polynomial software is originally written by * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories. * */ @@ -72,1454 +72,1790 @@ #include <stdio.h> #include <stdlib.h> #ifdef FLAT_INC -#include "e_os.h" +# include "e_os.h" #else -#include "../e_os.h" +# include "../e_os.h" #endif #include <string.h> #include <time.h> - #ifdef OPENSSL_NO_EC -int main(int argc, char * argv[]) { puts("Elliptic curves are disabled."); return 0; } +int main(int argc, char *argv[]) +{ + puts("Elliptic curves are disabled."); + return 0; +} #else - -#include <openssl/ec.h> -#ifndef OPENSSL_NO_ENGINE -#include <openssl/engine.h> -#endif -#include <openssl/err.h> -#include <openssl/obj_mac.h> -#include <openssl/objects.h> -#include <openssl/rand.h> -#include <openssl/bn.h> -#include <openssl/opensslconf.h> - -#if defined(_MSC_VER) && defined(_MIPS_) && (_MSC_VER/100==12) +# include <openssl/ec.h> +# ifndef OPENSSL_NO_ENGINE +# include <openssl/engine.h> +# endif +# include <openssl/err.h> +# include <openssl/obj_mac.h> +# include <openssl/objects.h> +# include <openssl/rand.h> +# include <openssl/bn.h> +# include <openssl/opensslconf.h> + +# if defined(_MSC_VER) && defined(_MIPS_) && (_MSC_VER/100==12) /* suppress "too big too optimize" warning */ -#pragma warning(disable:4959) -#endif - -#define ABORT do { \ - fflush(stdout); \ - fprintf(stderr, "%s:%d: ABORT\n", __FILE__, __LINE__); \ - ERR_print_errors_fp(stderr); \ - EXIT(1); \ +# pragma warning(disable:4959) +# endif + +# define ABORT do { \ + fflush(stdout); \ + fprintf(stderr, "%s:%d: ABORT\n", __FILE__, __LINE__); \ + ERR_print_errors_fp(stderr); \ + EXIT(1); \ } while (0) -#define TIMING_BASE_PT 0 -#define TIMING_RAND_PT 1 -#define TIMING_SIMUL 2 +# define TIMING_BASE_PT 0 +# define TIMING_RAND_PT 1 +# define TIMING_SIMUL 2 -#if 0 +# if 0 static void timings(EC_GROUP *group, int type, BN_CTX *ctx) - { - clock_t clck; - int i, j; - BIGNUM *s; - BIGNUM *r[10], *r0[10]; - EC_POINT *P; - - s = BN_new(); - if (s == NULL) ABORT; - - fprintf(stdout, "Timings for %d-bit field, ", EC_GROUP_get_degree(group)); - if (!EC_GROUP_get_order(group, s, ctx)) ABORT; - fprintf(stdout, "%d-bit scalars ", (int)BN_num_bits(s)); - fflush(stdout); - - P = EC_POINT_new(group); - if (P == NULL) ABORT; - EC_POINT_copy(P, EC_GROUP_get0_generator(group)); - - for (i = 0; i < 10; i++) - { - if ((r[i] = BN_new()) == NULL) ABORT; - if (!BN_pseudo_rand(r[i], BN_num_bits(s), 0, 0)) ABORT; - if (type != TIMING_BASE_PT) - { - if ((r0[i] = BN_new()) == NULL) ABORT; - if (!BN_pseudo_rand(r0[i], BN_num_bits(s), 0, 0)) ABORT; - } - } - - clck = clock(); - for (i = 0; i < 10; i++) - { - for (j = 0; j < 10; j++) - { - if (!EC_POINT_mul(group, P, (type != TIMING_RAND_PT) ? r[i] : NULL, - (type != TIMING_BASE_PT) ? P : NULL, (type != TIMING_BASE_PT) ? r0[i] : NULL, ctx)) ABORT; - } - } - clck = clock() - clck; - - fprintf(stdout, "\n"); - -#ifdef CLOCKS_PER_SEC - /* "To determine the time in seconds, the value returned - * by the clock function should be divided by the value - * of the macro CLOCKS_PER_SEC." - * -- ISO/IEC 9899 */ -# define UNIT "s" -#else - /* "`CLOCKS_PER_SEC' undeclared (first use this function)" - * -- cc on NeXTstep/OpenStep */ -# define UNIT "units" -# define CLOCKS_PER_SEC 1 -#endif - - if (type == TIMING_BASE_PT) { - fprintf(stdout, "%i %s in %.2f " UNIT "\n", i*j, - "base point multiplications", (double)clck/CLOCKS_PER_SEC); - } else if (type == TIMING_RAND_PT) { - fprintf(stdout, "%i %s in %.2f " UNIT "\n", i*j, - "random point multiplications", (double)clck/CLOCKS_PER_SEC); - } else if (type == TIMING_SIMUL) { - fprintf(stdout, "%i %s in %.2f " UNIT "\n", i*j, - "s*P+t*Q operations", (double)clck/CLOCKS_PER_SEC); - } - fprintf(stdout, "average: %.4f " UNIT "\n", (double)clck/(CLOCKS_PER_SEC*i*j)); - - EC_POINT_free(P); - BN_free(s); - for (i = 0; i < 10; i++) - { - BN_free(r[i]); - if (type != TIMING_BASE_PT) BN_free(r0[i]); - } - } -#endif +{ + clock_t clck; + int i, j; + BIGNUM *s; + BIGNUM *r[10], *r0[10]; + EC_POINT *P; + + s = BN_new(); + if (s == NULL) + ABORT; + + fprintf(stdout, "Timings for %d-bit field, ", EC_GROUP_get_degree(group)); + if (!EC_GROUP_get_order(group, s, ctx)) + ABORT; + fprintf(stdout, "%d-bit scalars ", (int)BN_num_bits(s)); + fflush(stdout); + + P = EC_POINT_new(group); + if (P == NULL) + ABORT; + EC_POINT_copy(P, EC_GROUP_get0_generator(group)); + + for (i = 0; i < 10; i++) { + if ((r[i] = BN_new()) == NULL) + ABORT; + if (!BN_pseudo_rand(r[i], BN_num_bits(s), 0, 0)) + ABORT; + if (type != TIMING_BASE_PT) { + if ((r0[i] = BN_new()) == NULL) + ABORT; + if (!BN_pseudo_rand(r0[i], BN_num_bits(s), 0, 0)) + ABORT; + } + } + + clck = clock(); + for (i = 0; i < 10; i++) { + for (j = 0; j < 10; j++) { + if (!EC_POINT_mul + (group, P, (type != TIMING_RAND_PT) ? r[i] : NULL, + (type != TIMING_BASE_PT) ? P : NULL, + (type != TIMING_BASE_PT) ? r0[i] : NULL, ctx)) + ABORT; + } + } + clck = clock() - clck; + + fprintf(stdout, "\n"); + +# ifdef CLOCKS_PER_SEC + /* + * "To determine the time in seconds, the value returned by the clock + * function should be divided by the value of the macro CLOCKS_PER_SEC." + * -- ISO/IEC 9899 + */ +# define UNIT "s" +# else + /* + * "`CLOCKS_PER_SEC' undeclared (first use this function)" -- cc on + * NeXTstep/OpenStep + */ +# define UNIT "units" +# define CLOCKS_PER_SEC 1 +# endif + + if (type == TIMING_BASE_PT) { + fprintf(stdout, "%i %s in %.2f " UNIT "\n", i * j, + "base point multiplications", (double)clck / CLOCKS_PER_SEC); + } else if (type == TIMING_RAND_PT) { + fprintf(stdout, "%i %s in %.2f " UNIT "\n", i * j, + "random point multiplications", + (double)clck / CLOCKS_PER_SEC); + } else if (type == TIMING_SIMUL) { + fprintf(stdout, "%i %s in %.2f " UNIT "\n", i * j, + "s*P+t*Q operations", (double)clck / CLOCKS_PER_SEC); + } + fprintf(stdout, "average: %.4f " UNIT "\n", + (double)clck / (CLOCKS_PER_SEC * i * j)); + + EC_POINT_free(P); + BN_free(s); + for (i = 0; i < 10; i++) { + BN_free(r[i]); + if (type != TIMING_BASE_PT) + BN_free(r0[i]); + } +} +# endif /* test multiplication with group order, long and negative scalars */ static void group_order_tests(EC_GROUP *group) - { - BIGNUM *n1, *n2, *order; - EC_POINT *P = EC_POINT_new(group); - EC_POINT *Q = EC_POINT_new(group); - BN_CTX *ctx = BN_CTX_new(); - int i; - - n1 = BN_new(); n2 = BN_new(); order = BN_new(); - fprintf(stdout, "verify group order ..."); - fflush(stdout); - if (!EC_GROUP_get_order(group, order, ctx)) ABORT; - if (!EC_POINT_mul(group, Q, order, NULL, NULL, ctx)) ABORT; - if (!EC_POINT_is_at_infinity(group, Q)) ABORT; - fprintf(stdout, "."); - fflush(stdout); - if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; - if (!EC_POINT_mul(group, Q, order, NULL, NULL, ctx)) ABORT; - if (!EC_POINT_is_at_infinity(group, Q)) ABORT; - fprintf(stdout, " ok\n"); - fprintf(stdout, "long/negative scalar tests "); - for (i = 1; i <= 2; i++) - { - const BIGNUM *scalars[6]; - const EC_POINT *points[6]; - - fprintf(stdout, i == 1 ? - "allowing precomputation ... " : - "without precomputation ... "); - if (!BN_set_word(n1, i)) ABORT; - /* If i == 1, P will be the predefined generator for which - * EC_GROUP_precompute_mult has set up precomputation. */ - if (!EC_POINT_mul(group, P, n1, NULL, NULL, ctx)) ABORT; - - if (!BN_one(n1)) ABORT; - /* n1 = 1 - order */ - if (!BN_sub(n1, n1, order)) ABORT; - if (!EC_POINT_mul(group, Q, NULL, P, n1, ctx)) ABORT; - if (0 != EC_POINT_cmp(group, Q, P, ctx)) ABORT; - - /* n2 = 1 + order */ - if (!BN_add(n2, order, BN_value_one())) ABORT; - if (!EC_POINT_mul(group, Q, NULL, P, n2, ctx)) ABORT; - if (0 != EC_POINT_cmp(group, Q, P, ctx)) ABORT; - - /* n2 = (1 - order) * (1 + order) = 1 - order^2 */ - if (!BN_mul(n2, n1, n2, ctx)) ABORT; - if (!EC_POINT_mul(group, Q, NULL, P, n2, ctx)) ABORT; - if (0 != EC_POINT_cmp(group, Q, P, ctx)) ABORT; - - /* n2 = order^2 - 1 */ - BN_set_negative(n2, 0); - if (!EC_POINT_mul(group, Q, NULL, P, n2, ctx)) ABORT; - /* Add P to verify the result. */ - if (!EC_POINT_add(group, Q, Q, P, ctx)) ABORT; - if (!EC_POINT_is_at_infinity(group, Q)) ABORT; - - /* Exercise EC_POINTs_mul, including corner cases. */ - if (EC_POINT_is_at_infinity(group, P)) ABORT; - scalars[0] = n1; points[0] = Q; /* => infinity */ - scalars[1] = n2; points[1] = P; /* => -P */ - scalars[2] = n1; points[2] = Q; /* => infinity */ - scalars[3] = n2; points[3] = Q; /* => infinity */ - scalars[4] = n1; points[4] = P; /* => P */ - scalars[5] = n2; points[5] = Q; /* => infinity */ - if (!EC_POINTs_mul(group, P, NULL, 6, points, scalars, ctx)) ABORT; - if (!EC_POINT_is_at_infinity(group, P)) ABORT; - } - fprintf(stdout, "ok\n"); - - EC_POINT_free(P); - EC_POINT_free(Q); - BN_free(n1); - BN_free(n2); - BN_free(order); - BN_CTX_free(ctx); - } +{ + BIGNUM *n1, *n2, *order; + EC_POINT *P = EC_POINT_new(group); + EC_POINT *Q = EC_POINT_new(group); + BN_CTX *ctx = BN_CTX_new(); + int i; + + n1 = BN_new(); + n2 = BN_new(); + order = BN_new(); + fprintf(stdout, "verify group order ..."); + fflush(stdout); + if (!EC_GROUP_get_order(group, order, ctx)) + ABORT; + if (!EC_POINT_mul(group, Q, order, NULL, NULL, ctx)) + ABORT; + if (!EC_POINT_is_at_infinity(group, Q)) + ABORT; + fprintf(stdout, "."); + fflush(stdout); + if (!EC_GROUP_precompute_mult(group, ctx)) + ABORT; + if (!EC_POINT_mul(group, Q, order, NULL, NULL, ctx)) + ABORT; + if (!EC_POINT_is_at_infinity(group, Q)) + ABORT; + fprintf(stdout, " ok\n"); + fprintf(stdout, "long/negative scalar tests "); + for (i = 1; i <= 2; i++) { + const BIGNUM *scalars[6]; + const EC_POINT *points[6]; + + fprintf(stdout, i == 1 ? + "allowing precomputation ... " : + "without precomputation ... "); + if (!BN_set_word(n1, i)) + ABORT; + /* + * If i == 1, P will be the predefined generator for which + * EC_GROUP_precompute_mult has set up precomputation. + */ + if (!EC_POINT_mul(group, P, n1, NULL, NULL, ctx)) + ABORT; + + if (!BN_one(n1)) + ABORT; + /* n1 = 1 - order */ + if (!BN_sub(n1, n1, order)) + ABORT; + if (!EC_POINT_mul(group, Q, NULL, P, n1, ctx)) + ABORT; + if (0 != EC_POINT_cmp(group, Q, P, ctx)) + ABORT; + + /* n2 = 1 + order */ + if (!BN_add(n2, order, BN_value_one())) + ABORT; + if (!EC_POINT_mul(group, Q, NULL, P, n2, ctx)) + ABORT; + if (0 != EC_POINT_cmp(group, Q, P, ctx)) + ABORT; + + /* n2 = (1 - order) * (1 + order) = 1 - order^2 */ + if (!BN_mul(n2, n1, n2, ctx)) + ABORT; + if (!EC_POINT_mul(group, Q, NULL, P, n2, ctx)) + ABORT; + if (0 != EC_POINT_cmp(group, Q, P, ctx)) + ABORT; + + /* n2 = order^2 - 1 */ + BN_set_negative(n2, 0); + if (!EC_POINT_mul(group, Q, NULL, P, n2, ctx)) + ABORT; + /* Add P to verify the result. */ + if (!EC_POINT_add(group, Q, Q, P, ctx)) + ABORT; + if (!EC_POINT_is_at_infinity(group, Q)) + ABORT; + + /* Exercise EC_POINTs_mul, including corner cases. */ + if (EC_POINT_is_at_infinity(group, P)) + ABORT; + scalars[0] = n1; + points[0] = Q; /* => infinity */ + scalars[1] = n2; + points[1] = P; /* => -P */ + scalars[2] = n1; + points[2] = Q; /* => infinity */ + scalars[3] = n2; + points[3] = Q; /* => infinity */ + scalars[4] = n1; + points[4] = P; /* => P */ + scalars[5] = n2; + points[5] = Q; /* => infinity */ + if (!EC_POINTs_mul(group, P, NULL, 6, points, scalars, ctx)) + ABORT; + if (!EC_POINT_is_at_infinity(group, P)) + ABORT; + } + fprintf(stdout, "ok\n"); + + EC_POINT_free(P); + EC_POINT_free(Q); + BN_free(n1); + BN_free(n2); + BN_free(order); + BN_CTX_free(ctx); +} static void prime_field_tests(void) - { - BN_CTX *ctx = NULL; - BIGNUM *p, *a, *b; - EC_GROUP *group; - EC_GROUP *P_160 = NULL, *P_192 = NULL, *P_224 = NULL, *P_256 = NULL, *P_384 = NULL, *P_521 = NULL; - EC_POINT *P, *Q, *R; - BIGNUM *x, *y, *z; - unsigned char buf[100]; - size_t i, len; - int k; - -#if 1 /* optional */ - ctx = BN_CTX_new(); - if (!ctx) ABORT; -#endif - - p = BN_new(); - a = BN_new(); - b = BN_new(); - if (!p || !a || !b) ABORT; - - if (!BN_hex2bn(&p, "17")) ABORT; - if (!BN_hex2bn(&a, "1")) ABORT; - if (!BN_hex2bn(&b, "1")) ABORT; - - group = EC_GROUP_new(EC_GFp_mont_method()); /* applications should use EC_GROUP_new_curve_GFp - * so that the library gets to choose the EC_METHOD */ - if (!group) ABORT; - - if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; - - { - EC_GROUP *tmp; - tmp = EC_GROUP_new(EC_GROUP_method_of(group)); - if (!tmp) ABORT; - if (!EC_GROUP_copy(tmp, group)) ABORT; - EC_GROUP_free(group); - group = tmp; - } - - if (!EC_GROUP_get_curve_GFp(group, p, a, b, ctx)) ABORT; - - fprintf(stdout, "Curve defined by Weierstrass equation\n y^2 = x^3 + a*x + b (mod 0x"); - BN_print_fp(stdout, p); - fprintf(stdout, ")\n a = 0x"); - BN_print_fp(stdout, a); - fprintf(stdout, "\n b = 0x"); - BN_print_fp(stdout, b); - fprintf(stdout, "\n"); - - P = EC_POINT_new(group); - Q = EC_POINT_new(group); - R = EC_POINT_new(group); - if (!P || !Q || !R) ABORT; - - if (!EC_POINT_set_to_infinity(group, P)) ABORT; - if (!EC_POINT_is_at_infinity(group, P)) ABORT; - - buf[0] = 0; - if (!EC_POINT_oct2point(group, Q, buf, 1, ctx)) ABORT; - - if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT; - if (!EC_POINT_is_at_infinity(group, P)) ABORT; - - x = BN_new(); - y = BN_new(); - z = BN_new(); - if (!x || !y || !z) ABORT; - - if (!BN_hex2bn(&x, "D")) ABORT; - if (!EC_POINT_set_compressed_coordinates_GFp(group, Q, x, 1, ctx)) ABORT; - if (!EC_POINT_is_on_curve(group, Q, ctx)) - { - if (!EC_POINT_get_affine_coordinates_GFp(group, Q, x, y, ctx)) ABORT; - fprintf(stderr, "Point is not on curve: x = 0x"); - BN_print_fp(stderr, x); - fprintf(stderr, ", y = 0x"); - BN_print_fp(stderr, y); - fprintf(stderr, "\n"); - ABORT; - } - - fprintf(stdout, "A cyclic subgroup:\n"); - k = 100; - do - { - if (k-- == 0) ABORT; - - if (EC_POINT_is_at_infinity(group, P)) - fprintf(stdout, " point at infinity\n"); - else - { - if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; - - fprintf(stdout, " x = 0x"); - BN_print_fp(stdout, x); - fprintf(stdout, ", y = 0x"); - BN_print_fp(stdout, y); - fprintf(stdout, "\n"); - } - - if (!EC_POINT_copy(R, P)) ABORT; - if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT; - -#if 0 /* optional */ - { - EC_POINT *points[3]; - - points[0] = R; - points[1] = Q; - points[2] = P; - if (!EC_POINTs_make_affine(group, 2, points, ctx)) ABORT; - } -#endif - - } - while (!EC_POINT_is_at_infinity(group, P)); - - if (!EC_POINT_add(group, P, Q, R, ctx)) ABORT; - if (!EC_POINT_is_at_infinity(group, P)) ABORT; - - len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf, sizeof buf, ctx); - if (len == 0) ABORT; - if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; - if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; - fprintf(stdout, "Generator as octet string, compressed form:\n "); - for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); - - len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx); - if (len == 0) ABORT; - if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; - if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; - fprintf(stdout, "\nGenerator as octet string, uncompressed form:\n "); - for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); - - len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx); - if (len == 0) ABORT; - if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; - if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; - fprintf(stdout, "\nGenerator as octet string, hybrid form:\n "); - for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); - - if (!EC_POINT_get_Jprojective_coordinates_GFp(group, R, x, y, z, ctx)) ABORT; - fprintf(stdout, "\nA representation of the inverse of that generator in\nJacobian projective coordinates:\n X = 0x"); - BN_print_fp(stdout, x); - fprintf(stdout, ", Y = 0x"); - BN_print_fp(stdout, y); - fprintf(stdout, ", Z = 0x"); - BN_print_fp(stdout, z); - fprintf(stdout, "\n"); - - if (!EC_POINT_invert(group, P, ctx)) ABORT; - if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT; - - - /* Curve secp160r1 (Certicom Research SEC 2 Version 1.0, section 2.4.2, 2000) - * -- not a NIST curve, but commonly used */ - - if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF")) ABORT; - if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; - if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC")) ABORT; - if (!BN_hex2bn(&b, "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45")) ABORT; - if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; - - if (!BN_hex2bn(&x, "4A96B5688EF573284664698968C38BB913CBFC82")) ABORT; - if (!BN_hex2bn(&y, "23a628553168947d59dcc912042351377ac5fb32")) ABORT; - if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; - if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; - if (!BN_hex2bn(&z, "0100000000000000000001F4C8F927AED3CA752257")) ABORT; - if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; - - if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; - fprintf(stdout, "\nSEC2 curve secp160r1 -- Generator:\n x = 0x"); - BN_print_fp(stdout, x); - fprintf(stdout, "\n y = 0x"); - BN_print_fp(stdout, y); - fprintf(stdout, "\n"); - /* G_y value taken from the standard: */ - if (!BN_hex2bn(&z, "23a628553168947d59dcc912042351377ac5fb32")) ABORT; - if (0 != BN_cmp(y, z)) ABORT; - - fprintf(stdout, "verify degree ..."); - if (EC_GROUP_get_degree(group) != 160) ABORT; - fprintf(stdout, " ok\n"); - - group_order_tests(group); - - if (!(P_160 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; - if (!EC_GROUP_copy(P_160, group)) ABORT; - - - /* Curve P-192 (FIPS PUB 186-2, App. 6) */ - - if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF")) ABORT; - if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; - if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC")) ABORT; - if (!BN_hex2bn(&b, "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1")) ABORT; - if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; - - if (!BN_hex2bn(&x, "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012")) ABORT; - if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT; - if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; - if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831")) ABORT; - if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; - - if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; - fprintf(stdout, "\nNIST curve P-192 -- Generator:\n x = 0x"); - BN_print_fp(stdout, x); - fprintf(stdout, "\n y = 0x"); - BN_print_fp(stdout, y); - fprintf(stdout, "\n"); - /* G_y value taken from the standard: */ - if (!BN_hex2bn(&z, "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811")) ABORT; - if (0 != BN_cmp(y, z)) ABORT; - - fprintf(stdout, "verify degree ..."); - if (EC_GROUP_get_degree(group) != 192) ABORT; - fprintf(stdout, " ok\n"); - - group_order_tests(group); - - if (!(P_192 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; - if (!EC_GROUP_copy(P_192, group)) ABORT; - - - /* Curve P-224 (FIPS PUB 186-2, App. 6) */ - - if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001")) ABORT; - if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; - if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE")) ABORT; - if (!BN_hex2bn(&b, "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4")) ABORT; - if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; - - if (!BN_hex2bn(&x, "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21")) ABORT; - if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT; - if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; - if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D")) ABORT; - if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; - - if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; - fprintf(stdout, "\nNIST curve P-224 -- Generator:\n x = 0x"); - BN_print_fp(stdout, x); - fprintf(stdout, "\n y = 0x"); - BN_print_fp(stdout, y); - fprintf(stdout, "\n"); - /* G_y value taken from the standard: */ - if (!BN_hex2bn(&z, "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34")) ABORT; - if (0 != BN_cmp(y, z)) ABORT; - - fprintf(stdout, "verify degree ..."); - if (EC_GROUP_get_degree(group) != 224) ABORT; - fprintf(stdout, " ok\n"); - - group_order_tests(group); - - if (!(P_224 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; - if (!EC_GROUP_copy(P_224, group)) ABORT; - - - /* Curve P-256 (FIPS PUB 186-2, App. 6) */ - - if (!BN_hex2bn(&p, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF")) ABORT; - if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; - if (!BN_hex2bn(&a, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC")) ABORT; - if (!BN_hex2bn(&b, "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B")) ABORT; - if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; - - if (!BN_hex2bn(&x, "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296")) ABORT; - if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT; - if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; - if (!BN_hex2bn(&z, "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E" - "84F3B9CAC2FC632551")) ABORT; - if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; - - if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; - fprintf(stdout, "\nNIST curve P-256 -- Generator:\n x = 0x"); - BN_print_fp(stdout, x); - fprintf(stdout, "\n y = 0x"); - BN_print_fp(stdout, y); - fprintf(stdout, "\n"); - /* G_y value taken from the standard: */ - if (!BN_hex2bn(&z, "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5")) ABORT; - if (0 != BN_cmp(y, z)) ABORT; - - fprintf(stdout, "verify degree ..."); - if (EC_GROUP_get_degree(group) != 256) ABORT; - fprintf(stdout, " ok\n"); - - group_order_tests(group); - - if (!(P_256 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; - if (!EC_GROUP_copy(P_256, group)) ABORT; - - - /* Curve P-384 (FIPS PUB 186-2, App. 6) */ - - if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - "FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF")) ABORT; - if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; - if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - "FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC")) ABORT; - if (!BN_hex2bn(&b, "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141" - "120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF")) ABORT; - if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; - - if (!BN_hex2bn(&x, "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B" - "9859F741E082542A385502F25DBF55296C3A545E3872760AB7")) ABORT; - if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT; - if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; - if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - "FFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973")) ABORT; - if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; - - if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; - fprintf(stdout, "\nNIST curve P-384 -- Generator:\n x = 0x"); - BN_print_fp(stdout, x); - fprintf(stdout, "\n y = 0x"); - BN_print_fp(stdout, y); - fprintf(stdout, "\n"); - /* G_y value taken from the standard: */ - if (!BN_hex2bn(&z, "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A14" - "7CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F")) ABORT; - if (0 != BN_cmp(y, z)) ABORT; - - fprintf(stdout, "verify degree ..."); - if (EC_GROUP_get_degree(group) != 384) ABORT; - fprintf(stdout, " ok\n"); - - group_order_tests(group); - - if (!(P_384 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; - if (!EC_GROUP_copy(P_384, group)) ABORT; - - - /* Curve P-521 (FIPS PUB 186-2, App. 6) */ - - if (!BN_hex2bn(&p, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - "FFFFFFFFFFFFFFFFFFFFFFFFFFFF")) ABORT; - if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; - if (!BN_hex2bn(&a, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - "FFFFFFFFFFFFFFFFFFFFFFFFFFFC")) ABORT; - if (!BN_hex2bn(&b, "051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B" - "315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573" - "DF883D2C34F1EF451FD46B503F00")) ABORT; - if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; - - if (!BN_hex2bn(&x, "C6858E06B70404E9CD9E3ECB662395B4429C648139053F" - "B521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B" - "3C1856A429BF97E7E31C2E5BD66")) ABORT; - if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT; - if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; - if (!BN_hex2bn(&z, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - "FFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5" - "C9B8899C47AEBB6FB71E91386409")) ABORT; - if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; - - if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; - fprintf(stdout, "\nNIST curve P-521 -- Generator:\n x = 0x"); - BN_print_fp(stdout, x); - fprintf(stdout, "\n y = 0x"); - BN_print_fp(stdout, y); - fprintf(stdout, "\n"); - /* G_y value taken from the standard: */ - if (!BN_hex2bn(&z, "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579" - "B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C" - "7086A272C24088BE94769FD16650")) ABORT; - if (0 != BN_cmp(y, z)) ABORT; - - fprintf(stdout, "verify degree ..."); - if (EC_GROUP_get_degree(group) != 521) ABORT; - fprintf(stdout, " ok\n"); - - group_order_tests(group); - - if (!(P_521 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; - if (!EC_GROUP_copy(P_521, group)) ABORT; - - - /* more tests using the last curve */ - - if (!EC_POINT_copy(Q, P)) ABORT; - if (EC_POINT_is_at_infinity(group, Q)) ABORT; - if (!EC_POINT_dbl(group, P, P, ctx)) ABORT; - if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; - if (!EC_POINT_invert(group, Q, ctx)) ABORT; /* P = -2Q */ - - if (!EC_POINT_add(group, R, P, Q, ctx)) ABORT; - if (!EC_POINT_add(group, R, R, Q, ctx)) ABORT; - if (!EC_POINT_is_at_infinity(group, R)) ABORT; /* R = P + 2Q */ - - { - const EC_POINT *points[4]; - const BIGNUM *scalars[4]; - BIGNUM scalar3; - - if (EC_POINT_is_at_infinity(group, Q)) ABORT; - points[0] = Q; - points[1] = Q; - points[2] = Q; - points[3] = Q; - - if (!EC_GROUP_get_order(group, z, ctx)) ABORT; - if (!BN_add(y, z, BN_value_one())) ABORT; - if (BN_is_odd(y)) ABORT; - if (!BN_rshift1(y, y)) ABORT; - scalars[0] = y; /* (group order + 1)/2, so y*Q + y*Q = Q */ - scalars[1] = y; - - fprintf(stdout, "combined multiplication ..."); - fflush(stdout); - - /* z is still the group order */ - if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT; - if (!EC_POINTs_mul(group, R, z, 2, points, scalars, ctx)) ABORT; - if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT; - if (0 != EC_POINT_cmp(group, R, Q, ctx)) ABORT; - - fprintf(stdout, "."); - fflush(stdout); - - if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0)) ABORT; - if (!BN_add(z, z, y)) ABORT; - BN_set_negative(z, 1); - scalars[0] = y; - scalars[1] = z; /* z = -(order + y) */ - - if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT; - if (!EC_POINT_is_at_infinity(group, P)) ABORT; - - fprintf(stdout, "."); - fflush(stdout); - - if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0)) ABORT; - if (!BN_add(z, x, y)) ABORT; - BN_set_negative(z, 1); - scalars[0] = x; - scalars[1] = y; - scalars[2] = z; /* z = -(x+y) */ - - BN_init(&scalar3); - BN_zero(&scalar3); - scalars[3] = &scalar3; - - if (!EC_POINTs_mul(group, P, NULL, 4, points, scalars, ctx)) ABORT; - if (!EC_POINT_is_at_infinity(group, P)) ABORT; - - fprintf(stdout, " ok\n\n"); - - BN_free(&scalar3); - } - - -#if 0 - timings(P_160, TIMING_BASE_PT, ctx); - timings(P_160, TIMING_RAND_PT, ctx); - timings(P_160, TIMING_SIMUL, ctx); - timings(P_192, TIMING_BASE_PT, ctx); - timings(P_192, TIMING_RAND_PT, ctx); - timings(P_192, TIMING_SIMUL, ctx); - timings(P_224, TIMING_BASE_PT, ctx); - timings(P_224, TIMING_RAND_PT, ctx); - timings(P_224, TIMING_SIMUL, ctx); - timings(P_256, TIMING_BASE_PT, ctx); - timings(P_256, TIMING_RAND_PT, ctx); - timings(P_256, TIMING_SIMUL, ctx); - timings(P_384, TIMING_BASE_PT, ctx); - timings(P_384, TIMING_RAND_PT, ctx); - timings(P_384, TIMING_SIMUL, ctx); - timings(P_521, TIMING_BASE_PT, ctx); - timings(P_521, TIMING_RAND_PT, ctx); - timings(P_521, TIMING_SIMUL, ctx); -#endif - - - if (ctx) - BN_CTX_free(ctx); - BN_free(p); BN_free(a); BN_free(b); - EC_GROUP_free(group); - EC_POINT_free(P); - EC_POINT_free(Q); - EC_POINT_free(R); - BN_free(x); BN_free(y); BN_free(z); - - if (P_160) EC_GROUP_free(P_160); - if (P_192) EC_GROUP_free(P_192); - if (P_224) EC_GROUP_free(P_224); - if (P_256) EC_GROUP_free(P_256); - if (P_384) EC_GROUP_free(P_384); - if (P_521) EC_GROUP_free(P_521); - - } +{ + BN_CTX *ctx = NULL; + BIGNUM *p, *a, *b; + EC_GROUP *group; + EC_GROUP *P_160 = NULL, *P_192 = NULL, *P_224 = NULL, *P_256 = + NULL, *P_384 = NULL, *P_521 = NULL; + EC_POINT *P, *Q, *R; + BIGNUM *x, *y, *z; + unsigned char buf[100]; + size_t i, len; + int k; + +# if 1 /* optional */ + ctx = BN_CTX_new(); + if (!ctx) + ABORT; +# endif + + p = BN_new(); + a = BN_new(); + b = BN_new(); + if (!p || !a || !b) + ABORT; + + if (!BN_hex2bn(&p, "17")) + ABORT; + if (!BN_hex2bn(&a, "1")) + ABORT; + if (!BN_hex2bn(&b, "1")) + ABORT; + + group = EC_GROUP_new(EC_GFp_mont_method()); /* applications should use + * EC_GROUP_new_curve_GFp so + * that the library gets to + * choose the EC_METHOD */ + if (!group) + ABORT; + + if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) + ABORT; + + { + EC_GROUP *tmp; + tmp = EC_GROUP_new(EC_GROUP_method_of(group)); + if (!tmp) + ABORT; + if (!EC_GROUP_copy(tmp, group)) + ABORT; + EC_GROUP_free(group); + group = tmp; + } + + if (!EC_GROUP_get_curve_GFp(group, p, a, b, ctx)) + ABORT; + + fprintf(stdout, + "Curve defined by Weierstrass equation\n y^2 = x^3 + a*x + b (mod 0x"); + BN_print_fp(stdout, p); + fprintf(stdout, ")\n a = 0x"); + BN_print_fp(stdout, a); + fprintf(stdout, "\n b = 0x"); + BN_print_fp(stdout, b); + fprintf(stdout, "\n"); + + P = EC_POINT_new(group); + Q = EC_POINT_new(group); + R = EC_POINT_new(group); + if (!P || !Q || !R) + ABORT; + + if (!EC_POINT_set_to_infinity(group, P)) + ABORT; + if (!EC_POINT_is_at_infinity(group, P)) + ABORT; + + buf[0] = 0; + if (!EC_POINT_oct2point(group, Q, buf, 1, ctx)) + ABORT; + + if (!EC_POINT_add(group, P, P, Q, ctx)) + ABORT; + if (!EC_POINT_is_at_infinity(group, P)) + ABORT; + + x = BN_new(); + y = BN_new(); + z = BN_new(); + if (!x || !y || !z) + ABORT; + + if (!BN_hex2bn(&x, "D")) + ABORT; + if (!EC_POINT_set_compressed_coordinates_GFp(group, Q, x, 1, ctx)) + ABORT; + if (!EC_POINT_is_on_curve(group, Q, ctx)) { + if (!EC_POINT_get_affine_coordinates_GFp(group, Q, x, y, ctx)) + ABORT; + fprintf(stderr, "Point is not on curve: x = 0x"); + BN_print_fp(stderr, x); + fprintf(stderr, ", y = 0x"); + BN_print_fp(stderr, y); + fprintf(stderr, "\n"); + ABORT; + } + + fprintf(stdout, "A cyclic subgroup:\n"); + k = 100; + do { + if (k-- == 0) + ABORT; + + if (EC_POINT_is_at_infinity(group, P)) + fprintf(stdout, " point at infinity\n"); + else { + if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) + ABORT; + + fprintf(stdout, " x = 0x"); + BN_print_fp(stdout, x); + fprintf(stdout, ", y = 0x"); + BN_print_fp(stdout, y); + fprintf(stdout, "\n"); + } + + if (!EC_POINT_copy(R, P)) + ABORT; + if (!EC_POINT_add(group, P, P, Q, ctx)) + ABORT; + +# if 0 /* optional */ + { + EC_POINT *points[3]; + + points[0] = R; + points[1] = Q; + points[2] = P; + if (!EC_POINTs_make_affine(group, 2, points, ctx)) + ABORT; + } +# endif + + } + while (!EC_POINT_is_at_infinity(group, P)); + + if (!EC_POINT_add(group, P, Q, R, ctx)) + ABORT; + if (!EC_POINT_is_at_infinity(group, P)) + ABORT; + + len = + EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf, + sizeof buf, ctx); + if (len == 0) + ABORT; + if (!EC_POINT_oct2point(group, P, buf, len, ctx)) + ABORT; + if (0 != EC_POINT_cmp(group, P, Q, ctx)) + ABORT; + fprintf(stdout, "Generator as octet string, compressed form:\n "); + for (i = 0; i < len; i++) + fprintf(stdout, "%02X", buf[i]); + + len = + EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, + sizeof buf, ctx); + if (len == 0) + ABORT; + if (!EC_POINT_oct2point(group, P, buf, len, ctx)) + ABORT; + if (0 != EC_POINT_cmp(group, P, Q, ctx)) + ABORT; + fprintf(stdout, "\nGenerator as octet string, uncompressed form:\n "); + for (i = 0; i < len; i++) + fprintf(stdout, "%02X", buf[i]); + + len = + EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, + ctx); + if (len == 0) + ABORT; + if (!EC_POINT_oct2point(group, P, buf, len, ctx)) + ABORT; + if (0 != EC_POINT_cmp(group, P, Q, ctx)) + ABORT; + fprintf(stdout, "\nGenerator as octet string, hybrid form:\n "); + for (i = 0; i < len; i++) + fprintf(stdout, "%02X", buf[i]); + + if (!EC_POINT_get_Jprojective_coordinates_GFp(group, R, x, y, z, ctx)) + ABORT; + fprintf(stdout, + "\nA representation of the inverse of that generator in\nJacobian projective coordinates:\n X = 0x"); + BN_print_fp(stdout, x); + fprintf(stdout, ", Y = 0x"); + BN_print_fp(stdout, y); + fprintf(stdout, ", Z = 0x"); + BN_print_fp(stdout, z); + fprintf(stdout, "\n"); + + if (!EC_POINT_invert(group, P, ctx)) + ABORT; + if (0 != EC_POINT_cmp(group, P, R, ctx)) + ABORT; + + /* + * Curve secp160r1 (Certicom Research SEC 2 Version 1.0, section 2.4.2, + * 2000) -- not a NIST curve, but commonly used + */ + + if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF")) + ABORT; + if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) + ABORT; + if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC")) + ABORT; + if (!BN_hex2bn(&b, "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45")) + ABORT; + if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) + ABORT; + + if (!BN_hex2bn(&x, "4A96B5688EF573284664698968C38BB913CBFC82")) + ABORT; + if (!BN_hex2bn(&y, "23a628553168947d59dcc912042351377ac5fb32")) + ABORT; + if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) + ABORT; + if (!EC_POINT_is_on_curve(group, P, ctx)) + ABORT; + if (!BN_hex2bn(&z, "0100000000000000000001F4C8F927AED3CA752257")) + ABORT; + if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) + ABORT; + + if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) + ABORT; + fprintf(stdout, "\nSEC2 curve secp160r1 -- Generator:\n x = 0x"); + BN_print_fp(stdout, x); + fprintf(stdout, "\n y = 0x"); + BN_print_fp(stdout, y); + fprintf(stdout, "\n"); + /* G_y value taken from the standard: */ + if (!BN_hex2bn(&z, "23a628553168947d59dcc912042351377ac5fb32")) + ABORT; + if (0 != BN_cmp(y, z)) + ABORT; + + fprintf(stdout, "verify degree ..."); + if (EC_GROUP_get_degree(group) != 160) + ABORT; + fprintf(stdout, " ok\n"); + + group_order_tests(group); + + if (!(P_160 = EC_GROUP_new(EC_GROUP_method_of(group)))) + ABORT; + if (!EC_GROUP_copy(P_160, group)) + ABORT; + + /* Curve P-192 (FIPS PUB 186-2, App. 6) */ + + if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF")) + ABORT; + if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) + ABORT; + if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC")) + ABORT; + if (!BN_hex2bn(&b, "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1")) + ABORT; + if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) + ABORT; + + if (!BN_hex2bn(&x, "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012")) + ABORT; + if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) + ABORT; + if (!EC_POINT_is_on_curve(group, P, ctx)) + ABORT; + if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831")) + ABORT; + if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) + ABORT; + + if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) + ABORT; + fprintf(stdout, "\nNIST curve P-192 -- Generator:\n x = 0x"); + BN_print_fp(stdout, x); + fprintf(stdout, "\n y = 0x"); + BN_print_fp(stdout, y); + fprintf(stdout, "\n"); + /* G_y value taken from the standard: */ + if (!BN_hex2bn(&z, "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811")) + ABORT; + if (0 != BN_cmp(y, z)) + ABORT; + + fprintf(stdout, "verify degree ..."); + if (EC_GROUP_get_degree(group) != 192) + ABORT; + fprintf(stdout, " ok\n"); + + group_order_tests(group); + + if (!(P_192 = EC_GROUP_new(EC_GROUP_method_of(group)))) + ABORT; + if (!EC_GROUP_copy(P_192, group)) + ABORT; + + /* Curve P-224 (FIPS PUB 186-2, App. 6) */ + + if (!BN_hex2bn + (&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001")) + ABORT; + if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) + ABORT; + if (!BN_hex2bn + (&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE")) + ABORT; + if (!BN_hex2bn + (&b, "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4")) + ABORT; + if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) + ABORT; + + if (!BN_hex2bn + (&x, "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21")) + ABORT; + if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) + ABORT; + if (!EC_POINT_is_on_curve(group, P, ctx)) + ABORT; + if (!BN_hex2bn + (&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D")) + ABORT; + if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) + ABORT; + + if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) + ABORT; + fprintf(stdout, "\nNIST curve P-224 -- Generator:\n x = 0x"); + BN_print_fp(stdout, x); + fprintf(stdout, "\n y = 0x"); + BN_print_fp(stdout, y); + fprintf(stdout, "\n"); + /* G_y value taken from the standard: */ + if (!BN_hex2bn + (&z, "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34")) + ABORT; + if (0 != BN_cmp(y, z)) + ABORT; + + fprintf(stdout, "verify degree ..."); + if (EC_GROUP_get_degree(group) != 224) + ABORT; + fprintf(stdout, " ok\n"); + + group_order_tests(group); + + if (!(P_224 = EC_GROUP_new(EC_GROUP_method_of(group)))) + ABORT; + if (!EC_GROUP_copy(P_224, group)) + ABORT; + + /* Curve P-256 (FIPS PUB 186-2, App. 6) */ + + if (!BN_hex2bn + (&p, + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF")) + ABORT; + if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) + ABORT; + if (!BN_hex2bn + (&a, + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC")) + ABORT; + if (!BN_hex2bn + (&b, + "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B")) + ABORT; + if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) + ABORT; + + if (!BN_hex2bn + (&x, + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296")) + ABORT; + if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) + ABORT; + if (!EC_POINT_is_on_curve(group, P, ctx)) + ABORT; + if (!BN_hex2bn(&z, "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E" + "84F3B9CAC2FC632551")) + ABORT; + if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) + ABORT; + + if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) + ABORT; + fprintf(stdout, "\nNIST curve P-256 -- Generator:\n x = 0x"); + BN_print_fp(stdout, x); + fprintf(stdout, "\n y = 0x"); + BN_print_fp(stdout, y); + fprintf(stdout, "\n"); + /* G_y value taken from the standard: */ + if (!BN_hex2bn + (&z, + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5")) + ABORT; + if (0 != BN_cmp(y, z)) + ABORT; + + fprintf(stdout, "verify degree ..."); + if (EC_GROUP_get_degree(group) != 256) + ABORT; + fprintf(stdout, " ok\n"); + + group_order_tests(group); + + if (!(P_256 = EC_GROUP_new(EC_GROUP_method_of(group)))) + ABORT; + if (!EC_GROUP_copy(P_256, group)) + ABORT; + + /* Curve P-384 (FIPS PUB 186-2, App. 6) */ + + if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF")) + ABORT; + if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) + ABORT; + if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC")) + ABORT; + if (!BN_hex2bn(&b, "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141" + "120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF")) + ABORT; + if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) + ABORT; + + if (!BN_hex2bn(&x, "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B" + "9859F741E082542A385502F25DBF55296C3A545E3872760AB7")) + ABORT; + if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) + ABORT; + if (!EC_POINT_is_on_curve(group, P, ctx)) + ABORT; + if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973")) + ABORT; + if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) + ABORT; + + if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) + ABORT; + fprintf(stdout, "\nNIST curve P-384 -- Generator:\n x = 0x"); + BN_print_fp(stdout, x); + fprintf(stdout, "\n y = 0x"); + BN_print_fp(stdout, y); + fprintf(stdout, "\n"); + /* G_y value taken from the standard: */ + if (!BN_hex2bn(&z, "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A14" + "7CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F")) + ABORT; + if (0 != BN_cmp(y, z)) + ABORT; + + fprintf(stdout, "verify degree ..."); + if (EC_GROUP_get_degree(group) != 384) + ABORT; + fprintf(stdout, " ok\n"); + + group_order_tests(group); + + if (!(P_384 = EC_GROUP_new(EC_GROUP_method_of(group)))) + ABORT; + if (!EC_GROUP_copy(P_384, group)) + ABORT; + + /* Curve P-521 (FIPS PUB 186-2, App. 6) */ + + if (!BN_hex2bn(&p, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF")) + ABORT; + if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) + ABORT; + if (!BN_hex2bn(&a, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFC")) + ABORT; + if (!BN_hex2bn(&b, "051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B" + "315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573" + "DF883D2C34F1EF451FD46B503F00")) + ABORT; + if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) + ABORT; + + if (!BN_hex2bn(&x, "C6858E06B70404E9CD9E3ECB662395B4429C648139053F" + "B521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B" + "3C1856A429BF97E7E31C2E5BD66")) + ABORT; + if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) + ABORT; + if (!EC_POINT_is_on_curve(group, P, ctx)) + ABORT; + if (!BN_hex2bn(&z, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5" + "C9B8899C47AEBB6FB71E91386409")) + ABORT; + if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) + ABORT; + + if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) + ABORT; + fprintf(stdout, "\nNIST curve P-521 -- Generator:\n x = 0x"); + BN_print_fp(stdout, x); + fprintf(stdout, "\n y = 0x"); + BN_print_fp(stdout, y); + fprintf(stdout, "\n"); + /* G_y value taken from the standard: */ + if (!BN_hex2bn(&z, "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579" + "B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C" + "7086A272C24088BE94769FD16650")) + ABORT; + if (0 != BN_cmp(y, z)) + ABORT; + + fprintf(stdout, "verify degree ..."); + if (EC_GROUP_get_degree(group) != 521) + ABORT; + fprintf(stdout, " ok\n"); + + group_order_tests(group); + + if (!(P_521 = EC_GROUP_new(EC_GROUP_method_of(group)))) + ABORT; + if (!EC_GROUP_copy(P_521, group)) + ABORT; + + /* more tests using the last curve */ + + if (!EC_POINT_copy(Q, P)) + ABORT; + if (EC_POINT_is_at_infinity(group, Q)) + ABORT; + if (!EC_POINT_dbl(group, P, P, ctx)) + ABORT; + if (!EC_POINT_is_on_curve(group, P, ctx)) + ABORT; + if (!EC_POINT_invert(group, Q, ctx)) + ABORT; /* P = -2Q */ + + if (!EC_POINT_add(group, R, P, Q, ctx)) + ABORT; + if (!EC_POINT_add(group, R, R, Q, ctx)) + ABORT; + if (!EC_POINT_is_at_infinity(group, R)) + ABORT; /* R = P + 2Q */ + + { + const EC_POINT *points[4]; + const BIGNUM *scalars[4]; + BIGNUM scalar3; + + if (EC_POINT_is_at_infinity(group, Q)) + ABORT; + points[0] = Q; + points[1] = Q; + points[2] = Q; + points[3] = Q; + + if (!EC_GROUP_get_order(group, z, ctx)) + ABORT; + if (!BN_add(y, z, BN_value_one())) + ABORT; + if (BN_is_odd(y)) + ABORT; + if (!BN_rshift1(y, y)) + ABORT; + scalars[0] = y; /* (group order + 1)/2, so y*Q + y*Q = Q */ + scalars[1] = y; + + fprintf(stdout, "combined multiplication ..."); + fflush(stdout); + + /* z is still the group order */ + if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) + ABORT; + if (!EC_POINTs_mul(group, R, z, 2, points, scalars, ctx)) + ABORT; + if (0 != EC_POINT_cmp(group, P, R, ctx)) + ABORT; + if (0 != EC_POINT_cmp(group, R, Q, ctx)) + ABORT; + + fprintf(stdout, "."); + fflush(stdout); + + if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0)) + ABORT; + if (!BN_add(z, z, y)) + ABORT; + BN_set_negative(z, 1); + scalars[0] = y; + scalars[1] = z; /* z = -(order + y) */ + + if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) + ABORT; + if (!EC_POINT_is_at_infinity(group, P)) + ABORT; + + fprintf(stdout, "."); + fflush(stdout); + + if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0)) + ABORT; + if (!BN_add(z, x, y)) + ABORT; + BN_set_negative(z, 1); + scalars[0] = x; + scalars[1] = y; + scalars[2] = z; /* z = -(x+y) */ + + BN_init(&scalar3); + BN_zero(&scalar3); + scalars[3] = &scalar3; + + if (!EC_POINTs_mul(group, P, NULL, 4, points, scalars, ctx)) + ABORT; + if (!EC_POINT_is_at_infinity(group, P)) + ABORT; + + fprintf(stdout, " ok\n\n"); + + BN_free(&scalar3); + } + +# if 0 + timings(P_160, TIMING_BASE_PT, ctx); + timings(P_160, TIMING_RAND_PT, ctx); + timings(P_160, TIMING_SIMUL, ctx); + timings(P_192, TIMING_BASE_PT, ctx); + timings(P_192, TIMING_RAND_PT, ctx); + timings(P_192, TIMING_SIMUL, ctx); + timings(P_224, TIMING_BASE_PT, ctx); + timings(P_224, TIMING_RAND_PT, ctx); + timings(P_224, TIMING_SIMUL, ctx); + timings(P_256, TIMING_BASE_PT, ctx); + timings(P_256, TIMING_RAND_PT, ctx); + timings(P_256, TIMING_SIMUL, ctx); + timings(P_384, TIMING_BASE_PT, ctx); + timings(P_384, TIMING_RAND_PT, ctx); + timings(P_384, TIMING_SIMUL, ctx); + timings(P_521, TIMING_BASE_PT, ctx); + timings(P_521, TIMING_RAND_PT, ctx); + timings(P_521, TIMING_SIMUL, ctx); +# endif + + if (ctx) + BN_CTX_free(ctx); + BN_free(p); + BN_free(a); + BN_free(b); + EC_GROUP_free(group); + EC_POINT_free(P); + EC_POINT_free(Q); + EC_POINT_free(R); + BN_free(x); + BN_free(y); + BN_free(z); + + if (P_160) + EC_GROUP_free(P_160); + if (P_192) + EC_GROUP_free(P_192); + if (P_224) + EC_GROUP_free(P_224); + if (P_256) + EC_GROUP_free(P_256); + if (P_384) + EC_GROUP_free(P_384); + if (P_521) + EC_GROUP_free(P_521); + +} /* Change test based on whether binary point compression is enabled or not. */ -#ifdef OPENSSL_EC_BIN_PT_COMP -#define CHAR2_CURVE_TEST_INTERNAL(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \ - if (!BN_hex2bn(&x, _x)) ABORT; \ - if (!EC_POINT_set_compressed_coordinates_GF2m(group, P, x, _y_bit, ctx)) ABORT; \ - if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; \ - if (!BN_hex2bn(&z, _order)) ABORT; \ - if (!BN_hex2bn(&cof, _cof)) ABORT; \ - if (!EC_GROUP_set_generator(group, P, z, cof)) ABORT; \ - if (!EC_POINT_get_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT; \ - fprintf(stdout, "\n%s -- Generator:\n x = 0x", _name); \ - BN_print_fp(stdout, x); \ - fprintf(stdout, "\n y = 0x"); \ - BN_print_fp(stdout, y); \ - fprintf(stdout, "\n"); \ - /* G_y value taken from the standard: */ \ - if (!BN_hex2bn(&z, _y)) ABORT; \ - if (0 != BN_cmp(y, z)) ABORT; -#else -#define CHAR2_CURVE_TEST_INTERNAL(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \ - if (!BN_hex2bn(&x, _x)) ABORT; \ - if (!BN_hex2bn(&y, _y)) ABORT; \ - if (!EC_POINT_set_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT; \ - if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; \ - if (!BN_hex2bn(&z, _order)) ABORT; \ - if (!BN_hex2bn(&cof, _cof)) ABORT; \ - if (!EC_GROUP_set_generator(group, P, z, cof)) ABORT; \ - fprintf(stdout, "\n%s -- Generator:\n x = 0x", _name); \ - BN_print_fp(stdout, x); \ - fprintf(stdout, "\n y = 0x"); \ - BN_print_fp(stdout, y); \ - fprintf(stdout, "\n"); -#endif - -#define CHAR2_CURVE_TEST(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \ - if (!BN_hex2bn(&p, _p)) ABORT; \ - if (!BN_hex2bn(&a, _a)) ABORT; \ - if (!BN_hex2bn(&b, _b)) ABORT; \ - if (!EC_GROUP_set_curve_GF2m(group, p, a, b, ctx)) ABORT; \ - CHAR2_CURVE_TEST_INTERNAL(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \ - fprintf(stdout, "verify degree ..."); \ - if (EC_GROUP_get_degree(group) != _degree) ABORT; \ - fprintf(stdout, " ok\n"); \ - group_order_tests(group); \ - if (!(_variable = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; \ - if (!EC_GROUP_copy(_variable, group)) ABORT; \ - -#ifndef OPENSSL_NO_EC2M +# ifdef OPENSSL_EC_BIN_PT_COMP +# define CHAR2_CURVE_TEST_INTERNAL(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \ + if (!BN_hex2bn(&x, _x)) ABORT; \ + if (!EC_POINT_set_compressed_coordinates_GF2m(group, P, x, _y_bit, ctx)) ABORT; \ + if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; \ + if (!BN_hex2bn(&z, _order)) ABORT; \ + if (!BN_hex2bn(&cof, _cof)) ABORT; \ + if (!EC_GROUP_set_generator(group, P, z, cof)) ABORT; \ + if (!EC_POINT_get_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT; \ + fprintf(stdout, "\n%s -- Generator:\n x = 0x", _name); \ + BN_print_fp(stdout, x); \ + fprintf(stdout, "\n y = 0x"); \ + BN_print_fp(stdout, y); \ + fprintf(stdout, "\n"); \ + /* G_y value taken from the standard: */ \ + if (!BN_hex2bn(&z, _y)) ABORT; \ + if (0 != BN_cmp(y, z)) ABORT; +# else +# define CHAR2_CURVE_TEST_INTERNAL(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \ + if (!BN_hex2bn(&x, _x)) ABORT; \ + if (!BN_hex2bn(&y, _y)) ABORT; \ + if (!EC_POINT_set_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT; \ + if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; \ + if (!BN_hex2bn(&z, _order)) ABORT; \ + if (!BN_hex2bn(&cof, _cof)) ABORT; \ + if (!EC_GROUP_set_generator(group, P, z, cof)) ABORT; \ + fprintf(stdout, "\n%s -- Generator:\n x = 0x", _name); \ + BN_print_fp(stdout, x); \ + fprintf(stdout, "\n y = 0x"); \ + BN_print_fp(stdout, y); \ + fprintf(stdout, "\n"); +# endif + +# define CHAR2_CURVE_TEST(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \ + if (!BN_hex2bn(&p, _p)) ABORT; \ + if (!BN_hex2bn(&a, _a)) ABORT; \ + if (!BN_hex2bn(&b, _b)) ABORT; \ + if (!EC_GROUP_set_curve_GF2m(group, p, a, b, ctx)) ABORT; \ + CHAR2_CURVE_TEST_INTERNAL(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \ + fprintf(stdout, "verify degree ..."); \ + if (EC_GROUP_get_degree(group) != _degree) ABORT; \ + fprintf(stdout, " ok\n"); \ + group_order_tests(group); \ + if (!(_variable = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; \ + if (!EC_GROUP_copy(_variable, group)) ABORT; \ + +# ifndef OPENSSL_NO_EC2M static void char2_field_tests(void) - { - BN_CTX *ctx = NULL; - BIGNUM *p, *a, *b; - EC_GROUP *group; - EC_GROUP *C2_K163 = NULL, *C2_K233 = NULL, *C2_K283 = NULL, *C2_K409 = NULL, *C2_K571 = NULL; - EC_GROUP *C2_B163 = NULL, *C2_B233 = NULL, *C2_B283 = NULL, *C2_B409 = NULL, *C2_B571 = NULL; - EC_POINT *P, *Q, *R; - BIGNUM *x, *y, *z, *cof; - unsigned char buf[100]; - size_t i, len; - int k; - -#if 1 /* optional */ - ctx = BN_CTX_new(); - if (!ctx) ABORT; -#endif - - p = BN_new(); - a = BN_new(); - b = BN_new(); - if (!p || !a || !b) ABORT; - - if (!BN_hex2bn(&p, "13")) ABORT; - if (!BN_hex2bn(&a, "3")) ABORT; - if (!BN_hex2bn(&b, "1")) ABORT; - - group = EC_GROUP_new(EC_GF2m_simple_method()); /* applications should use EC_GROUP_new_curve_GF2m - * so that the library gets to choose the EC_METHOD */ - if (!group) ABORT; - if (!EC_GROUP_set_curve_GF2m(group, p, a, b, ctx)) ABORT; - - { - EC_GROUP *tmp; - tmp = EC_GROUP_new(EC_GROUP_method_of(group)); - if (!tmp) ABORT; - if (!EC_GROUP_copy(tmp, group)) ABORT; - EC_GROUP_free(group); - group = tmp; - } - - if (!EC_GROUP_get_curve_GF2m(group, p, a, b, ctx)) ABORT; - - fprintf(stdout, "Curve defined by Weierstrass equation\n y^2 + x*y = x^3 + a*x^2 + b (mod 0x"); - BN_print_fp(stdout, p); - fprintf(stdout, ")\n a = 0x"); - BN_print_fp(stdout, a); - fprintf(stdout, "\n b = 0x"); - BN_print_fp(stdout, b); - fprintf(stdout, "\n(0x... means binary polynomial)\n"); - - P = EC_POINT_new(group); - Q = EC_POINT_new(group); - R = EC_POINT_new(group); - if (!P || !Q || !R) ABORT; - - if (!EC_POINT_set_to_infinity(group, P)) ABORT; - if (!EC_POINT_is_at_infinity(group, P)) ABORT; - - buf[0] = 0; - if (!EC_POINT_oct2point(group, Q, buf, 1, ctx)) ABORT; - - if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT; - if (!EC_POINT_is_at_infinity(group, P)) ABORT; - - x = BN_new(); - y = BN_new(); - z = BN_new(); - cof = BN_new(); - if (!x || !y || !z || !cof) ABORT; - - if (!BN_hex2bn(&x, "6")) ABORT; +{ + BN_CTX *ctx = NULL; + BIGNUM *p, *a, *b; + EC_GROUP *group; + EC_GROUP *C2_K163 = NULL, *C2_K233 = NULL, *C2_K283 = NULL, *C2_K409 = + NULL, *C2_K571 = NULL; + EC_GROUP *C2_B163 = NULL, *C2_B233 = NULL, *C2_B283 = NULL, *C2_B409 = + NULL, *C2_B571 = NULL; + EC_POINT *P, *Q, *R; + BIGNUM *x, *y, *z, *cof; + unsigned char buf[100]; + size_t i, len; + int k; + +# if 1 /* optional */ + ctx = BN_CTX_new(); + if (!ctx) + ABORT; +# endif + + p = BN_new(); + a = BN_new(); + b = BN_new(); + if (!p || !a || !b) + ABORT; + + if (!BN_hex2bn(&p, "13")) + ABORT; + if (!BN_hex2bn(&a, "3")) + ABORT; + if (!BN_hex2bn(&b, "1")) + ABORT; + + group = EC_GROUP_new(EC_GF2m_simple_method()); /* applications should use + * EC_GROUP_new_curve_GF2m + * so that the library gets + * to choose the EC_METHOD */ + if (!group) + ABORT; + if (!EC_GROUP_set_curve_GF2m(group, p, a, b, ctx)) + ABORT; + + { + EC_GROUP *tmp; + tmp = EC_GROUP_new(EC_GROUP_method_of(group)); + if (!tmp) + ABORT; + if (!EC_GROUP_copy(tmp, group)) + ABORT; + EC_GROUP_free(group); + group = tmp; + } + + if (!EC_GROUP_get_curve_GF2m(group, p, a, b, ctx)) + ABORT; + + fprintf(stdout, + "Curve defined by Weierstrass equation\n y^2 + x*y = x^3 + a*x^2 + b (mod 0x"); + BN_print_fp(stdout, p); + fprintf(stdout, ")\n a = 0x"); + BN_print_fp(stdout, a); + fprintf(stdout, "\n b = 0x"); + BN_print_fp(stdout, b); + fprintf(stdout, "\n(0x... means binary polynomial)\n"); + + P = EC_POINT_new(group); + Q = EC_POINT_new(group); + R = EC_POINT_new(group); + if (!P || !Q || !R) + ABORT; + + if (!EC_POINT_set_to_infinity(group, P)) + ABORT; + if (!EC_POINT_is_at_infinity(group, P)) + ABORT; + + buf[0] = 0; + if (!EC_POINT_oct2point(group, Q, buf, 1, ctx)) + ABORT; + + if (!EC_POINT_add(group, P, P, Q, ctx)) + ABORT; + if (!EC_POINT_is_at_infinity(group, P)) + ABORT; + + x = BN_new(); + y = BN_new(); + z = BN_new(); + cof = BN_new(); + if (!x || !y || !z || !cof) + ABORT; + + if (!BN_hex2bn(&x, "6")) + ABORT; /* Change test based on whether binary point compression is enabled or not. */ -#ifdef OPENSSL_EC_BIN_PT_COMP - if (!EC_POINT_set_compressed_coordinates_GF2m(group, Q, x, 1, ctx)) ABORT; -#else - if (!BN_hex2bn(&y, "8")) ABORT; - if (!EC_POINT_set_affine_coordinates_GF2m(group, Q, x, y, ctx)) ABORT; -#endif - if (!EC_POINT_is_on_curve(group, Q, ctx)) - { +# ifdef OPENSSL_EC_BIN_PT_COMP + if (!EC_POINT_set_compressed_coordinates_GF2m(group, Q, x, 1, ctx)) + ABORT; +# else + if (!BN_hex2bn(&y, "8")) + ABORT; + if (!EC_POINT_set_affine_coordinates_GF2m(group, Q, x, y, ctx)) + ABORT; +# endif + if (!EC_POINT_is_on_curve(group, Q, ctx)) { /* Change test based on whether binary point compression is enabled or not. */ -#ifdef OPENSSL_EC_BIN_PT_COMP - if (!EC_POINT_get_affine_coordinates_GF2m(group, Q, x, y, ctx)) ABORT; -#endif - fprintf(stderr, "Point is not on curve: x = 0x"); - BN_print_fp(stderr, x); - fprintf(stderr, ", y = 0x"); - BN_print_fp(stderr, y); - fprintf(stderr, "\n"); - ABORT; - } - - fprintf(stdout, "A cyclic subgroup:\n"); - k = 100; - do - { - if (k-- == 0) ABORT; - - if (EC_POINT_is_at_infinity(group, P)) - fprintf(stdout, " point at infinity\n"); - else - { - if (!EC_POINT_get_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT; - - fprintf(stdout, " x = 0x"); - BN_print_fp(stdout, x); - fprintf(stdout, ", y = 0x"); - BN_print_fp(stdout, y); - fprintf(stdout, "\n"); - } - - if (!EC_POINT_copy(R, P)) ABORT; - if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT; - } - while (!EC_POINT_is_at_infinity(group, P)); - - if (!EC_POINT_add(group, P, Q, R, ctx)) ABORT; - if (!EC_POINT_is_at_infinity(group, P)) ABORT; +# ifdef OPENSSL_EC_BIN_PT_COMP + if (!EC_POINT_get_affine_coordinates_GF2m(group, Q, x, y, ctx)) + ABORT; +# endif + fprintf(stderr, "Point is not on curve: x = 0x"); + BN_print_fp(stderr, x); + fprintf(stderr, ", y = 0x"); + BN_print_fp(stderr, y); + fprintf(stderr, "\n"); + ABORT; + } + + fprintf(stdout, "A cyclic subgroup:\n"); + k = 100; + do { + if (k-- == 0) + ABORT; + + if (EC_POINT_is_at_infinity(group, P)) + fprintf(stdout, " point at infinity\n"); + else { + if (!EC_POINT_get_affine_coordinates_GF2m(group, P, x, y, ctx)) + ABORT; + + fprintf(stdout, " x = 0x"); + BN_print_fp(stdout, x); + fprintf(stdout, ", y = 0x"); + BN_print_fp(stdout, y); + fprintf(stdout, "\n"); + } + + if (!EC_POINT_copy(R, P)) + ABORT; + if (!EC_POINT_add(group, P, P, Q, ctx)) + ABORT; + } + while (!EC_POINT_is_at_infinity(group, P)); + + if (!EC_POINT_add(group, P, Q, R, ctx)) + ABORT; + if (!EC_POINT_is_at_infinity(group, P)) + ABORT; /* Change test based on whether binary point compression is enabled or not. */ -#ifdef OPENSSL_EC_BIN_PT_COMP - len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf, sizeof buf, ctx); - if (len == 0) ABORT; - if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; - if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; - fprintf(stdout, "Generator as octet string, compressed form:\n "); - for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); -#endif - - len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx); - if (len == 0) ABORT; - if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; - if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; - fprintf(stdout, "\nGenerator as octet string, uncompressed form:\n "); - for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); - -/* Change test based on whether binary point compression is enabled or not. */ -#ifdef OPENSSL_EC_BIN_PT_COMP - len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx); - if (len == 0) ABORT; - if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; - if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; - fprintf(stdout, "\nGenerator as octet string, hybrid form:\n "); - for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); -#endif - - fprintf(stdout, "\n"); - - if (!EC_POINT_invert(group, P, ctx)) ABORT; - if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT; - - - /* Curve K-163 (FIPS PUB 186-2, App. 6) */ - CHAR2_CURVE_TEST - ( - "NIST curve K-163", - "0800000000000000000000000000000000000000C9", - "1", - "1", - "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8", - "0289070FB05D38FF58321F2E800536D538CCDAA3D9", - 1, - "04000000000000000000020108A2E0CC0D99F8A5EF", - "2", - 163, - C2_K163 - ); - - /* Curve B-163 (FIPS PUB 186-2, App. 6) */ - CHAR2_CURVE_TEST - ( - "NIST curve B-163", - "0800000000000000000000000000000000000000C9", - "1", - "020A601907B8C953CA1481EB10512F78744A3205FD", - "03F0EBA16286A2D57EA0991168D4994637E8343E36", - "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1", - 1, - "040000000000000000000292FE77E70C12A4234C33", - "2", - 163, - C2_B163 - ); - - /* Curve K-233 (FIPS PUB 186-2, App. 6) */ - CHAR2_CURVE_TEST - ( - "NIST curve K-233", - "020000000000000000000000000000000000000004000000000000000001", - "0", - "1", - "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126", - "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3", - 0, - "008000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF", - "4", - 233, - C2_K233 - ); - - /* Curve B-233 (FIPS PUB 186-2, App. 6) */ - CHAR2_CURVE_TEST - ( - "NIST curve B-233", - "020000000000000000000000000000000000000004000000000000000001", - "000000000000000000000000000000000000000000000000000000000001", - "0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD", - "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B", - "01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052", - 1, - "01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7", - "2", - 233, - C2_B233 - ); - - /* Curve K-283 (FIPS PUB 186-2, App. 6) */ - CHAR2_CURVE_TEST - ( - "NIST curve K-283", - "0800000000000000000000000000000000000000000000000000000000000000000010A1", - "0", - "1", - "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836", - "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259", - 0, - "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61", - "4", - 283, - C2_K283 - ); - - /* Curve B-283 (FIPS PUB 186-2, App. 6) */ - CHAR2_CURVE_TEST - ( - "NIST curve B-283", - "0800000000000000000000000000000000000000000000000000000000000000000010A1", - "000000000000000000000000000000000000000000000000000000000000000000000001", - "027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5", - "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053", - "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4", - 1, - "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307", - "2", - 283, - C2_B283 - ); - - /* Curve K-409 (FIPS PUB 186-2, App. 6) */ - CHAR2_CURVE_TEST - ( - "NIST curve K-409", - "02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001", - "0", - "1", - "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746", - "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B", - 1, - "007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF", - "4", - 409, - C2_K409 - ); - - /* Curve B-409 (FIPS PUB 186-2, App. 6) */ - CHAR2_CURVE_TEST - ( - "NIST curve B-409", - "02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001", - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", - "0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F", - "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7", - "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706", - 1, - "010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173", - "2", - 409, - C2_B409 - ); - - /* Curve K-571 (FIPS PUB 186-2, App. 6) */ - CHAR2_CURVE_TEST - ( - "NIST curve K-571", - "80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425", - "0", - "1", - "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972", - "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3", - 0, - "020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001", - "4", - 571, - C2_K571 - ); - - /* Curve B-571 (FIPS PUB 186-2, App. 6) */ - CHAR2_CURVE_TEST - ( - "NIST curve B-571", - "80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425", - "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", - "02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A", - "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19", - "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B", - 1, - "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47", - "2", - 571, - C2_B571 - ); - - /* more tests using the last curve */ - - if (!EC_POINT_copy(Q, P)) ABORT; - if (EC_POINT_is_at_infinity(group, Q)) ABORT; - if (!EC_POINT_dbl(group, P, P, ctx)) ABORT; - if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; - if (!EC_POINT_invert(group, Q, ctx)) ABORT; /* P = -2Q */ - - if (!EC_POINT_add(group, R, P, Q, ctx)) ABORT; - if (!EC_POINT_add(group, R, R, Q, ctx)) ABORT; - if (!EC_POINT_is_at_infinity(group, R)) ABORT; /* R = P + 2Q */ - - { - const EC_POINT *points[3]; - const BIGNUM *scalars[3]; - - if (EC_POINT_is_at_infinity(group, Q)) ABORT; - points[0] = Q; - points[1] = Q; - points[2] = Q; - - if (!BN_add(y, z, BN_value_one())) ABORT; - if (BN_is_odd(y)) ABORT; - if (!BN_rshift1(y, y)) ABORT; - scalars[0] = y; /* (group order + 1)/2, so y*Q + y*Q = Q */ - scalars[1] = y; - - fprintf(stdout, "combined multiplication ..."); - fflush(stdout); - - /* z is still the group order */ - if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT; - if (!EC_POINTs_mul(group, R, z, 2, points, scalars, ctx)) ABORT; - if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT; - if (0 != EC_POINT_cmp(group, R, Q, ctx)) ABORT; - - fprintf(stdout, "."); - fflush(stdout); - - if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0)) ABORT; - if (!BN_add(z, z, y)) ABORT; - BN_set_negative(z, 1); - scalars[0] = y; - scalars[1] = z; /* z = -(order + y) */ - - if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT; - if (!EC_POINT_is_at_infinity(group, P)) ABORT; - - fprintf(stdout, "."); - fflush(stdout); - - if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0)) ABORT; - if (!BN_add(z, x, y)) ABORT; - BN_set_negative(z, 1); - scalars[0] = x; - scalars[1] = y; - scalars[2] = z; /* z = -(x+y) */ - - if (!EC_POINTs_mul(group, P, NULL, 3, points, scalars, ctx)) ABORT; - if (!EC_POINT_is_at_infinity(group, P)) ABORT; - - fprintf(stdout, " ok\n\n"); - } - - -#if 0 - timings(C2_K163, TIMING_BASE_PT, ctx); - timings(C2_K163, TIMING_RAND_PT, ctx); - timings(C2_K163, TIMING_SIMUL, ctx); - timings(C2_B163, TIMING_BASE_PT, ctx); - timings(C2_B163, TIMING_RAND_PT, ctx); - timings(C2_B163, TIMING_SIMUL, ctx); - timings(C2_K233, TIMING_BASE_PT, ctx); - timings(C2_K233, TIMING_RAND_PT, ctx); - timings(C2_K233, TIMING_SIMUL, ctx); - timings(C2_B233, TIMING_BASE_PT, ctx); - timings(C2_B233, TIMING_RAND_PT, ctx); - timings(C2_B233, TIMING_SIMUL, ctx); - timings(C2_K283, TIMING_BASE_PT, ctx); - timings(C2_K283, TIMING_RAND_PT, ctx); - timings(C2_K283, TIMING_SIMUL, ctx); - timings(C2_B283, TIMING_BASE_PT, ctx); - timings(C2_B283, TIMING_RAND_PT, ctx); - timings(C2_B283, TIMING_SIMUL, ctx); - timings(C2_K409, TIMING_BASE_PT, ctx); - timings(C2_K409, TIMING_RAND_PT, ctx); - timings(C2_K409, TIMING_SIMUL, ctx); - timings(C2_B409, TIMING_BASE_PT, ctx); - timings(C2_B409, TIMING_RAND_PT, ctx); - timings(C2_B409, TIMING_SIMUL, ctx); - timings(C2_K571, TIMING_BASE_PT, ctx); - timings(C2_K571, TIMING_RAND_PT, ctx); - timings(C2_K571, TIMING_SIMUL, ctx); - timings(C2_B571, TIMING_BASE_PT, ctx); - timings(C2_B571, TIMING_RAND_PT, ctx); - timings(C2_B571, TIMING_SIMUL, ctx); -#endif +# ifdef OPENSSL_EC_BIN_PT_COMP + len = + EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf, + sizeof buf, ctx); + if (len == 0) + ABORT; + if (!EC_POINT_oct2point(group, P, buf, len, ctx)) + ABORT; + if (0 != EC_POINT_cmp(group, P, Q, ctx)) + ABORT; + fprintf(stdout, "Generator as octet string, compressed form:\n "); + for (i = 0; i < len; i++) + fprintf(stdout, "%02X", buf[i]); +# endif + + len = + EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, + sizeof buf, ctx); + if (len == 0) + ABORT; + if (!EC_POINT_oct2point(group, P, buf, len, ctx)) + ABORT; + if (0 != EC_POINT_cmp(group, P, Q, ctx)) + ABORT; + fprintf(stdout, "\nGenerator as octet string, uncompressed form:\n "); + for (i = 0; i < len; i++) + fprintf(stdout, "%02X", buf[i]); - - if (ctx) - BN_CTX_free(ctx); - BN_free(p); BN_free(a); BN_free(b); - EC_GROUP_free(group); - EC_POINT_free(P); - EC_POINT_free(Q); - EC_POINT_free(R); - BN_free(x); BN_free(y); BN_free(z); BN_free(cof); - - if (C2_K163) EC_GROUP_free(C2_K163); - if (C2_B163) EC_GROUP_free(C2_B163); - if (C2_K233) EC_GROUP_free(C2_K233); - if (C2_B233) EC_GROUP_free(C2_B233); - if (C2_K283) EC_GROUP_free(C2_K283); - if (C2_B283) EC_GROUP_free(C2_B283); - if (C2_K409) EC_GROUP_free(C2_K409); - if (C2_B409) EC_GROUP_free(C2_B409); - if (C2_K571) EC_GROUP_free(C2_K571); - if (C2_B571) EC_GROUP_free(C2_B571); - - } -#endif +/* Change test based on whether binary point compression is enabled or not. */ +# ifdef OPENSSL_EC_BIN_PT_COMP + len = + EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, + ctx); + if (len == 0) + ABORT; + if (!EC_POINT_oct2point(group, P, buf, len, ctx)) + ABORT; + if (0 != EC_POINT_cmp(group, P, Q, ctx)) + ABORT; + fprintf(stdout, "\nGenerator as octet string, hybrid form:\n "); + for (i = 0; i < len; i++) + fprintf(stdout, "%02X", buf[i]); +# endif + + fprintf(stdout, "\n"); + + if (!EC_POINT_invert(group, P, ctx)) + ABORT; + if (0 != EC_POINT_cmp(group, P, R, ctx)) + ABORT; + + /* Curve K-163 (FIPS PUB 186-2, App. 6) */ + CHAR2_CURVE_TEST + ("NIST curve K-163", + "0800000000000000000000000000000000000000C9", + "1", + "1", + "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8", + "0289070FB05D38FF58321F2E800536D538CCDAA3D9", + 1, "04000000000000000000020108A2E0CC0D99F8A5EF", "2", 163, C2_K163); + + /* Curve B-163 (FIPS PUB 186-2, App. 6) */ + CHAR2_CURVE_TEST + ("NIST curve B-163", + "0800000000000000000000000000000000000000C9", + "1", + "020A601907B8C953CA1481EB10512F78744A3205FD", + "03F0EBA16286A2D57EA0991168D4994637E8343E36", + "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1", + 1, "040000000000000000000292FE77E70C12A4234C33", "2", 163, C2_B163); + + /* Curve K-233 (FIPS PUB 186-2, App. 6) */ + CHAR2_CURVE_TEST + ("NIST curve K-233", + "020000000000000000000000000000000000000004000000000000000001", + "0", + "1", + "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126", + "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3", + 0, + "008000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF", + "4", 233, C2_K233); + + /* Curve B-233 (FIPS PUB 186-2, App. 6) */ + CHAR2_CURVE_TEST + ("NIST curve B-233", + "020000000000000000000000000000000000000004000000000000000001", + "000000000000000000000000000000000000000000000000000000000001", + "0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD", + "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B", + "01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052", + 1, + "01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7", + "2", 233, C2_B233); + + /* Curve K-283 (FIPS PUB 186-2, App. 6) */ + CHAR2_CURVE_TEST + ("NIST curve K-283", + "0800000000000000000000000000000000000000000000000000000000000000000010A1", + "0", + "1", + "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836", + "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259", + 0, + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61", + "4", 283, C2_K283); + + /* Curve B-283 (FIPS PUB 186-2, App. 6) */ + CHAR2_CURVE_TEST + ("NIST curve B-283", + "0800000000000000000000000000000000000000000000000000000000000000000010A1", + "000000000000000000000000000000000000000000000000000000000000000000000001", + "027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5", + "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053", + "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4", + 1, + "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307", + "2", 283, C2_B283); + + /* Curve K-409 (FIPS PUB 186-2, App. 6) */ + CHAR2_CURVE_TEST + ("NIST curve K-409", + "02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001", + "0", + "1", + "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746", + "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B", + 1, + "007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF", + "4", 409, C2_K409); + + /* Curve B-409 (FIPS PUB 186-2, App. 6) */ + CHAR2_CURVE_TEST + ("NIST curve B-409", + "02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F", + "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7", + "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706", + 1, + "010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173", + "2", 409, C2_B409); + + /* Curve K-571 (FIPS PUB 186-2, App. 6) */ + CHAR2_CURVE_TEST + ("NIST curve K-571", + "80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425", + "0", + "1", + "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972", + "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3", + 0, + "020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001", + "4", 571, C2_K571); + + /* Curve B-571 (FIPS PUB 186-2, App. 6) */ + CHAR2_CURVE_TEST + ("NIST curve B-571", + "80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A", + "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19", + "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B", + 1, + "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47", + "2", 571, C2_B571); + + /* more tests using the last curve */ + + if (!EC_POINT_copy(Q, P)) + ABORT; + if (EC_POINT_is_at_infinity(group, Q)) + ABORT; + if (!EC_POINT_dbl(group, P, P, ctx)) + ABORT; + if (!EC_POINT_is_on_curve(group, P, ctx)) + ABORT; + if (!EC_POINT_invert(group, Q, ctx)) + ABORT; /* P = -2Q */ + + if (!EC_POINT_add(group, R, P, Q, ctx)) + ABORT; + if (!EC_POINT_add(group, R, R, Q, ctx)) + ABORT; + if (!EC_POINT_is_at_infinity(group, R)) + ABORT; /* R = P + 2Q */ + + { + const EC_POINT *points[3]; + const BIGNUM *scalars[3]; + + if (EC_POINT_is_at_infinity(group, Q)) + ABORT; + points[0] = Q; + points[1] = Q; + points[2] = Q; + + if (!BN_add(y, z, BN_value_one())) + ABORT; + if (BN_is_odd(y)) + ABORT; + if (!BN_rshift1(y, y)) + ABORT; + scalars[0] = y; /* (group order + 1)/2, so y*Q + y*Q = Q */ + scalars[1] = y; + + fprintf(stdout, "combined multiplication ..."); + fflush(stdout); + + /* z is still the group order */ + if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) + ABORT; + if (!EC_POINTs_mul(group, R, z, 2, points, scalars, ctx)) + ABORT; + if (0 != EC_POINT_cmp(group, P, R, ctx)) + ABORT; + if (0 != EC_POINT_cmp(group, R, Q, ctx)) + ABORT; + + fprintf(stdout, "."); + fflush(stdout); + + if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0)) + ABORT; + if (!BN_add(z, z, y)) + ABORT; + BN_set_negative(z, 1); + scalars[0] = y; + scalars[1] = z; /* z = -(order + y) */ + + if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) + ABORT; + if (!EC_POINT_is_at_infinity(group, P)) + ABORT; + + fprintf(stdout, "."); + fflush(stdout); + + if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0)) + ABORT; + if (!BN_add(z, x, y)) + ABORT; + BN_set_negative(z, 1); + scalars[0] = x; + scalars[1] = y; + scalars[2] = z; /* z = -(x+y) */ + + if (!EC_POINTs_mul(group, P, NULL, 3, points, scalars, ctx)) + ABORT; + if (!EC_POINT_is_at_infinity(group, P)) + ABORT; + + fprintf(stdout, " ok\n\n"); + } + +# if 0 + timings(C2_K163, TIMING_BASE_PT, ctx); + timings(C2_K163, TIMING_RAND_PT, ctx); + timings(C2_K163, TIMING_SIMUL, ctx); + timings(C2_B163, TIMING_BASE_PT, ctx); + timings(C2_B163, TIMING_RAND_PT, ctx); + timings(C2_B163, TIMING_SIMUL, ctx); + timings(C2_K233, TIMING_BASE_PT, ctx); + timings(C2_K233, TIMING_RAND_PT, ctx); + timings(C2_K233, TIMING_SIMUL, ctx); + timings(C2_B233, TIMING_BASE_PT, ctx); + timings(C2_B233, TIMING_RAND_PT, ctx); + timings(C2_B233, TIMING_SIMUL, ctx); + timings(C2_K283, TIMING_BASE_PT, ctx); + timings(C2_K283, TIMING_RAND_PT, ctx); + timings(C2_K283, TIMING_SIMUL, ctx); + timings(C2_B283, TIMING_BASE_PT, ctx); + timings(C2_B283, TIMING_RAND_PT, ctx); + timings(C2_B283, TIMING_SIMUL, ctx); + timings(C2_K409, TIMING_BASE_PT, ctx); + timings(C2_K409, TIMING_RAND_PT, ctx); + timings(C2_K409, TIMING_SIMUL, ctx); + timings(C2_B409, TIMING_BASE_PT, ctx); + timings(C2_B409, TIMING_RAND_PT, ctx); + timings(C2_B409, TIMING_SIMUL, ctx); + timings(C2_K571, TIMING_BASE_PT, ctx); + timings(C2_K571, TIMING_RAND_PT, ctx); + timings(C2_K571, TIMING_SIMUL, ctx); + timings(C2_B571, TIMING_BASE_PT, ctx); + timings(C2_B571, TIMING_RAND_PT, ctx); + timings(C2_B571, TIMING_SIMUL, ctx); +# endif + + if (ctx) + BN_CTX_free(ctx); + BN_free(p); + BN_free(a); + BN_free(b); + EC_GROUP_free(group); + EC_POINT_free(P); + EC_POINT_free(Q); + EC_POINT_free(R); + BN_free(x); + BN_free(y); + BN_free(z); + BN_free(cof); + + if (C2_K163) + EC_GROUP_free(C2_K163); + if (C2_B163) + EC_GROUP_free(C2_B163); + if (C2_K233) + EC_GROUP_free(C2_K233); + if (C2_B233) + EC_GROUP_free(C2_B233); + if (C2_K283) + EC_GROUP_free(C2_K283); + if (C2_B283) + EC_GROUP_free(C2_B283); + if (C2_K409) + EC_GROUP_free(C2_K409); + if (C2_B409) + EC_GROUP_free(C2_B409); + if (C2_K571) + EC_GROUP_free(C2_K571); + if (C2_B571) + EC_GROUP_free(C2_B571); + +} +# endif static void internal_curve_test(void) - { - EC_builtin_curve *curves = NULL; - size_t crv_len = 0, n = 0; - int ok = 1; - - crv_len = EC_get_builtin_curves(NULL, 0); - - curves = OPENSSL_malloc(sizeof(EC_builtin_curve) * crv_len); - - if (curves == NULL) - return; - - if (!EC_get_builtin_curves(curves, crv_len)) - { - OPENSSL_free(curves); - return; - } - - fprintf(stdout, "testing internal curves: "); - - for (n = 0; n < crv_len; n++) - { - EC_GROUP *group = NULL; - int nid = curves[n].nid; - if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL) - { - ok = 0; - fprintf(stdout, "\nEC_GROUP_new_curve_name() failed with" - " curve %s\n", OBJ_nid2sn(nid)); - /* try next curve */ - continue; - } - if (!EC_GROUP_check(group, NULL)) - { - ok = 0; - fprintf(stdout, "\nEC_GROUP_check() failed with" - " curve %s\n", OBJ_nid2sn(nid)); - EC_GROUP_free(group); - /* try the next curve */ - continue; - } - fprintf(stdout, "."); - fflush(stdout); - EC_GROUP_free(group); - } - if (ok) - fprintf(stdout, " ok\n\n"); - else - { - fprintf(stdout, " failed\n\n"); - ABORT; - } - OPENSSL_free(curves); - return; - } - -#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 -/* nistp_test_params contains magic numbers for testing our optimized - * implementations of several NIST curves with characteristic > 3. */ -struct nistp_test_params - { - const EC_METHOD* (*meth) (); - int degree; - /* Qx, Qy and D are taken from - * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/ECDSA_Prime.pdf - * Otherwise, values are standard curve parameters from FIPS 180-3 */ - const char *p, *a, *b, *Qx, *Qy, *Gx, *Gy, *order, *d; - }; - -static const struct nistp_test_params nistp_tests_params[] = - { - { - /* P-224 */ - EC_GFp_nistp224_method, - 224, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", /* p */ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", /* a */ - "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", /* b */ - "E84FB0B8E7000CB657D7973CF6B42ED78B301674276DF744AF130B3E", /* Qx */ - "4376675C6FC5612C21A0FF2D2A89D2987DF7A2BC52183B5982298555", /* Qy */ - "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", /* Gx */ - "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", /* Gy */ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", /* order */ - "3F0C488E987C80BE0FEE521F8D90BE6034EC69AE11CA72AA777481E8", /* d */ - }, - { - /* P-256 */ - EC_GFp_nistp256_method, - 256, - "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", /* p */ - "ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", /* a */ - "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", /* b */ - "b7e08afdfe94bad3f1dc8c734798ba1c62b3a0ad1e9ea2a38201cd0889bc7a19", /* Qx */ - "3603f747959dbf7a4bb226e41928729063adc7ae43529e61b563bbc606cc5e09", /* Qy */ - "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", /* Gx */ - "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", /* Gy */ - "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", /* order */ - "c477f9f65c22cce20657faa5b2d1d8122336f851a508a1ed04e479c34985bf96", /* d */ - }, - { - /* P-521 */ - EC_GFp_nistp521_method, - 521, - "1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", /* p */ - "1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc", /* a */ - "051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", /* b */ - "0098e91eef9a68452822309c52fab453f5f117c1da8ed796b255e9ab8f6410cca16e59df403a6bdc6ca467a37056b1e54b3005d8ac030decfeb68df18b171885d5c4", /* Qx */ - "0164350c321aecfc1cca1ba4364c9b15656150b4b78d6a48d7d28e7f31985ef17be8554376b72900712c4b83ad668327231526e313f5f092999a4632fd50d946bc2e", /* Qy */ - "c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", /* Gx */ - "11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", /* Gy */ - "1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409", /* order */ - "0100085f47b8e1b8b11b7eb33028c0b2888e304bfc98501955b45bba1478dc184eeedf09b86a5f7c21994406072787205e69a63709fe35aa93ba333514b24f961722", /* d */ - }, - }; +{ + EC_builtin_curve *curves = NULL; + size_t crv_len = 0, n = 0; + int ok = 1; + + crv_len = EC_get_builtin_curves(NULL, 0); + + curves = OPENSSL_malloc(sizeof(EC_builtin_curve) * crv_len); + + if (curves == NULL) + return; + + if (!EC_get_builtin_curves(curves, crv_len)) { + OPENSSL_free(curves); + return; + } + + fprintf(stdout, "testing internal curves: "); + + for (n = 0; n < crv_len; n++) { + EC_GROUP *group = NULL; + int nid = curves[n].nid; + if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL) { + ok = 0; + fprintf(stdout, "\nEC_GROUP_new_curve_name() failed with" + " curve %s\n", OBJ_nid2sn(nid)); + /* try next curve */ + continue; + } + if (!EC_GROUP_check(group, NULL)) { + ok = 0; + fprintf(stdout, "\nEC_GROUP_check() failed with" + " curve %s\n", OBJ_nid2sn(nid)); + EC_GROUP_free(group); + /* try the next curve */ + continue; + } + fprintf(stdout, "."); + fflush(stdout); + EC_GROUP_free(group); + } + if (ok) + fprintf(stdout, " ok\n\n"); + else { + fprintf(stdout, " failed\n\n"); + ABORT; + } + OPENSSL_free(curves); + return; +} + +# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 +/* + * nistp_test_params contains magic numbers for testing our optimized + * implementations of several NIST curves with characteristic > 3. + */ +struct nistp_test_params { + const EC_METHOD *(*meth) (); + int degree; + /* + * Qx, Qy and D are taken from + * http://csrcdocut.gov/groups/ST/toolkit/documents/Examples/ECDSA_Prime.pdf + * Otherwise, values are standard curve parameters from FIPS 180-3 + */ + const char *p, *a, *b, *Qx, *Qy, *Gx, *Gy, *order, *d; +}; + +static const struct nistp_test_params nistp_tests_params[] = { + { + /* P-224 */ + EC_GFp_nistp224_method, + 224, + /* p */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", + /* a */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", + /* b */ + "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", + /* Qx */ + "E84FB0B8E7000CB657D7973CF6B42ED78B301674276DF744AF130B3E", + /* Qy */ + "4376675C6FC5612C21A0FF2D2A89D2987DF7A2BC52183B5982298555", + /* Gx */ + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", + /* Gy */ + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", + /* order */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", + /* d */ + "3F0C488E987C80BE0FEE521F8D90BE6034EC69AE11CA72AA777481E8", + }, + { + /* P-256 */ + EC_GFp_nistp256_method, + 256, + /* p */ + "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", + /* a */ + "ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", + /* b */ + "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", + /* Qx */ + "b7e08afdfe94bad3f1dc8c734798ba1c62b3a0ad1e9ea2a38201cd0889bc7a19", + /* Qy */ + "3603f747959dbf7a4bb226e41928729063adc7ae43529e61b563bbc606cc5e09", + /* Gx */ + "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", + /* Gy */ + "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", + /* order */ + "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", + /* d */ + "c477f9f65c22cce20657faa5b2d1d8122336f851a508a1ed04e479c34985bf96", + }, + { + /* P-521 */ + EC_GFp_nistp521_method, + 521, + /* p */ + "1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + /* a */ + "1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc", + /* b */ + "051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", + /* Qx */ + "0098e91eef9a68452822309c52fab453f5f117c1da8ed796b255e9ab8f6410cca16e59df403a6bdc6ca467a37056b1e54b3005d8ac030decfeb68df18b171885d5c4", + /* Qy */ + "0164350c321aecfc1cca1ba4364c9b15656150b4b78d6a48d7d28e7f31985ef17be8554376b72900712c4b83ad668327231526e313f5f092999a4632fd50d946bc2e", + /* Gx */ + "c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", + /* Gy */ + "11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", + /* order */ + "1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409", + /* d */ + "0100085f47b8e1b8b11b7eb33028c0b2888e304bfc98501955b45bba1478dc184eeedf09b86a5f7c21994406072787205e69a63709fe35aa93ba333514b24f961722", + }, +}; static void nistp_single_test(const struct nistp_test_params *test) - { - BN_CTX *ctx; - BIGNUM *p, *a, *b, *x, *y, *n, *m, *order; - EC_GROUP *NISTP; - EC_POINT *G, *P, *Q, *Q_CHECK; - - fprintf(stdout, "\nNIST curve P-%d (optimised implementation):\n", test->degree); - ctx = BN_CTX_new(); - p = BN_new(); - a = BN_new(); - b = BN_new(); - x = BN_new(); y = BN_new(); - m = BN_new(); n = BN_new(); order = BN_new(); - - NISTP = EC_GROUP_new(test->meth()); - if(!NISTP) ABORT; - if (!BN_hex2bn(&p, test->p)) ABORT; - if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT; - if (!BN_hex2bn(&a, test->a)) ABORT; - if (!BN_hex2bn(&b, test->b)) ABORT; - if (!EC_GROUP_set_curve_GFp(NISTP, p, a, b, ctx)) ABORT; - G = EC_POINT_new(NISTP); - P = EC_POINT_new(NISTP); - Q = EC_POINT_new(NISTP); - Q_CHECK = EC_POINT_new(NISTP); - if(!BN_hex2bn(&x, test->Qx)) ABORT; - if(!BN_hex2bn(&y, test->Qy)) ABORT; - if(!EC_POINT_set_affine_coordinates_GFp(NISTP, Q_CHECK, x, y, ctx)) ABORT; - if (!BN_hex2bn(&x, test->Gx)) ABORT; - if (!BN_hex2bn(&y, test->Gy)) ABORT; - if (!EC_POINT_set_affine_coordinates_GFp(NISTP, G, x, y, ctx)) ABORT; - if (!BN_hex2bn(&order, test->order)) ABORT; - if (!EC_GROUP_set_generator(NISTP, G, order, BN_value_one())) ABORT; - - fprintf(stdout, "verify degree ... "); - if (EC_GROUP_get_degree(NISTP) != test->degree) ABORT; - fprintf(stdout, "ok\n"); - - fprintf(stdout, "NIST test vectors ... "); - if (!BN_hex2bn(&n, test->d)) ABORT; - /* fixed point multiplication */ - EC_POINT_mul(NISTP, Q, n, NULL, NULL, ctx); - if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT; - /* random point multiplication */ - EC_POINT_mul(NISTP, Q, NULL, G, n, ctx); - if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT; - - /* set generator to P = 2*G, where G is the standard generator */ - if (!EC_POINT_dbl(NISTP, P, G, ctx)) ABORT; - if (!EC_GROUP_set_generator(NISTP, P, order, BN_value_one())) ABORT; - /* set the scalar to m=n/2, where n is the NIST test scalar */ - if (!BN_rshift(m, n, 1)) ABORT; - - /* test the non-standard generator */ - /* fixed point multiplication */ - EC_POINT_mul(NISTP, Q, m, NULL, NULL, ctx); - if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT; - /* random point multiplication */ - EC_POINT_mul(NISTP, Q, NULL, P, m, ctx); - if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT; - - /* now repeat all tests with precomputation */ - if (!EC_GROUP_precompute_mult(NISTP, ctx)) ABORT; - - /* fixed point multiplication */ - EC_POINT_mul(NISTP, Q, m, NULL, NULL, ctx); - if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT; - /* random point multiplication */ - EC_POINT_mul(NISTP, Q, NULL, P, m, ctx); - if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT; - - /* reset generator */ - if (!EC_GROUP_set_generator(NISTP, G, order, BN_value_one())) ABORT; - /* fixed point multiplication */ - EC_POINT_mul(NISTP, Q, n, NULL, NULL, ctx); - if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT; - /* random point multiplication */ - EC_POINT_mul(NISTP, Q, NULL, G, n, ctx); - if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT; - - fprintf(stdout, "ok\n"); - group_order_tests(NISTP); -#if 0 - timings(NISTP, TIMING_BASE_PT, ctx); - timings(NISTP, TIMING_RAND_PT, ctx); -#endif - EC_GROUP_free(NISTP); - EC_POINT_free(G); - EC_POINT_free(P); - EC_POINT_free(Q); - EC_POINT_free(Q_CHECK); - BN_free(n); - BN_free(m); - BN_free(p); - BN_free(a); - BN_free(b); - BN_free(x); - BN_free(y); - BN_free(order); - BN_CTX_free(ctx); - } +{ + BN_CTX *ctx; + BIGNUM *p, *a, *b, *x, *y, *n, *m, *order; + EC_GROUP *NISTP; + EC_POINT *G, *P, *Q, *Q_CHECK; + + fprintf(stdout, "\nNIST curve P-%d (optimised implementation):\n", + test->degree); + ctx = BN_CTX_new(); + p = BN_new(); + a = BN_new(); + b = BN_new(); + x = BN_new(); + y = BN_new(); + m = BN_new(); + n = BN_new(); + order = BN_new(); + + NISTP = EC_GROUP_new(test->meth()); + if (!NISTP) + ABORT; + if (!BN_hex2bn(&p, test->p)) + ABORT; + if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) + ABORT; + if (!BN_hex2bn(&a, test->a)) + ABORT; + if (!BN_hex2bn(&b, test->b)) + ABORT; + if (!EC_GROUP_set_curve_GFp(NISTP, p, a, b, ctx)) + ABORT; + G = EC_POINT_new(NISTP); + P = EC_POINT_new(NISTP); + Q = EC_POINT_new(NISTP); + Q_CHECK = EC_POINT_new(NISTP); + if (!BN_hex2bn(&x, test->Qx)) + ABORT; + if (!BN_hex2bn(&y, test->Qy)) + ABORT; + if (!EC_POINT_set_affine_coordinates_GFp(NISTP, Q_CHECK, x, y, ctx)) + ABORT; + if (!BN_hex2bn(&x, test->Gx)) + ABORT; + if (!BN_hex2bn(&y, test->Gy)) + ABORT; + if (!EC_POINT_set_affine_coordinates_GFp(NISTP, G, x, y, ctx)) + ABORT; + if (!BN_hex2bn(&order, test->order)) + ABORT; + if (!EC_GROUP_set_generator(NISTP, G, order, BN_value_one())) + ABORT; + + fprintf(stdout, "verify degree ... "); + if (EC_GROUP_get_degree(NISTP) != test->degree) + ABORT; + fprintf(stdout, "ok\n"); + + fprintf(stdout, "NIST test vectors ... "); + if (!BN_hex2bn(&n, test->d)) + ABORT; + /* fixed point multiplication */ + EC_POINT_mul(NISTP, Q, n, NULL, NULL, ctx); + if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) + ABORT; + /* random point multiplication */ + EC_POINT_mul(NISTP, Q, NULL, G, n, ctx); + if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) + ABORT; + + /* set generator to P = 2*G, where G is the standard generator */ + if (!EC_POINT_dbl(NISTP, P, G, ctx)) + ABORT; + if (!EC_GROUP_set_generator(NISTP, P, order, BN_value_one())) + ABORT; + /* set the scalar to m=n/2, where n is the NIST test scalar */ + if (!BN_rshift(m, n, 1)) + ABORT; + + /* test the non-standard generator */ + /* fixed point multiplication */ + EC_POINT_mul(NISTP, Q, m, NULL, NULL, ctx); + if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) + ABORT; + /* random point multiplication */ + EC_POINT_mul(NISTP, Q, NULL, P, m, ctx); + if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) + ABORT; + + /* now repeat all tests with precomputation */ + if (!EC_GROUP_precompute_mult(NISTP, ctx)) + ABORT; + + /* fixed point multiplication */ + EC_POINT_mul(NISTP, Q, m, NULL, NULL, ctx); + if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) + ABORT; + /* random point multiplication */ + EC_POINT_mul(NISTP, Q, NULL, P, m, ctx); + if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) + ABORT; + + /* reset generator */ + if (!EC_GROUP_set_generator(NISTP, G, order, BN_value_one())) + ABORT; + /* fixed point multiplication */ + EC_POINT_mul(NISTP, Q, n, NULL, NULL, ctx); + if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) + ABORT; + /* random point multiplication */ + EC_POINT_mul(NISTP, Q, NULL, G, n, ctx); + if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) + ABORT; + + fprintf(stdout, "ok\n"); + group_order_tests(NISTP); +# if 0 + timings(NISTP, TIMING_BASE_PT, ctx); + timings(NISTP, TIMING_RAND_PT, ctx); +# endif + EC_GROUP_free(NISTP); + EC_POINT_free(G); + EC_POINT_free(P); + EC_POINT_free(Q); + EC_POINT_free(Q_CHECK); + BN_free(n); + BN_free(m); + BN_free(p); + BN_free(a); + BN_free(b); + BN_free(x); + BN_free(y); + BN_free(order); + BN_CTX_free(ctx); +} static void nistp_tests() - { - unsigned i; - - for (i = 0; i < sizeof(nistp_tests_params) / sizeof(struct nistp_test_params); i++) - { - nistp_single_test(&nistp_tests_params[i]); - } - } -#endif +{ + unsigned i; -static const char rnd_seed[] = "string to make the random number generator think it has entropy"; + for (i = 0; + i < sizeof(nistp_tests_params) / sizeof(struct nistp_test_params); + i++) { + nistp_single_test(&nistp_tests_params[i]); + } +} +# endif -int main(int argc, char *argv[]) - { - - /* enable memory leak checking unless explicitly disabled */ - if (!((getenv("OPENSSL_DEBUG_MEMORY") != NULL) && (0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off")))) - { - CRYPTO_malloc_debug_init(); - CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL); - } - else - { - /* OPENSSL_DEBUG_MEMORY=off */ - CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0); - } - CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); - ERR_load_crypto_strings(); - - RAND_seed(rnd_seed, sizeof rnd_seed); /* or BN_generate_prime may fail */ - - prime_field_tests(); - puts(""); -#ifndef OPENSSL_NO_EC2M - char2_field_tests(); -#endif -#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 - nistp_tests(); -#endif - /* test the internal curves */ - internal_curve_test(); +static const char rnd_seed[] = + "string to make the random number generator think it has entropy"; -#ifndef OPENSSL_NO_ENGINE - ENGINE_cleanup(); -#endif - CRYPTO_cleanup_all_ex_data(); - ERR_free_strings(); - ERR_remove_thread_state(NULL); - CRYPTO_mem_leaks_fp(stderr); - - return 0; - } +int main(int argc, char *argv[]) +{ + + /* enable memory leak checking unless explicitly disabled */ + if (!((getenv("OPENSSL_DEBUG_MEMORY") != NULL) + && (0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off")))) { + CRYPTO_malloc_debug_init(); + CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL); + } else { + /* OPENSSL_DEBUG_MEMORY=off */ + CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0); + } + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); + ERR_load_crypto_strings(); + + RAND_seed(rnd_seed, sizeof rnd_seed); /* or BN_generate_prime may fail */ + + prime_field_tests(); + puts(""); +# ifndef OPENSSL_NO_EC2M + char2_field_tests(); +# endif +# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 + nistp_tests(); +# endif + /* test the internal curves */ + internal_curve_test(); + +# ifndef OPENSSL_NO_ENGINE + ENGINE_cleanup(); +# endif + CRYPTO_cleanup_all_ex_data(); + ERR_free_strings(); + ERR_remove_thread_state(NULL); + CRYPTO_mem_leaks_fp(stderr); + + return 0; +} #endif |