summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/ec
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/ec')
-rw-r--r--src/lib/libcrypto/ec/ec.h69
-rw-r--r--src/lib/libcrypto/ec/ec2_smpl.c351
-rw-r--r--src/lib/libcrypto/ec/ec_cvt.c28
-rw-r--r--src/lib/libcrypto/ec/ec_err.c20
-rw-r--r--src/lib/libcrypto/ec/ec_lcl.h55
-rw-r--r--src/lib/libcrypto/ec/ec_lib.c80
-rw-r--r--src/lib/libcrypto/ec/ecp_mont.c14
-rw-r--r--src/lib/libcrypto/ec/ecp_nist.c13
-rw-r--r--src/lib/libcrypto/ec/ecp_smpl.c379
-rw-r--r--src/lib/libcrypto/ec/ectest.c341
10 files changed, 463 insertions, 887 deletions
diff --git a/src/lib/libcrypto/ec/ec.h b/src/lib/libcrypto/ec/ec.h
index ee7078130c..9d01325af3 100644
--- a/src/lib/libcrypto/ec/ec.h
+++ b/src/lib/libcrypto/ec/ec.h
@@ -151,7 +151,24 @@ const EC_METHOD *EC_GFp_mont_method(void);
151 */ 151 */
152const EC_METHOD *EC_GFp_nist_method(void); 152const EC_METHOD *EC_GFp_nist_method(void);
153 153
154#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
155/** Returns 64-bit optimized methods for nistp224
156 * \return EC_METHOD object
157 */
158const EC_METHOD *EC_GFp_nistp224_method(void);
159
160/** Returns 64-bit optimized methods for nistp256
161 * \return EC_METHOD object
162 */
163const EC_METHOD *EC_GFp_nistp256_method(void);
164
165/** Returns 64-bit optimized methods for nistp521
166 * \return EC_METHOD object
167 */
168const EC_METHOD *EC_GFp_nistp521_method(void);
169#endif
154 170
171#ifndef OPENSSL_NO_EC2M
155/********************************************************************/ 172/********************************************************************/
156/* EC_METHOD for curves over GF(2^m) */ 173/* EC_METHOD for curves over GF(2^m) */
157/********************************************************************/ 174/********************************************************************/
@@ -161,6 +178,8 @@ const EC_METHOD *EC_GFp_nist_method(void);
161 */ 178 */
162const EC_METHOD *EC_GF2m_simple_method(void); 179const EC_METHOD *EC_GF2m_simple_method(void);
163 180
181#endif
182
164 183
165/********************************************************************/ 184/********************************************************************/
166/* EC_GROUP functions */ 185/* EC_GROUP functions */
@@ -282,6 +301,7 @@ int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, co
282 */ 301 */
283int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx); 302int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx);
284 303
304#ifndef OPENSSL_NO_EC2M
285/** Sets the parameter of a ec over GF2m defined by y^2 + x*y = x^3 + a*x^2 + b 305/** Sets the parameter of a ec over GF2m defined by y^2 + x*y = x^3 + a*x^2 + b
286 * \param group EC_GROUP object 306 * \param group EC_GROUP object
287 * \param p BIGNUM with the polynomial defining the underlying field 307 * \param p BIGNUM with the polynomial defining the underlying field
@@ -301,7 +321,7 @@ int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, c
301 * \return 1 on success and 0 if an error occured 321 * \return 1 on success and 0 if an error occured
302 */ 322 */
303int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx); 323int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx);
304 324#endif
305/** Returns the number of bits needed to represent a field element 325/** Returns the number of bits needed to represent a field element
306 * \param group EC_GROUP object 326 * \param group EC_GROUP object
307 * \return number of bits needed to represent a field element 327 * \return number of bits needed to represent a field element
@@ -342,7 +362,7 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx);
342 * \return newly created EC_GROUP object with the specified parameters 362 * \return newly created EC_GROUP object with the specified parameters
343 */ 363 */
344EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); 364EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
345 365#ifndef OPENSSL_NO_EC2M
346/** Creates a new EC_GROUP object with the specified parameters defined 366/** Creates a new EC_GROUP object with the specified parameters defined
347 * over GF2m (defined by the equation y^2 + x*y = x^3 + a*x^2 + b) 367 * over GF2m (defined by the equation y^2 + x*y = x^3 + a*x^2 + b)
348 * \param p BIGNUM with the polynomial defining the underlying field 368 * \param p BIGNUM with the polynomial defining the underlying field
@@ -352,7 +372,7 @@ EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM
352 * \return newly created EC_GROUP object with the specified parameters 372 * \return newly created EC_GROUP object with the specified parameters
353 */ 373 */
354EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); 374EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
355 375#endif
356/** Creates a EC_GROUP object with a curve specified by a NID 376/** Creates a EC_GROUP object with a curve specified by a NID
357 * \param nid NID of the OID of the curve name 377 * \param nid NID of the OID of the curve name
358 * \return newly created EC_GROUP object with specified curve or NULL 378 * \return newly created EC_GROUP object with specified curve or NULL
@@ -481,7 +501,7 @@ int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
481 */ 501 */
482int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *p, 502int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *p,
483 const BIGNUM *x, int y_bit, BN_CTX *ctx); 503 const BIGNUM *x, int y_bit, BN_CTX *ctx);
484 504#ifndef OPENSSL_NO_EC2M
485/** Sets the affine coordinates of a EC_POINT over GF2m 505/** Sets the affine coordinates of a EC_POINT over GF2m
486 * \param group underlying EC_GROUP object 506 * \param group underlying EC_GROUP object
487 * \param p EC_POINT object 507 * \param p EC_POINT object
@@ -514,7 +534,7 @@ int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,
514 */ 534 */
515int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, EC_POINT *p, 535int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, EC_POINT *p,
516 const BIGNUM *x, int y_bit, BN_CTX *ctx); 536 const BIGNUM *x, int y_bit, BN_CTX *ctx);
517 537#endif
518/** Encodes a EC_POINT object to a octet string 538/** Encodes a EC_POINT object to a octet string
519 * \param group underlying EC_GROUP object 539 * \param group underlying EC_GROUP object
520 * \param p EC_POINT object 540 * \param p EC_POINT object
@@ -653,9 +673,11 @@ int EC_GROUP_have_precompute_mult(const EC_GROUP *group);
653/* EC_GROUP_get_basis_type() returns the NID of the basis type 673/* EC_GROUP_get_basis_type() returns the NID of the basis type
654 * used to represent the field elements */ 674 * used to represent the field elements */
655int EC_GROUP_get_basis_type(const EC_GROUP *); 675int EC_GROUP_get_basis_type(const EC_GROUP *);
676#ifndef OPENSSL_NO_EC2M
656int EC_GROUP_get_trinomial_basis(const EC_GROUP *, unsigned int *k); 677int EC_GROUP_get_trinomial_basis(const EC_GROUP *, unsigned int *k);
657int EC_GROUP_get_pentanomial_basis(const EC_GROUP *, unsigned int *k1, 678int EC_GROUP_get_pentanomial_basis(const EC_GROUP *, unsigned int *k1,
658 unsigned int *k2, unsigned int *k3); 679 unsigned int *k2, unsigned int *k3);
680#endif
659 681
660#define OPENSSL_EC_NAMED_CURVE 0x001 682#define OPENSSL_EC_NAMED_CURVE 0x001
661 683
@@ -689,11 +711,21 @@ typedef struct ec_key_st EC_KEY;
689#define EC_PKEY_NO_PARAMETERS 0x001 711#define EC_PKEY_NO_PARAMETERS 0x001
690#define EC_PKEY_NO_PUBKEY 0x002 712#define EC_PKEY_NO_PUBKEY 0x002
691 713
714/* some values for the flags field */
715#define EC_FLAG_NON_FIPS_ALLOW 0x1
716#define EC_FLAG_FIPS_CHECKED 0x2
717
692/** Creates a new EC_KEY object. 718/** Creates a new EC_KEY object.
693 * \return EC_KEY object or NULL if an error occurred. 719 * \return EC_KEY object or NULL if an error occurred.
694 */ 720 */
695EC_KEY *EC_KEY_new(void); 721EC_KEY *EC_KEY_new(void);
696 722
723int EC_KEY_get_flags(const EC_KEY *key);
724
725void EC_KEY_set_flags(EC_KEY *key, int flags);
726
727void EC_KEY_clear_flags(EC_KEY *key, int flags);
728
697/** Creates a new EC_KEY object using a named curve as underlying 729/** Creates a new EC_KEY object using a named curve as underlying
698 * EC_GROUP object. 730 * EC_GROUP object.
699 * \param nid NID of the named curve. 731 * \param nid NID of the named curve.
@@ -799,6 +831,15 @@ int EC_KEY_generate_key(EC_KEY *key);
799 */ 831 */
800int EC_KEY_check_key(const EC_KEY *key); 832int EC_KEY_check_key(const EC_KEY *key);
801 833
834/** Sets a public key from affine coordindates performing
835 * neccessary NIST PKV tests.
836 * \param key the EC_KEY object
837 * \param x public key x coordinate
838 * \param y public key y coordinate
839 * \return 1 on success and 0 otherwise.
840 */
841int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y);
842
802 843
803/********************************************************************/ 844/********************************************************************/
804/* de- and encoding functions for SEC1 ECPrivateKey */ 845/* de- and encoding functions for SEC1 ECPrivateKey */
@@ -926,6 +967,7 @@ void ERR_load_EC_strings(void);
926/* Error codes for the EC functions. */ 967/* Error codes for the EC functions. */
927 968
928/* Function codes. */ 969/* Function codes. */
970#define EC_F_BN_TO_FELEM 224
929#define EC_F_COMPUTE_WNAF 143 971#define EC_F_COMPUTE_WNAF 143
930#define EC_F_D2I_ECPARAMETERS 144 972#define EC_F_D2I_ECPARAMETERS 144
931#define EC_F_D2I_ECPKPARAMETERS 145 973#define EC_F_D2I_ECPKPARAMETERS 145
@@ -968,6 +1010,15 @@ void ERR_load_EC_strings(void);
968#define EC_F_EC_GFP_MONT_FIELD_SQR 132 1010#define EC_F_EC_GFP_MONT_FIELD_SQR 132
969#define EC_F_EC_GFP_MONT_GROUP_SET_CURVE 189 1011#define EC_F_EC_GFP_MONT_GROUP_SET_CURVE 189
970#define EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP 135 1012#define EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP 135
1013#define EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE 225
1014#define EC_F_EC_GFP_NISTP224_POINTS_MUL 228
1015#define EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES 226
1016#define EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE 230
1017#define EC_F_EC_GFP_NISTP256_POINTS_MUL 231
1018#define EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES 232
1019#define EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE 233
1020#define EC_F_EC_GFP_NISTP521_POINTS_MUL 234
1021#define EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES 235
971#define EC_F_EC_GFP_NIST_FIELD_MUL 200 1022#define EC_F_EC_GFP_NIST_FIELD_MUL 200
972#define EC_F_EC_GFP_NIST_FIELD_SQR 201 1023#define EC_F_EC_GFP_NIST_FIELD_SQR 201
973#define EC_F_EC_GFP_NIST_GROUP_SET_CURVE 202 1024#define EC_F_EC_GFP_NIST_GROUP_SET_CURVE 202
@@ -1010,6 +1061,7 @@ void ERR_load_EC_strings(void);
1010#define EC_F_EC_KEY_NEW 182 1061#define EC_F_EC_KEY_NEW 182
1011#define EC_F_EC_KEY_PRINT 180 1062#define EC_F_EC_KEY_PRINT 180
1012#define EC_F_EC_KEY_PRINT_FP 181 1063#define EC_F_EC_KEY_PRINT_FP 181
1064#define EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES 229
1013#define EC_F_EC_POINTS_MAKE_AFFINE 136 1065#define EC_F_EC_POINTS_MAKE_AFFINE 136
1014#define EC_F_EC_POINT_ADD 112 1066#define EC_F_EC_POINT_ADD 112
1015#define EC_F_EC_POINT_CMP 113 1067#define EC_F_EC_POINT_CMP 113
@@ -1040,6 +1092,9 @@ void ERR_load_EC_strings(void);
1040#define EC_F_I2D_ECPKPARAMETERS 191 1092#define EC_F_I2D_ECPKPARAMETERS 191
1041#define EC_F_I2D_ECPRIVATEKEY 192 1093#define EC_F_I2D_ECPRIVATEKEY 192
1042#define EC_F_I2O_ECPUBLICKEY 151 1094#define EC_F_I2O_ECPUBLICKEY 151
1095#define EC_F_NISTP224_PRE_COMP_NEW 227
1096#define EC_F_NISTP256_PRE_COMP_NEW 236
1097#define EC_F_NISTP521_PRE_COMP_NEW 237
1043#define EC_F_O2I_ECPUBLICKEY 152 1098#define EC_F_O2I_ECPUBLICKEY 152
1044#define EC_F_OLD_EC_PRIV_DECODE 222 1099#define EC_F_OLD_EC_PRIV_DECODE 222
1045#define EC_F_PKEY_EC_CTRL 197 1100#define EC_F_PKEY_EC_CTRL 197
@@ -1052,12 +1107,15 @@ void ERR_load_EC_strings(void);
1052/* Reason codes. */ 1107/* Reason codes. */
1053#define EC_R_ASN1_ERROR 115 1108#define EC_R_ASN1_ERROR 115
1054#define EC_R_ASN1_UNKNOWN_FIELD 116 1109#define EC_R_ASN1_UNKNOWN_FIELD 116
1110#define EC_R_BIGNUM_OUT_OF_RANGE 144
1055#define EC_R_BUFFER_TOO_SMALL 100 1111#define EC_R_BUFFER_TOO_SMALL 100
1112#define EC_R_COORDINATES_OUT_OF_RANGE 146
1056#define EC_R_D2I_ECPKPARAMETERS_FAILURE 117 1113#define EC_R_D2I_ECPKPARAMETERS_FAILURE 117
1057#define EC_R_DECODE_ERROR 142 1114#define EC_R_DECODE_ERROR 142
1058#define EC_R_DISCRIMINANT_IS_ZERO 118 1115#define EC_R_DISCRIMINANT_IS_ZERO 118
1059#define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE 119 1116#define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE 119
1060#define EC_R_FIELD_TOO_LARGE 143 1117#define EC_R_FIELD_TOO_LARGE 143
1118#define EC_R_GF2M_NOT_SUPPORTED 147
1061#define EC_R_GROUP2PKPARAMETERS_FAILURE 120 1119#define EC_R_GROUP2PKPARAMETERS_FAILURE 120
1062#define EC_R_I2D_ECPKPARAMETERS_FAILURE 121 1120#define EC_R_I2D_ECPKPARAMETERS_FAILURE 121
1063#define EC_R_INCOMPATIBLE_OBJECTS 101 1121#define EC_R_INCOMPATIBLE_OBJECTS 101
@@ -1092,6 +1150,7 @@ void ERR_load_EC_strings(void);
1092#define EC_R_UNKNOWN_GROUP 129 1150#define EC_R_UNKNOWN_GROUP 129
1093#define EC_R_UNKNOWN_ORDER 114 1151#define EC_R_UNKNOWN_ORDER 114
1094#define EC_R_UNSUPPORTED_FIELD 131 1152#define EC_R_UNSUPPORTED_FIELD 131
1153#define EC_R_WRONG_CURVE_PARAMETERS 145
1095#define EC_R_WRONG_ORDER 130 1154#define EC_R_WRONG_ORDER 130
1096 1155
1097#ifdef __cplusplus 1156#ifdef __cplusplus
diff --git a/src/lib/libcrypto/ec/ec2_smpl.c b/src/lib/libcrypto/ec/ec2_smpl.c
index 03deae6674..e0e59c7d82 100644
--- a/src/lib/libcrypto/ec/ec2_smpl.c
+++ b/src/lib/libcrypto/ec/ec2_smpl.c
@@ -71,10 +71,20 @@
71 71
72#include "ec_lcl.h" 72#include "ec_lcl.h"
73 73
74#ifndef OPENSSL_NO_EC2M
75
76#ifdef OPENSSL_FIPS
77#include <openssl/fips.h>
78#endif
79
74 80
75const EC_METHOD *EC_GF2m_simple_method(void) 81const EC_METHOD *EC_GF2m_simple_method(void)
76 { 82 {
83#ifdef OPENSSL_FIPS
84 return fips_ec_gf2m_simple_method();
85#else
77 static const EC_METHOD ret = { 86 static const EC_METHOD ret = {
87 EC_FLAGS_DEFAULT_OCT,
78 NID_X9_62_characteristic_two_field, 88 NID_X9_62_characteristic_two_field,
79 ec_GF2m_simple_group_init, 89 ec_GF2m_simple_group_init,
80 ec_GF2m_simple_group_finish, 90 ec_GF2m_simple_group_finish,
@@ -93,9 +103,7 @@ const EC_METHOD *EC_GF2m_simple_method(void)
93 0 /* get_Jprojective_coordinates_GFp */, 103 0 /* get_Jprojective_coordinates_GFp */,
94 ec_GF2m_simple_point_set_affine_coordinates, 104 ec_GF2m_simple_point_set_affine_coordinates,
95 ec_GF2m_simple_point_get_affine_coordinates, 105 ec_GF2m_simple_point_get_affine_coordinates,
96 ec_GF2m_simple_set_compressed_coordinates, 106 0,0,0,
97 ec_GF2m_simple_point2oct,
98 ec_GF2m_simple_oct2point,
99 ec_GF2m_simple_add, 107 ec_GF2m_simple_add,
100 ec_GF2m_simple_dbl, 108 ec_GF2m_simple_dbl,
101 ec_GF2m_simple_invert, 109 ec_GF2m_simple_invert,
@@ -118,6 +126,7 @@ const EC_METHOD *EC_GF2m_simple_method(void)
118 0 /* field_set_to_one */ }; 126 0 /* field_set_to_one */ };
119 127
120 return &ret; 128 return &ret;
129#endif
121 } 130 }
122 131
123 132
@@ -405,340 +414,6 @@ int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_
405 return ret; 414 return ret;
406 } 415 }
407 416
408
409/* Calculates and sets the affine coordinates of an EC_POINT from the given
410 * compressed coordinates. Uses algorithm 2.3.4 of SEC 1.
411 * Note that the simple implementation only uses affine coordinates.
412 *
413 * The method is from the following publication:
414 *
415 * Harper, Menezes, Vanstone:
416 * "Public-Key Cryptosystems with Very Small Key Lengths",
417 * EUROCRYPT '92, Springer-Verlag LNCS 658,
418 * published February 1993
419 *
420 * US Patents 6,141,420 and 6,618,483 (Vanstone, Mullin, Agnew) describe
421 * the same method, but claim no priority date earlier than July 29, 1994
422 * (and additionally fail to cite the EUROCRYPT '92 publication as prior art).
423 */
424int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
425 const BIGNUM *x_, int y_bit, BN_CTX *ctx)
426 {
427 BN_CTX *new_ctx = NULL;
428 BIGNUM *tmp, *x, *y, *z;
429 int ret = 0, z0;
430
431 /* clear error queue */
432 ERR_clear_error();
433
434 if (ctx == NULL)
435 {
436 ctx = new_ctx = BN_CTX_new();
437 if (ctx == NULL)
438 return 0;
439 }
440
441 y_bit = (y_bit != 0) ? 1 : 0;
442
443 BN_CTX_start(ctx);
444 tmp = BN_CTX_get(ctx);
445 x = BN_CTX_get(ctx);
446 y = BN_CTX_get(ctx);
447 z = BN_CTX_get(ctx);
448 if (z == NULL) goto err;
449
450 if (!BN_GF2m_mod_arr(x, x_, group->poly)) goto err;
451 if (BN_is_zero(x))
452 {
453 if (!BN_GF2m_mod_sqrt_arr(y, &group->b, group->poly, ctx)) goto err;
454 }
455 else
456 {
457 if (!group->meth->field_sqr(group, tmp, x, ctx)) goto err;
458 if (!group->meth->field_div(group, tmp, &group->b, tmp, ctx)) goto err;
459 if (!BN_GF2m_add(tmp, &group->a, tmp)) goto err;
460 if (!BN_GF2m_add(tmp, x, tmp)) goto err;
461 if (!BN_GF2m_mod_solve_quad_arr(z, tmp, group->poly, ctx))
462 {
463 unsigned long err = ERR_peek_last_error();
464
465 if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NO_SOLUTION)
466 {
467 ERR_clear_error();
468 ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
469 }
470 else
471 ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
472 goto err;
473 }
474 z0 = (BN_is_odd(z)) ? 1 : 0;
475 if (!group->meth->field_mul(group, y, x, z, ctx)) goto err;
476 if (z0 != y_bit)
477 {
478 if (!BN_GF2m_add(y, y, x)) goto err;
479 }
480 }
481
482 if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
483
484 ret = 1;
485
486 err:
487 BN_CTX_end(ctx);
488 if (new_ctx != NULL)
489 BN_CTX_free(new_ctx);
490 return ret;
491 }
492
493
494/* Converts an EC_POINT to an octet string.
495 * If buf is NULL, the encoded length will be returned.
496 * If the length len of buf is smaller than required an error will be returned.
497 */
498size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
499 unsigned char *buf, size_t len, BN_CTX *ctx)
500 {
501 size_t ret;
502 BN_CTX *new_ctx = NULL;
503 int used_ctx = 0;
504 BIGNUM *x, *y, *yxi;
505 size_t field_len, i, skip;
506
507 if ((form != POINT_CONVERSION_COMPRESSED)
508 && (form != POINT_CONVERSION_UNCOMPRESSED)
509 && (form != POINT_CONVERSION_HYBRID))
510 {
511 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
512 goto err;
513 }
514
515 if (EC_POINT_is_at_infinity(group, point))
516 {
517 /* encodes to a single 0 octet */
518 if (buf != NULL)
519 {
520 if (len < 1)
521 {
522 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
523 return 0;
524 }
525 buf[0] = 0;
526 }
527 return 1;
528 }
529
530
531 /* ret := required output buffer length */
532 field_len = (EC_GROUP_get_degree(group) + 7) / 8;
533 ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
534
535 /* if 'buf' is NULL, just return required length */
536 if (buf != NULL)
537 {
538 if (len < ret)
539 {
540 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
541 goto err;
542 }
543
544 if (ctx == NULL)
545 {
546 ctx = new_ctx = BN_CTX_new();
547 if (ctx == NULL)
548 return 0;
549 }
550
551 BN_CTX_start(ctx);
552 used_ctx = 1;
553 x = BN_CTX_get(ctx);
554 y = BN_CTX_get(ctx);
555 yxi = BN_CTX_get(ctx);
556 if (yxi == NULL) goto err;
557
558 if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
559
560 buf[0] = form;
561 if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x))
562 {
563 if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
564 if (BN_is_odd(yxi)) buf[0]++;
565 }
566
567 i = 1;
568
569 skip = field_len - BN_num_bytes(x);
570 if (skip > field_len)
571 {
572 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
573 goto err;
574 }
575 while (skip > 0)
576 {
577 buf[i++] = 0;
578 skip--;
579 }
580 skip = BN_bn2bin(x, buf + i);
581 i += skip;
582 if (i != 1 + field_len)
583 {
584 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
585 goto err;
586 }
587
588 if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
589 {
590 skip = field_len - BN_num_bytes(y);
591 if (skip > field_len)
592 {
593 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
594 goto err;
595 }
596 while (skip > 0)
597 {
598 buf[i++] = 0;
599 skip--;
600 }
601 skip = BN_bn2bin(y, buf + i);
602 i += skip;
603 }
604
605 if (i != ret)
606 {
607 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
608 goto err;
609 }
610 }
611
612 if (used_ctx)
613 BN_CTX_end(ctx);
614 if (new_ctx != NULL)
615 BN_CTX_free(new_ctx);
616 return ret;
617
618 err:
619 if (used_ctx)
620 BN_CTX_end(ctx);
621 if (new_ctx != NULL)
622 BN_CTX_free(new_ctx);
623 return 0;
624 }
625
626
627/* Converts an octet string representation to an EC_POINT.
628 * Note that the simple implementation only uses affine coordinates.
629 */
630int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
631 const unsigned char *buf, size_t len, BN_CTX *ctx)
632 {
633 point_conversion_form_t form;
634 int y_bit;
635 BN_CTX *new_ctx = NULL;
636 BIGNUM *x, *y, *yxi;
637 size_t field_len, enc_len;
638 int ret = 0;
639
640 if (len == 0)
641 {
642 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
643 return 0;
644 }
645 form = buf[0];
646 y_bit = form & 1;
647 form = form & ~1U;
648 if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
649 && (form != POINT_CONVERSION_UNCOMPRESSED)
650 && (form != POINT_CONVERSION_HYBRID))
651 {
652 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
653 return 0;
654 }
655 if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
656 {
657 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
658 return 0;
659 }
660
661 if (form == 0)
662 {
663 if (len != 1)
664 {
665 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
666 return 0;
667 }
668
669 return EC_POINT_set_to_infinity(group, point);
670 }
671
672 field_len = (EC_GROUP_get_degree(group) + 7) / 8;
673 enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
674
675 if (len != enc_len)
676 {
677 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
678 return 0;
679 }
680
681 if (ctx == NULL)
682 {
683 ctx = new_ctx = BN_CTX_new();
684 if (ctx == NULL)
685 return 0;
686 }
687
688 BN_CTX_start(ctx);
689 x = BN_CTX_get(ctx);
690 y = BN_CTX_get(ctx);
691 yxi = BN_CTX_get(ctx);
692 if (yxi == NULL) goto err;
693
694 if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
695 if (BN_ucmp(x, &group->field) >= 0)
696 {
697 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
698 goto err;
699 }
700
701 if (form == POINT_CONVERSION_COMPRESSED)
702 {
703 if (!EC_POINT_set_compressed_coordinates_GF2m(group, point, x, y_bit, ctx)) goto err;
704 }
705 else
706 {
707 if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
708 if (BN_ucmp(y, &group->field) >= 0)
709 {
710 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
711 goto err;
712 }
713 if (form == POINT_CONVERSION_HYBRID)
714 {
715 if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
716 if (y_bit != BN_is_odd(yxi))
717 {
718 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
719 goto err;
720 }
721 }
722
723 if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
724 }
725
726 if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
727 {
728 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
729 goto err;
730 }
731
732 ret = 1;
733
734 err:
735 BN_CTX_end(ctx);
736 if (new_ctx != NULL)
737 BN_CTX_free(new_ctx);
738 return ret;
739 }
740
741
742/* Computes a + b and stores the result in r. r could be a or b, a could be b. 417/* Computes a + b and stores the result in r. r could be a or b, a could be b.
743 * Uses algorithm A.10.2 of IEEE P1363. 418 * Uses algorithm A.10.2 of IEEE P1363.
744 */ 419 */
@@ -1040,3 +715,5 @@ int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
1040 { 715 {
1041 return BN_GF2m_mod_div(r, a, b, &group->field, ctx); 716 return BN_GF2m_mod_div(r, a, b, &group->field, ctx);
1042 } 717 }
718
719#endif
diff --git a/src/lib/libcrypto/ec/ec_cvt.c b/src/lib/libcrypto/ec/ec_cvt.c
index d45640bab9..bfcbab35fe 100644
--- a/src/lib/libcrypto/ec/ec_cvt.c
+++ b/src/lib/libcrypto/ec/ec_cvt.c
@@ -78,7 +78,32 @@ EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM
78 const EC_METHOD *meth; 78 const EC_METHOD *meth;
79 EC_GROUP *ret; 79 EC_GROUP *ret;
80 80
81#if defined(OPENSSL_BN_ASM_MONT)
82 /*
83 * This might appear controversial, but the fact is that generic
84 * prime method was observed to deliver better performance even
85 * for NIST primes on a range of platforms, e.g.: 60%-15%
86 * improvement on IA-64, ~25% on ARM, 30%-90% on P4, 20%-25%
87 * in 32-bit build and 35%--12% in 64-bit build on Core2...
88 * Coefficients are relative to optimized bn_nist.c for most
89 * intensive ECDSA verify and ECDH operations for 192- and 521-
90 * bit keys respectively. Choice of these boundary values is
91 * arguable, because the dependency of improvement coefficient
92 * from key length is not a "monotone" curve. For example while
93 * 571-bit result is 23% on ARM, 384-bit one is -1%. But it's
94 * generally faster, sometimes "respectfully" faster, sometimes
95 * "tolerably" slower... What effectively happens is that loop
96 * with bn_mul_add_words is put against bn_mul_mont, and the
97 * latter "wins" on short vectors. Correct solution should be
98 * implementing dedicated NxN multiplication subroutines for
99 * small N. But till it materializes, let's stick to generic
100 * prime method...
101 * <appro>
102 */
103 meth = EC_GFp_mont_method();
104#else
81 meth = EC_GFp_nist_method(); 105 meth = EC_GFp_nist_method();
106#endif
82 107
83 ret = EC_GROUP_new(meth); 108 ret = EC_GROUP_new(meth);
84 if (ret == NULL) 109 if (ret == NULL)
@@ -122,7 +147,7 @@ EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM
122 return ret; 147 return ret;
123 } 148 }
124 149
125 150#ifndef OPENSSL_NO_EC2M
126EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) 151EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
127 { 152 {
128 const EC_METHOD *meth; 153 const EC_METHOD *meth;
@@ -142,3 +167,4 @@ EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM
142 167
143 return ret; 168 return ret;
144 } 169 }
170#endif
diff --git a/src/lib/libcrypto/ec/ec_err.c b/src/lib/libcrypto/ec/ec_err.c
index 84b4833371..0d19398731 100644
--- a/src/lib/libcrypto/ec/ec_err.c
+++ b/src/lib/libcrypto/ec/ec_err.c
@@ -1,6 +1,6 @@
1/* crypto/ec/ec_err.c */ 1/* crypto/ec/ec_err.c */
2/* ==================================================================== 2/* ====================================================================
3 * Copyright (c) 1999-2007 The OpenSSL Project. All rights reserved. 3 * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
@@ -70,6 +70,7 @@
70 70
71static ERR_STRING_DATA EC_str_functs[]= 71static ERR_STRING_DATA EC_str_functs[]=
72 { 72 {
73{ERR_FUNC(EC_F_BN_TO_FELEM), "BN_TO_FELEM"},
73{ERR_FUNC(EC_F_COMPUTE_WNAF), "COMPUTE_WNAF"}, 74{ERR_FUNC(EC_F_COMPUTE_WNAF), "COMPUTE_WNAF"},
74{ERR_FUNC(EC_F_D2I_ECPARAMETERS), "d2i_ECParameters"}, 75{ERR_FUNC(EC_F_D2I_ECPARAMETERS), "d2i_ECParameters"},
75{ERR_FUNC(EC_F_D2I_ECPKPARAMETERS), "d2i_ECPKParameters"}, 76{ERR_FUNC(EC_F_D2I_ECPKPARAMETERS), "d2i_ECPKParameters"},
@@ -112,6 +113,15 @@ static ERR_STRING_DATA EC_str_functs[]=
112{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_SQR), "ec_GFp_mont_field_sqr"}, 113{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_SQR), "ec_GFp_mont_field_sqr"},
113{ERR_FUNC(EC_F_EC_GFP_MONT_GROUP_SET_CURVE), "ec_GFp_mont_group_set_curve"}, 114{ERR_FUNC(EC_F_EC_GFP_MONT_GROUP_SET_CURVE), "ec_GFp_mont_group_set_curve"},
114{ERR_FUNC(EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP), "EC_GFP_MONT_GROUP_SET_CURVE_GFP"}, 115{ERR_FUNC(EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP), "EC_GFP_MONT_GROUP_SET_CURVE_GFP"},
116{ERR_FUNC(EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE), "ec_GFp_nistp224_group_set_curve"},
117{ERR_FUNC(EC_F_EC_GFP_NISTP224_POINTS_MUL), "ec_GFp_nistp224_points_mul"},
118{ERR_FUNC(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES), "ec_GFp_nistp224_point_get_affine_coordinates"},
119{ERR_FUNC(EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE), "ec_GFp_nistp256_group_set_curve"},
120{ERR_FUNC(EC_F_EC_GFP_NISTP256_POINTS_MUL), "ec_GFp_nistp256_points_mul"},
121{ERR_FUNC(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES), "ec_GFp_nistp256_point_get_affine_coordinates"},
122{ERR_FUNC(EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE), "ec_GFp_nistp521_group_set_curve"},
123{ERR_FUNC(EC_F_EC_GFP_NISTP521_POINTS_MUL), "ec_GFp_nistp521_points_mul"},
124{ERR_FUNC(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES), "ec_GFp_nistp521_point_get_affine_coordinates"},
115{ERR_FUNC(EC_F_EC_GFP_NIST_FIELD_MUL), "ec_GFp_nist_field_mul"}, 125{ERR_FUNC(EC_F_EC_GFP_NIST_FIELD_MUL), "ec_GFp_nist_field_mul"},
116{ERR_FUNC(EC_F_EC_GFP_NIST_FIELD_SQR), "ec_GFp_nist_field_sqr"}, 126{ERR_FUNC(EC_F_EC_GFP_NIST_FIELD_SQR), "ec_GFp_nist_field_sqr"},
117{ERR_FUNC(EC_F_EC_GFP_NIST_GROUP_SET_CURVE), "ec_GFp_nist_group_set_curve"}, 127{ERR_FUNC(EC_F_EC_GFP_NIST_GROUP_SET_CURVE), "ec_GFp_nist_group_set_curve"},
@@ -154,6 +164,7 @@ static ERR_STRING_DATA EC_str_functs[]=
154{ERR_FUNC(EC_F_EC_KEY_NEW), "EC_KEY_new"}, 164{ERR_FUNC(EC_F_EC_KEY_NEW), "EC_KEY_new"},
155{ERR_FUNC(EC_F_EC_KEY_PRINT), "EC_KEY_print"}, 165{ERR_FUNC(EC_F_EC_KEY_PRINT), "EC_KEY_print"},
156{ERR_FUNC(EC_F_EC_KEY_PRINT_FP), "EC_KEY_print_fp"}, 166{ERR_FUNC(EC_F_EC_KEY_PRINT_FP), "EC_KEY_print_fp"},
167{ERR_FUNC(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES), "EC_KEY_set_public_key_affine_coordinates"},
157{ERR_FUNC(EC_F_EC_POINTS_MAKE_AFFINE), "EC_POINTs_make_affine"}, 168{ERR_FUNC(EC_F_EC_POINTS_MAKE_AFFINE), "EC_POINTs_make_affine"},
158{ERR_FUNC(EC_F_EC_POINT_ADD), "EC_POINT_add"}, 169{ERR_FUNC(EC_F_EC_POINT_ADD), "EC_POINT_add"},
159{ERR_FUNC(EC_F_EC_POINT_CMP), "EC_POINT_cmp"}, 170{ERR_FUNC(EC_F_EC_POINT_CMP), "EC_POINT_cmp"},
@@ -184,6 +195,9 @@ static ERR_STRING_DATA EC_str_functs[]=
184{ERR_FUNC(EC_F_I2D_ECPKPARAMETERS), "i2d_ECPKParameters"}, 195{ERR_FUNC(EC_F_I2D_ECPKPARAMETERS), "i2d_ECPKParameters"},
185{ERR_FUNC(EC_F_I2D_ECPRIVATEKEY), "i2d_ECPrivateKey"}, 196{ERR_FUNC(EC_F_I2D_ECPRIVATEKEY), "i2d_ECPrivateKey"},
186{ERR_FUNC(EC_F_I2O_ECPUBLICKEY), "i2o_ECPublicKey"}, 197{ERR_FUNC(EC_F_I2O_ECPUBLICKEY), "i2o_ECPublicKey"},
198{ERR_FUNC(EC_F_NISTP224_PRE_COMP_NEW), "NISTP224_PRE_COMP_NEW"},
199{ERR_FUNC(EC_F_NISTP256_PRE_COMP_NEW), "NISTP256_PRE_COMP_NEW"},
200{ERR_FUNC(EC_F_NISTP521_PRE_COMP_NEW), "NISTP521_PRE_COMP_NEW"},
187{ERR_FUNC(EC_F_O2I_ECPUBLICKEY), "o2i_ECPublicKey"}, 201{ERR_FUNC(EC_F_O2I_ECPUBLICKEY), "o2i_ECPublicKey"},
188{ERR_FUNC(EC_F_OLD_EC_PRIV_DECODE), "OLD_EC_PRIV_DECODE"}, 202{ERR_FUNC(EC_F_OLD_EC_PRIV_DECODE), "OLD_EC_PRIV_DECODE"},
189{ERR_FUNC(EC_F_PKEY_EC_CTRL), "PKEY_EC_CTRL"}, 203{ERR_FUNC(EC_F_PKEY_EC_CTRL), "PKEY_EC_CTRL"},
@@ -199,12 +213,15 @@ static ERR_STRING_DATA EC_str_reasons[]=
199 { 213 {
200{ERR_REASON(EC_R_ASN1_ERROR) ,"asn1 error"}, 214{ERR_REASON(EC_R_ASN1_ERROR) ,"asn1 error"},
201{ERR_REASON(EC_R_ASN1_UNKNOWN_FIELD) ,"asn1 unknown field"}, 215{ERR_REASON(EC_R_ASN1_UNKNOWN_FIELD) ,"asn1 unknown field"},
216{ERR_REASON(EC_R_BIGNUM_OUT_OF_RANGE) ,"bignum out of range"},
202{ERR_REASON(EC_R_BUFFER_TOO_SMALL) ,"buffer too small"}, 217{ERR_REASON(EC_R_BUFFER_TOO_SMALL) ,"buffer too small"},
218{ERR_REASON(EC_R_COORDINATES_OUT_OF_RANGE),"coordinates out of range"},
203{ERR_REASON(EC_R_D2I_ECPKPARAMETERS_FAILURE),"d2i ecpkparameters failure"}, 219{ERR_REASON(EC_R_D2I_ECPKPARAMETERS_FAILURE),"d2i ecpkparameters failure"},
204{ERR_REASON(EC_R_DECODE_ERROR) ,"decode error"}, 220{ERR_REASON(EC_R_DECODE_ERROR) ,"decode error"},
205{ERR_REASON(EC_R_DISCRIMINANT_IS_ZERO) ,"discriminant is zero"}, 221{ERR_REASON(EC_R_DISCRIMINANT_IS_ZERO) ,"discriminant is zero"},
206{ERR_REASON(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE),"ec group new by name failure"}, 222{ERR_REASON(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE),"ec group new by name failure"},
207{ERR_REASON(EC_R_FIELD_TOO_LARGE) ,"field too large"}, 223{ERR_REASON(EC_R_FIELD_TOO_LARGE) ,"field too large"},
224{ERR_REASON(EC_R_GF2M_NOT_SUPPORTED) ,"gf2m not supported"},
208{ERR_REASON(EC_R_GROUP2PKPARAMETERS_FAILURE),"group2pkparameters failure"}, 225{ERR_REASON(EC_R_GROUP2PKPARAMETERS_FAILURE),"group2pkparameters failure"},
209{ERR_REASON(EC_R_I2D_ECPKPARAMETERS_FAILURE),"i2d ecpkparameters failure"}, 226{ERR_REASON(EC_R_I2D_ECPKPARAMETERS_FAILURE),"i2d ecpkparameters failure"},
210{ERR_REASON(EC_R_INCOMPATIBLE_OBJECTS) ,"incompatible objects"}, 227{ERR_REASON(EC_R_INCOMPATIBLE_OBJECTS) ,"incompatible objects"},
@@ -239,6 +256,7 @@ static ERR_STRING_DATA EC_str_reasons[]=
239{ERR_REASON(EC_R_UNKNOWN_GROUP) ,"unknown group"}, 256{ERR_REASON(EC_R_UNKNOWN_GROUP) ,"unknown group"},
240{ERR_REASON(EC_R_UNKNOWN_ORDER) ,"unknown order"}, 257{ERR_REASON(EC_R_UNKNOWN_ORDER) ,"unknown order"},
241{ERR_REASON(EC_R_UNSUPPORTED_FIELD) ,"unsupported field"}, 258{ERR_REASON(EC_R_UNSUPPORTED_FIELD) ,"unsupported field"},
259{ERR_REASON(EC_R_WRONG_CURVE_PARAMETERS) ,"wrong curve parameters"},
242{ERR_REASON(EC_R_WRONG_ORDER) ,"wrong order"}, 260{ERR_REASON(EC_R_WRONG_ORDER) ,"wrong order"},
243{0,NULL} 261{0,NULL}
244 }; 262 };
diff --git a/src/lib/libcrypto/ec/ec_lcl.h b/src/lib/libcrypto/ec/ec_lcl.h
index 3e2c34b0bc..da7967df38 100644
--- a/src/lib/libcrypto/ec/ec_lcl.h
+++ b/src/lib/libcrypto/ec/ec_lcl.h
@@ -3,7 +3,7 @@
3 * Originally written by Bodo Moeller for the OpenSSL project. 3 * Originally written by Bodo Moeller for the OpenSSL project.
4 */ 4 */
5/* ==================================================================== 5/* ====================================================================
6 * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. 6 * Copyright (c) 1998-2010 The OpenSSL Project. All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
@@ -82,10 +82,15 @@
82# endif 82# endif
83#endif 83#endif
84 84
85/* Use default functions for poin2oct, oct2point and compressed coordinates */
86#define EC_FLAGS_DEFAULT_OCT 0x1
87
85/* Structure details are not part of the exported interface, 88/* Structure details are not part of the exported interface,
86 * so all this may change in future versions. */ 89 * so all this may change in future versions. */
87 90
88struct ec_method_st { 91struct ec_method_st {
92 /* Various method flags */
93 int flags;
89 /* used by EC_METHOD_get_field_type: */ 94 /* used by EC_METHOD_get_field_type: */
90 int field_type; /* a NID */ 95 int field_type; /* a NID */
91 96
@@ -244,6 +249,7 @@ struct ec_key_st {
244 point_conversion_form_t conv_form; 249 point_conversion_form_t conv_form;
245 250
246 int references; 251 int references;
252 int flags;
247 253
248 EC_EXTRA_DATA *method_data; 254 EC_EXTRA_DATA *method_data;
249} /* EC_KEY */; 255} /* EC_KEY */;
@@ -391,3 +397,50 @@ int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
391 size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *); 397 size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *);
392int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx); 398int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
393int ec_GF2m_have_precompute_mult(const EC_GROUP *group); 399int ec_GF2m_have_precompute_mult(const EC_GROUP *group);
400
401/* method functions in ec2_mult.c */
402int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
403 size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *);
404int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
405int ec_GF2m_have_precompute_mult(const EC_GROUP *group);
406
407#ifndef OPENSSL_EC_NISTP_64_GCC_128
408/* method functions in ecp_nistp224.c */
409int ec_GFp_nistp224_group_init(EC_GROUP *group);
410int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *n, BN_CTX *);
411int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx);
412int 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 *);
413int 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);
414int ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
415int ec_GFp_nistp224_have_precompute_mult(const EC_GROUP *group);
416
417/* method functions in ecp_nistp256.c */
418int ec_GFp_nistp256_group_init(EC_GROUP *group);
419int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *n, BN_CTX *);
420int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx);
421int 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 *);
422int 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);
423int ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
424int ec_GFp_nistp256_have_precompute_mult(const EC_GROUP *group);
425
426/* method functions in ecp_nistp521.c */
427int ec_GFp_nistp521_group_init(EC_GROUP *group);
428int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *n, BN_CTX *);
429int ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx);
430int 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 *);
431int 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);
432int ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
433int ec_GFp_nistp521_have_precompute_mult(const EC_GROUP *group);
434
435/* utility functions in ecp_nistputil.c */
436void ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array,
437 size_t felem_size, void *tmp_felems,
438 void (*felem_one)(void *out),
439 int (*felem_is_zero)(const void *in),
440 void (*felem_assign)(void *out, const void *in),
441 void (*felem_square)(void *out, const void *in),
442 void (*felem_mul)(void *out, const void *in1, const void *in2),
443 void (*felem_inv)(void *out, const void *in),
444 void (*felem_contract)(void *out, const void *in));
445void ec_GFp_nistp_recode_scalar_bits(unsigned char *sign, unsigned char *digit, unsigned char in);
446#endif
diff --git a/src/lib/libcrypto/ec/ec_lib.c b/src/lib/libcrypto/ec/ec_lib.c
index dd7da0fcf9..25247b5803 100644
--- a/src/lib/libcrypto/ec/ec_lib.c
+++ b/src/lib/libcrypto/ec/ec_lib.c
@@ -425,7 +425,7 @@ int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *
425 return group->meth->group_get_curve(group, p, a, b, ctx); 425 return group->meth->group_get_curve(group, p, a, b, ctx);
426 } 426 }
427 427
428 428#ifndef OPENSSL_NO_EC2M
429int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) 429int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
430 { 430 {
431 if (group->meth->group_set_curve == 0) 431 if (group->meth->group_set_curve == 0)
@@ -446,7 +446,7 @@ int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM
446 } 446 }
447 return group->meth->group_get_curve(group, p, a, b, ctx); 447 return group->meth->group_get_curve(group, p, a, b, ctx);
448 } 448 }
449 449#endif
450 450
451int EC_GROUP_get_degree(const EC_GROUP *group) 451int EC_GROUP_get_degree(const EC_GROUP *group)
452 { 452 {
@@ -856,7 +856,7 @@ int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
856 return group->meth->point_set_affine_coordinates(group, point, x, y, ctx); 856 return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
857 } 857 }
858 858
859 859#ifndef OPENSSL_NO_EC2M
860int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point, 860int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point,
861 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) 861 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
862 { 862 {
@@ -872,7 +872,7 @@ int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point,
872 } 872 }
873 return group->meth->point_set_affine_coordinates(group, point, x, y, ctx); 873 return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
874 } 874 }
875 875#endif
876 876
877int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point, 877int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
878 BIGNUM *x, BIGNUM *y, BN_CTX *ctx) 878 BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
@@ -890,7 +890,7 @@ int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *p
890 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); 890 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
891 } 891 }
892 892
893 893#ifndef OPENSSL_NO_EC2M
894int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, const EC_POINT *point, 894int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, const EC_POINT *point,
895 BIGNUM *x, BIGNUM *y, BN_CTX *ctx) 895 BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
896 { 896 {
@@ -906,75 +906,7 @@ int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, const EC_POINT *
906 } 906 }
907 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); 907 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
908 } 908 }
909 909#endif
910
911int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
912 const BIGNUM *x, int y_bit, BN_CTX *ctx)
913 {
914 if (group->meth->point_set_compressed_coordinates == 0)
915 {
916 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
917 return 0;
918 }
919 if (group->meth != point->meth)
920 {
921 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
922 return 0;
923 }
924 return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx);
925 }
926
927
928int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point,
929 const BIGNUM *x, int y_bit, BN_CTX *ctx)
930 {
931 if (group->meth->point_set_compressed_coordinates == 0)
932 {
933 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
934 return 0;
935 }
936 if (group->meth != point->meth)
937 {
938 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
939 return 0;
940 }
941 return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx);
942 }
943
944
945size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
946 unsigned char *buf, size_t len, BN_CTX *ctx)
947 {
948 if (group->meth->point2oct == 0)
949 {
950 ECerr(EC_F_EC_POINT_POINT2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
951 return 0;
952 }
953 if (group->meth != point->meth)
954 {
955 ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_INCOMPATIBLE_OBJECTS);
956 return 0;
957 }
958 return group->meth->point2oct(group, point, form, buf, len, ctx);
959 }
960
961
962int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
963 const unsigned char *buf, size_t len, BN_CTX *ctx)
964 {
965 if (group->meth->oct2point == 0)
966 {
967 ECerr(EC_F_EC_POINT_OCT2POINT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
968 return 0;
969 }
970 if (group->meth != point->meth)
971 {
972 ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_INCOMPATIBLE_OBJECTS);
973 return 0;
974 }
975 return group->meth->oct2point(group, point, buf, len, ctx);
976 }
977
978 910
979int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) 911int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
980 { 912 {
diff --git a/src/lib/libcrypto/ec/ecp_mont.c b/src/lib/libcrypto/ec/ecp_mont.c
index 9fc4a466a5..079e47431b 100644
--- a/src/lib/libcrypto/ec/ecp_mont.c
+++ b/src/lib/libcrypto/ec/ecp_mont.c
@@ -63,12 +63,20 @@
63 63
64#include <openssl/err.h> 64#include <openssl/err.h>
65 65
66#ifdef OPENSSL_FIPS
67#include <openssl/fips.h>
68#endif
69
66#include "ec_lcl.h" 70#include "ec_lcl.h"
67 71
68 72
69const EC_METHOD *EC_GFp_mont_method(void) 73const EC_METHOD *EC_GFp_mont_method(void)
70 { 74 {
75#ifdef OPENSSL_FIPS
76 return fips_ec_gfp_mont_method();
77#else
71 static const EC_METHOD ret = { 78 static const EC_METHOD ret = {
79 EC_FLAGS_DEFAULT_OCT,
72 NID_X9_62_prime_field, 80 NID_X9_62_prime_field,
73 ec_GFp_mont_group_init, 81 ec_GFp_mont_group_init,
74 ec_GFp_mont_group_finish, 82 ec_GFp_mont_group_finish,
@@ -87,9 +95,7 @@ const EC_METHOD *EC_GFp_mont_method(void)
87 ec_GFp_simple_get_Jprojective_coordinates_GFp, 95 ec_GFp_simple_get_Jprojective_coordinates_GFp,
88 ec_GFp_simple_point_set_affine_coordinates, 96 ec_GFp_simple_point_set_affine_coordinates,
89 ec_GFp_simple_point_get_affine_coordinates, 97 ec_GFp_simple_point_get_affine_coordinates,
90 ec_GFp_simple_set_compressed_coordinates, 98 0,0,0,
91 ec_GFp_simple_point2oct,
92 ec_GFp_simple_oct2point,
93 ec_GFp_simple_add, 99 ec_GFp_simple_add,
94 ec_GFp_simple_dbl, 100 ec_GFp_simple_dbl,
95 ec_GFp_simple_invert, 101 ec_GFp_simple_invert,
@@ -108,7 +114,9 @@ const EC_METHOD *EC_GFp_mont_method(void)
108 ec_GFp_mont_field_decode, 114 ec_GFp_mont_field_decode,
109 ec_GFp_mont_field_set_to_one }; 115 ec_GFp_mont_field_set_to_one };
110 116
117
111 return &ret; 118 return &ret;
119#endif
112 } 120 }
113 121
114 122
diff --git a/src/lib/libcrypto/ec/ecp_nist.c b/src/lib/libcrypto/ec/ecp_nist.c
index 2a5682ea41..aad2d5f443 100644
--- a/src/lib/libcrypto/ec/ecp_nist.c
+++ b/src/lib/libcrypto/ec/ecp_nist.c
@@ -67,9 +67,17 @@
67#include <openssl/obj_mac.h> 67#include <openssl/obj_mac.h>
68#include "ec_lcl.h" 68#include "ec_lcl.h"
69 69
70#ifdef OPENSSL_FIPS
71#include <openssl/fips.h>
72#endif
73
70const EC_METHOD *EC_GFp_nist_method(void) 74const EC_METHOD *EC_GFp_nist_method(void)
71 { 75 {
76#ifdef OPENSSL_FIPS
77 return fips_ec_gfp_nist_method();
78#else
72 static const EC_METHOD ret = { 79 static const EC_METHOD ret = {
80 EC_FLAGS_DEFAULT_OCT,
73 NID_X9_62_prime_field, 81 NID_X9_62_prime_field,
74 ec_GFp_simple_group_init, 82 ec_GFp_simple_group_init,
75 ec_GFp_simple_group_finish, 83 ec_GFp_simple_group_finish,
@@ -88,9 +96,7 @@ const EC_METHOD *EC_GFp_nist_method(void)
88 ec_GFp_simple_get_Jprojective_coordinates_GFp, 96 ec_GFp_simple_get_Jprojective_coordinates_GFp,
89 ec_GFp_simple_point_set_affine_coordinates, 97 ec_GFp_simple_point_set_affine_coordinates,
90 ec_GFp_simple_point_get_affine_coordinates, 98 ec_GFp_simple_point_get_affine_coordinates,
91 ec_GFp_simple_set_compressed_coordinates, 99 0,0,0,
92 ec_GFp_simple_point2oct,
93 ec_GFp_simple_oct2point,
94 ec_GFp_simple_add, 100 ec_GFp_simple_add,
95 ec_GFp_simple_dbl, 101 ec_GFp_simple_dbl,
96 ec_GFp_simple_invert, 102 ec_GFp_simple_invert,
@@ -110,6 +116,7 @@ const EC_METHOD *EC_GFp_nist_method(void)
110 0 /* field_set_to_one */ }; 116 0 /* field_set_to_one */ };
111 117
112 return &ret; 118 return &ret;
119#endif
113 } 120 }
114 121
115int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src) 122int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src)
diff --git a/src/lib/libcrypto/ec/ecp_smpl.c b/src/lib/libcrypto/ec/ecp_smpl.c
index 66a92e2a90..7cbb321f9a 100644
--- a/src/lib/libcrypto/ec/ecp_smpl.c
+++ b/src/lib/libcrypto/ec/ecp_smpl.c
@@ -65,11 +65,19 @@
65#include <openssl/err.h> 65#include <openssl/err.h>
66#include <openssl/symhacks.h> 66#include <openssl/symhacks.h>
67 67
68#ifdef OPENSSL_FIPS
69#include <openssl/fips.h>
70#endif
71
68#include "ec_lcl.h" 72#include "ec_lcl.h"
69 73
70const EC_METHOD *EC_GFp_simple_method(void) 74const EC_METHOD *EC_GFp_simple_method(void)
71 { 75 {
76#ifdef OPENSSL_FIPS
77 return fips_ec_gfp_simple_method();
78#else
72 static const EC_METHOD ret = { 79 static const EC_METHOD ret = {
80 EC_FLAGS_DEFAULT_OCT,
73 NID_X9_62_prime_field, 81 NID_X9_62_prime_field,
74 ec_GFp_simple_group_init, 82 ec_GFp_simple_group_init,
75 ec_GFp_simple_group_finish, 83 ec_GFp_simple_group_finish,
@@ -88,9 +96,7 @@ const EC_METHOD *EC_GFp_simple_method(void)
88 ec_GFp_simple_get_Jprojective_coordinates_GFp, 96 ec_GFp_simple_get_Jprojective_coordinates_GFp,
89 ec_GFp_simple_point_set_affine_coordinates, 97 ec_GFp_simple_point_set_affine_coordinates,
90 ec_GFp_simple_point_get_affine_coordinates, 98 ec_GFp_simple_point_get_affine_coordinates,
91 ec_GFp_simple_set_compressed_coordinates, 99 0,0,0,
92 ec_GFp_simple_point2oct,
93 ec_GFp_simple_oct2point,
94 ec_GFp_simple_add, 100 ec_GFp_simple_add,
95 ec_GFp_simple_dbl, 101 ec_GFp_simple_dbl,
96 ec_GFp_simple_invert, 102 ec_GFp_simple_invert,
@@ -110,6 +116,7 @@ const EC_METHOD *EC_GFp_simple_method(void)
110 0 /* field_set_to_one */ }; 116 0 /* field_set_to_one */ };
111 117
112 return &ret; 118 return &ret;
119#endif
113 } 120 }
114 121
115 122
@@ -633,372 +640,6 @@ int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_P
633 return ret; 640 return ret;
634 } 641 }
635 642
636
637int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
638 const BIGNUM *x_, int y_bit, BN_CTX *ctx)
639 {
640 BN_CTX *new_ctx = NULL;
641 BIGNUM *tmp1, *tmp2, *x, *y;
642 int ret = 0;
643
644 /* clear error queue*/
645 ERR_clear_error();
646
647 if (ctx == NULL)
648 {
649 ctx = new_ctx = BN_CTX_new();
650 if (ctx == NULL)
651 return 0;
652 }
653
654 y_bit = (y_bit != 0);
655
656 BN_CTX_start(ctx);
657 tmp1 = BN_CTX_get(ctx);
658 tmp2 = BN_CTX_get(ctx);
659 x = BN_CTX_get(ctx);
660 y = BN_CTX_get(ctx);
661 if (y == NULL) goto err;
662
663 /* Recover y. We have a Weierstrass equation
664 * y^2 = x^3 + a*x + b,
665 * so y is one of the square roots of x^3 + a*x + b.
666 */
667
668 /* tmp1 := x^3 */
669 if (!BN_nnmod(x, x_, &group->field,ctx)) goto err;
670 if (group->meth->field_decode == 0)
671 {
672 /* field_{sqr,mul} work on standard representation */
673 if (!group->meth->field_sqr(group, tmp2, x_, ctx)) goto err;
674 if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx)) goto err;
675 }
676 else
677 {
678 if (!BN_mod_sqr(tmp2, x_, &group->field, ctx)) goto err;
679 if (!BN_mod_mul(tmp1, tmp2, x_, &group->field, ctx)) goto err;
680 }
681
682 /* tmp1 := tmp1 + a*x */
683 if (group->a_is_minus3)
684 {
685 if (!BN_mod_lshift1_quick(tmp2, x, &group->field)) goto err;
686 if (!BN_mod_add_quick(tmp2, tmp2, x, &group->field)) goto err;
687 if (!BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
688 }
689 else
690 {
691 if (group->meth->field_decode)
692 {
693 if (!group->meth->field_decode(group, tmp2, &group->a, ctx)) goto err;
694 if (!BN_mod_mul(tmp2, tmp2, x, &group->field, ctx)) goto err;
695 }
696 else
697 {
698 /* field_mul works on standard representation */
699 if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx)) goto err;
700 }
701
702 if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
703 }
704
705 /* tmp1 := tmp1 + b */
706 if (group->meth->field_decode)
707 {
708 if (!group->meth->field_decode(group, tmp2, &group->b, ctx)) goto err;
709 if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
710 }
711 else
712 {
713 if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field)) goto err;
714 }
715
716 if (!BN_mod_sqrt(y, tmp1, &group->field, ctx))
717 {
718 unsigned long err = ERR_peek_last_error();
719
720 if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE)
721 {
722 ERR_clear_error();
723 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
724 }
725 else
726 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
727 goto err;
728 }
729
730 if (y_bit != BN_is_odd(y))
731 {
732 if (BN_is_zero(y))
733 {
734 int kron;
735
736 kron = BN_kronecker(x, &group->field, ctx);
737 if (kron == -2) goto err;
738
739 if (kron == 1)
740 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSION_BIT);
741 else
742 /* BN_mod_sqrt() should have cought this error (not a square) */
743 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
744 goto err;
745 }
746 if (!BN_usub(y, &group->field, y)) goto err;
747 }
748 if (y_bit != BN_is_odd(y))
749 {
750 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_INTERNAL_ERROR);
751 goto err;
752 }
753
754 if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
755
756 ret = 1;
757
758 err:
759 BN_CTX_end(ctx);
760 if (new_ctx != NULL)
761 BN_CTX_free(new_ctx);
762 return ret;
763 }
764
765
766size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
767 unsigned char *buf, size_t len, BN_CTX *ctx)
768 {
769 size_t ret;
770 BN_CTX *new_ctx = NULL;
771 int used_ctx = 0;
772 BIGNUM *x, *y;
773 size_t field_len, i, skip;
774
775 if ((form != POINT_CONVERSION_COMPRESSED)
776 && (form != POINT_CONVERSION_UNCOMPRESSED)
777 && (form != POINT_CONVERSION_HYBRID))
778 {
779 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
780 goto err;
781 }
782
783 if (EC_POINT_is_at_infinity(group, point))
784 {
785 /* encodes to a single 0 octet */
786 if (buf != NULL)
787 {
788 if (len < 1)
789 {
790 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
791 return 0;
792 }
793 buf[0] = 0;
794 }
795 return 1;
796 }
797
798
799 /* ret := required output buffer length */
800 field_len = BN_num_bytes(&group->field);
801 ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
802
803 /* if 'buf' is NULL, just return required length */
804 if (buf != NULL)
805 {
806 if (len < ret)
807 {
808 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
809 goto err;
810 }
811
812 if (ctx == NULL)
813 {
814 ctx = new_ctx = BN_CTX_new();
815 if (ctx == NULL)
816 return 0;
817 }
818
819 BN_CTX_start(ctx);
820 used_ctx = 1;
821 x = BN_CTX_get(ctx);
822 y = BN_CTX_get(ctx);
823 if (y == NULL) goto err;
824
825 if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
826
827 if ((form == POINT_CONVERSION_COMPRESSED || form == POINT_CONVERSION_HYBRID) && BN_is_odd(y))
828 buf[0] = form + 1;
829 else
830 buf[0] = form;
831
832 i = 1;
833
834 skip = field_len - BN_num_bytes(x);
835 if (skip > field_len)
836 {
837 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
838 goto err;
839 }
840 while (skip > 0)
841 {
842 buf[i++] = 0;
843 skip--;
844 }
845 skip = BN_bn2bin(x, buf + i);
846 i += skip;
847 if (i != 1 + field_len)
848 {
849 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
850 goto err;
851 }
852
853 if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
854 {
855 skip = field_len - BN_num_bytes(y);
856 if (skip > field_len)
857 {
858 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
859 goto err;
860 }
861 while (skip > 0)
862 {
863 buf[i++] = 0;
864 skip--;
865 }
866 skip = BN_bn2bin(y, buf + i);
867 i += skip;
868 }
869
870 if (i != ret)
871 {
872 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
873 goto err;
874 }
875 }
876
877 if (used_ctx)
878 BN_CTX_end(ctx);
879 if (new_ctx != NULL)
880 BN_CTX_free(new_ctx);
881 return ret;
882
883 err:
884 if (used_ctx)
885 BN_CTX_end(ctx);
886 if (new_ctx != NULL)
887 BN_CTX_free(new_ctx);
888 return 0;
889 }
890
891
892int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
893 const unsigned char *buf, size_t len, BN_CTX *ctx)
894 {
895 point_conversion_form_t form;
896 int y_bit;
897 BN_CTX *new_ctx = NULL;
898 BIGNUM *x, *y;
899 size_t field_len, enc_len;
900 int ret = 0;
901
902 if (len == 0)
903 {
904 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
905 return 0;
906 }
907 form = buf[0];
908 y_bit = form & 1;
909 form = form & ~1U;
910 if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
911 && (form != POINT_CONVERSION_UNCOMPRESSED)
912 && (form != POINT_CONVERSION_HYBRID))
913 {
914 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
915 return 0;
916 }
917 if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
918 {
919 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
920 return 0;
921 }
922
923 if (form == 0)
924 {
925 if (len != 1)
926 {
927 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
928 return 0;
929 }
930
931 return EC_POINT_set_to_infinity(group, point);
932 }
933
934 field_len = BN_num_bytes(&group->field);
935 enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
936
937 if (len != enc_len)
938 {
939 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
940 return 0;
941 }
942
943 if (ctx == NULL)
944 {
945 ctx = new_ctx = BN_CTX_new();
946 if (ctx == NULL)
947 return 0;
948 }
949
950 BN_CTX_start(ctx);
951 x = BN_CTX_get(ctx);
952 y = BN_CTX_get(ctx);
953 if (y == NULL) goto err;
954
955 if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
956 if (BN_ucmp(x, &group->field) >= 0)
957 {
958 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
959 goto err;
960 }
961
962 if (form == POINT_CONVERSION_COMPRESSED)
963 {
964 if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx)) goto err;
965 }
966 else
967 {
968 if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
969 if (BN_ucmp(y, &group->field) >= 0)
970 {
971 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
972 goto err;
973 }
974 if (form == POINT_CONVERSION_HYBRID)
975 {
976 if (y_bit != BN_is_odd(y))
977 {
978 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
979 goto err;
980 }
981 }
982
983 if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
984 }
985
986 if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
987 {
988 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
989 goto err;
990 }
991
992 ret = 1;
993
994 err:
995 BN_CTX_end(ctx);
996 if (new_ctx != NULL)
997 BN_CTX_free(new_ctx);
998 return ret;
999 }
1000
1001
1002int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) 643int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
1003 { 644 {
1004 int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); 645 int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
diff --git a/src/lib/libcrypto/ec/ectest.c b/src/lib/libcrypto/ec/ectest.c
index 7509cb9c7c..f107782de0 100644
--- a/src/lib/libcrypto/ec/ectest.c
+++ b/src/lib/libcrypto/ec/ectest.c
@@ -94,6 +94,7 @@ int main(int argc, char * argv[]) { puts("Elliptic curves are disabled."); retur
94#include <openssl/objects.h> 94#include <openssl/objects.h>
95#include <openssl/rand.h> 95#include <openssl/rand.h>
96#include <openssl/bn.h> 96#include <openssl/bn.h>
97#include <openssl/opensslconf.h>
97 98
98#if defined(_MSC_VER) && defined(_MIPS_) && (_MSC_VER/100==12) 99#if defined(_MSC_VER) && defined(_MIPS_) && (_MSC_VER/100==12)
99/* suppress "too big too optimize" warning */ 100/* suppress "too big too optimize" warning */
@@ -107,10 +108,6 @@ int main(int argc, char * argv[]) { puts("Elliptic curves are disabled."); retur
107 EXIT(1); \ 108 EXIT(1); \
108} while (0) 109} while (0)
109 110
110void prime_field_tests(void);
111void char2_field_tests(void);
112void internal_curve_test(void);
113
114#define TIMING_BASE_PT 0 111#define TIMING_BASE_PT 0
115#define TIMING_RAND_PT 1 112#define TIMING_RAND_PT 1
116#define TIMING_SIMUL 2 113#define TIMING_SIMUL 2
@@ -195,7 +192,50 @@ static void timings(EC_GROUP *group, int type, BN_CTX *ctx)
195 } 192 }
196#endif 193#endif
197 194
198void prime_field_tests() 195/* test multiplication with group order, long and negative scalars */
196static void group_order_tests(EC_GROUP *group)
197 {
198 BIGNUM *n1, *n2, *order;
199 EC_POINT *P = EC_POINT_new(group);
200 EC_POINT *Q = EC_POINT_new(group);
201 BN_CTX *ctx = BN_CTX_new();
202
203 n1 = BN_new(); n2 = BN_new(); order = BN_new();
204 fprintf(stdout, "verify group order ...");
205 fflush(stdout);
206 if (!EC_GROUP_get_order(group, order, ctx)) ABORT;
207 if (!EC_POINT_mul(group, Q, order, NULL, NULL, ctx)) ABORT;
208 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
209 fprintf(stdout, ".");
210 fflush(stdout);
211 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
212 if (!EC_POINT_mul(group, Q, order, NULL, NULL, ctx)) ABORT;
213 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
214 fprintf(stdout, " ok\n");
215 fprintf(stdout, "long/negative scalar tests ... ");
216 if (!BN_one(n1)) ABORT;
217 /* n1 = 1 - order */
218 if (!BN_sub(n1, n1, order)) ABORT;
219 if(!EC_POINT_mul(group, Q, NULL, P, n1, ctx)) ABORT;
220 if (0 != EC_POINT_cmp(group, Q, P, ctx)) ABORT;
221 /* n2 = 1 + order */
222 if (!BN_add(n2, order, BN_value_one())) ABORT;
223 if(!EC_POINT_mul(group, Q, NULL, P, n2, ctx)) ABORT;
224 if (0 != EC_POINT_cmp(group, Q, P, ctx)) ABORT;
225 /* n2 = (1 - order) * (1 + order) */
226 if (!BN_mul(n2, n1, n2, ctx)) ABORT;
227 if(!EC_POINT_mul(group, Q, NULL, P, n2, ctx)) ABORT;
228 if (0 != EC_POINT_cmp(group, Q, P, ctx)) ABORT;
229 fprintf(stdout, "ok\n");
230 EC_POINT_free(P);
231 EC_POINT_free(Q);
232 BN_free(n1);
233 BN_free(n2);
234 BN_free(order);
235 BN_CTX_free(ctx);
236 }
237
238static void prime_field_tests(void)
199 { 239 {
200 BN_CTX *ctx = NULL; 240 BN_CTX *ctx = NULL;
201 BIGNUM *p, *a, *b; 241 BIGNUM *p, *a, *b;
@@ -321,21 +361,21 @@ void prime_field_tests()
321 if (len == 0) ABORT; 361 if (len == 0) ABORT;
322 if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; 362 if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
323 if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; 363 if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
324 fprintf(stdout, "Generator as octect string, compressed form:\n "); 364 fprintf(stdout, "Generator as octet string, compressed form:\n ");
325 for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); 365 for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
326 366
327 len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx); 367 len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx);
328 if (len == 0) ABORT; 368 if (len == 0) ABORT;
329 if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; 369 if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
330 if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; 370 if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
331 fprintf(stdout, "\nGenerator as octect string, uncompressed form:\n "); 371 fprintf(stdout, "\nGenerator as octet string, uncompressed form:\n ");
332 for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); 372 for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
333 373
334 len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx); 374 len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx);
335 if (len == 0) ABORT; 375 if (len == 0) ABORT;
336 if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; 376 if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
337 if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; 377 if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
338 fprintf(stdout, "\nGenerator as octect string, hybrid form:\n "); 378 fprintf(stdout, "\nGenerator as octet string, hybrid form:\n ");
339 for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); 379 for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
340 380
341 if (!EC_POINT_get_Jprojective_coordinates_GFp(group, R, x, y, z, ctx)) ABORT; 381 if (!EC_POINT_get_Jprojective_coordinates_GFp(group, R, x, y, z, ctx)) ABORT;
@@ -381,17 +421,7 @@ void prime_field_tests()
381 if (EC_GROUP_get_degree(group) != 160) ABORT; 421 if (EC_GROUP_get_degree(group) != 160) ABORT;
382 fprintf(stdout, " ok\n"); 422 fprintf(stdout, " ok\n");
383 423
384 fprintf(stdout, "verify group order ..."); 424 group_order_tests(group);
385 fflush(stdout);
386 if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
387 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
388 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
389 fprintf(stdout, ".");
390 fflush(stdout);
391 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
392 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
393 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
394 fprintf(stdout, " ok\n");
395 425
396 if (!(P_160 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; 426 if (!(P_160 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
397 if (!EC_GROUP_copy(P_160, group)) ABORT; 427 if (!EC_GROUP_copy(P_160, group)) ABORT;
@@ -425,17 +455,7 @@ void prime_field_tests()
425 if (EC_GROUP_get_degree(group) != 192) ABORT; 455 if (EC_GROUP_get_degree(group) != 192) ABORT;
426 fprintf(stdout, " ok\n"); 456 fprintf(stdout, " ok\n");
427 457
428 fprintf(stdout, "verify group order ..."); 458 group_order_tests(group);
429 fflush(stdout);
430 if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
431 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
432 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
433 fprintf(stdout, ".");
434 fflush(stdout);
435 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
436 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
437 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
438 fprintf(stdout, " ok\n");
439 459
440 if (!(P_192 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; 460 if (!(P_192 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
441 if (!EC_GROUP_copy(P_192, group)) ABORT; 461 if (!EC_GROUP_copy(P_192, group)) ABORT;
@@ -469,17 +489,7 @@ void prime_field_tests()
469 if (EC_GROUP_get_degree(group) != 224) ABORT; 489 if (EC_GROUP_get_degree(group) != 224) ABORT;
470 fprintf(stdout, " ok\n"); 490 fprintf(stdout, " ok\n");
471 491
472 fprintf(stdout, "verify group order ..."); 492 group_order_tests(group);
473 fflush(stdout);
474 if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
475 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
476 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
477 fprintf(stdout, ".");
478 fflush(stdout);
479 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
480 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
481 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
482 fprintf(stdout, " ok\n");
483 493
484 if (!(P_224 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; 494 if (!(P_224 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
485 if (!EC_GROUP_copy(P_224, group)) ABORT; 495 if (!EC_GROUP_copy(P_224, group)) ABORT;
@@ -514,17 +524,7 @@ void prime_field_tests()
514 if (EC_GROUP_get_degree(group) != 256) ABORT; 524 if (EC_GROUP_get_degree(group) != 256) ABORT;
515 fprintf(stdout, " ok\n"); 525 fprintf(stdout, " ok\n");
516 526
517 fprintf(stdout, "verify group order ..."); 527 group_order_tests(group);
518 fflush(stdout);
519 if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
520 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
521 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
522 fprintf(stdout, ".");
523 fflush(stdout);
524 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
525 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
526 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
527 fprintf(stdout, " ok\n");
528 528
529 if (!(P_256 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; 529 if (!(P_256 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
530 if (!EC_GROUP_copy(P_256, group)) ABORT; 530 if (!EC_GROUP_copy(P_256, group)) ABORT;
@@ -563,18 +563,8 @@ void prime_field_tests()
563 fprintf(stdout, "verify degree ..."); 563 fprintf(stdout, "verify degree ...");
564 if (EC_GROUP_get_degree(group) != 384) ABORT; 564 if (EC_GROUP_get_degree(group) != 384) ABORT;
565 fprintf(stdout, " ok\n"); 565 fprintf(stdout, " ok\n");
566 566
567 fprintf(stdout, "verify group order ..."); 567 group_order_tests(group);
568 fflush(stdout);
569 if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
570 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
571 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
572 fprintf(stdout, ".");
573 fflush(stdout);
574 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
575 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
576 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
577 fprintf(stdout, " ok\n");
578 568
579 if (!(P_384 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; 569 if (!(P_384 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
580 if (!EC_GROUP_copy(P_384, group)) ABORT; 570 if (!EC_GROUP_copy(P_384, group)) ABORT;
@@ -619,18 +609,8 @@ void prime_field_tests()
619 fprintf(stdout, "verify degree ..."); 609 fprintf(stdout, "verify degree ...");
620 if (EC_GROUP_get_degree(group) != 521) ABORT; 610 if (EC_GROUP_get_degree(group) != 521) ABORT;
621 fprintf(stdout, " ok\n"); 611 fprintf(stdout, " ok\n");
622 612
623 fprintf(stdout, "verify group order ..."); 613 group_order_tests(group);
624 fflush(stdout);
625 if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
626 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
627 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
628 fprintf(stdout, ".");
629 fflush(stdout);
630 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
631 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
632 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
633 fprintf(stdout, " ok\n");
634 614
635 if (!(P_521 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; 615 if (!(P_521 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
636 if (!EC_GROUP_copy(P_521, group)) ABORT; 616 if (!EC_GROUP_copy(P_521, group)) ABORT;
@@ -659,6 +639,7 @@ void prime_field_tests()
659 points[2] = Q; 639 points[2] = Q;
660 points[3] = Q; 640 points[3] = Q;
661 641
642 if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
662 if (!BN_add(y, z, BN_value_one())) ABORT; 643 if (!BN_add(y, z, BN_value_one())) ABORT;
663 if (BN_is_odd(y)) ABORT; 644 if (BN_is_odd(y)) ABORT;
664 if (!BN_rshift1(y, y)) ABORT; 645 if (!BN_rshift1(y, y)) ABORT;
@@ -792,22 +773,14 @@ void prime_field_tests()
792 fprintf(stdout, "verify degree ..."); \ 773 fprintf(stdout, "verify degree ..."); \
793 if (EC_GROUP_get_degree(group) != _degree) ABORT; \ 774 if (EC_GROUP_get_degree(group) != _degree) ABORT; \
794 fprintf(stdout, " ok\n"); \ 775 fprintf(stdout, " ok\n"); \
795 fprintf(stdout, "verify group order ..."); \ 776 group_order_tests(group); \
796 fflush(stdout); \
797 if (!EC_GROUP_get_order(group, z, ctx)) ABORT; \
798 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; \
799 if (!EC_POINT_is_at_infinity(group, Q)) ABORT; \
800 fprintf(stdout, "."); \
801 fflush(stdout); \
802 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; \
803 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; \
804 if (!EC_POINT_is_at_infinity(group, Q)) ABORT; \
805 fprintf(stdout, " ok\n"); \
806 if (!(_variable = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; \ 777 if (!(_variable = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; \
807 if (!EC_GROUP_copy(_variable, group)) ABORT; 778 if (!EC_GROUP_copy(_variable, group)) ABORT; \
808 779
809void char2_field_tests() 780#ifndef OPENSSL_NO_EC2M
810 { 781
782static void char2_field_tests(void)
783 {
811 BN_CTX *ctx = NULL; 784 BN_CTX *ctx = NULL;
812 BIGNUM *p, *a, *b; 785 BIGNUM *p, *a, *b;
813 EC_GROUP *group; 786 EC_GROUP *group;
@@ -1239,8 +1212,9 @@ void char2_field_tests()
1239 if (C2_B571) EC_GROUP_free(C2_B571); 1212 if (C2_B571) EC_GROUP_free(C2_B571);
1240 1213
1241 } 1214 }
1215#endif
1242 1216
1243void internal_curve_test(void) 1217static void internal_curve_test(void)
1244 { 1218 {
1245 EC_builtin_curve *curves = NULL; 1219 EC_builtin_curve *curves = NULL;
1246 size_t crv_len = 0, n = 0; 1220 size_t crv_len = 0, n = 0;
@@ -1287,13 +1261,189 @@ void internal_curve_test(void)
1287 EC_GROUP_free(group); 1261 EC_GROUP_free(group);
1288 } 1262 }
1289 if (ok) 1263 if (ok)
1290 fprintf(stdout, " ok\n"); 1264 fprintf(stdout, " ok\n\n");
1291 else 1265 else
1292 fprintf(stdout, " failed\n"); 1266 {
1267 fprintf(stdout, " failed\n\n");
1268 ABORT;
1269 }
1293 OPENSSL_free(curves); 1270 OPENSSL_free(curves);
1294 return; 1271 return;
1295 } 1272 }
1296 1273
1274#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
1275/* nistp_test_params contains magic numbers for testing our optimized
1276 * implementations of several NIST curves with characteristic > 3. */
1277struct nistp_test_params
1278 {
1279 const EC_METHOD* (*meth) ();
1280 int degree;
1281 /* Qx, Qy and D are taken from
1282 * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/ECDSA_Prime.pdf
1283 * Otherwise, values are standard curve parameters from FIPS 180-3 */
1284 const char *p, *a, *b, *Qx, *Qy, *Gx, *Gy, *order, *d;
1285 };
1286
1287static const struct nistp_test_params nistp_tests_params[] =
1288 {
1289 {
1290 /* P-224 */
1291 EC_GFp_nistp224_method,
1292 224,
1293 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", /* p */
1294 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", /* a */
1295 "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", /* b */
1296 "E84FB0B8E7000CB657D7973CF6B42ED78B301674276DF744AF130B3E", /* Qx */
1297 "4376675C6FC5612C21A0FF2D2A89D2987DF7A2BC52183B5982298555", /* Qy */
1298 "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", /* Gx */
1299 "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", /* Gy */
1300 "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", /* order */
1301 "3F0C488E987C80BE0FEE521F8D90BE6034EC69AE11CA72AA777481E8", /* d */
1302 },
1303 {
1304 /* P-256 */
1305 EC_GFp_nistp256_method,
1306 256,
1307 "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", /* p */
1308 "ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", /* a */
1309 "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", /* b */
1310 "b7e08afdfe94bad3f1dc8c734798ba1c62b3a0ad1e9ea2a38201cd0889bc7a19", /* Qx */
1311 "3603f747959dbf7a4bb226e41928729063adc7ae43529e61b563bbc606cc5e09", /* Qy */
1312 "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", /* Gx */
1313 "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", /* Gy */
1314 "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", /* order */
1315 "c477f9f65c22cce20657faa5b2d1d8122336f851a508a1ed04e479c34985bf96", /* d */
1316 },
1317 {
1318 /* P-521 */
1319 EC_GFp_nistp521_method,
1320 521,
1321 "1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", /* p */
1322 "1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc", /* a */
1323 "051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", /* b */
1324 "0098e91eef9a68452822309c52fab453f5f117c1da8ed796b255e9ab8f6410cca16e59df403a6bdc6ca467a37056b1e54b3005d8ac030decfeb68df18b171885d5c4", /* Qx */
1325 "0164350c321aecfc1cca1ba4364c9b15656150b4b78d6a48d7d28e7f31985ef17be8554376b72900712c4b83ad668327231526e313f5f092999a4632fd50d946bc2e", /* Qy */
1326 "c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", /* Gx */
1327 "11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", /* Gy */
1328 "1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409", /* order */
1329 "0100085f47b8e1b8b11b7eb33028c0b2888e304bfc98501955b45bba1478dc184eeedf09b86a5f7c21994406072787205e69a63709fe35aa93ba333514b24f961722", /* d */
1330 },
1331 };
1332
1333void nistp_single_test(const struct nistp_test_params *test)
1334 {
1335 BN_CTX *ctx;
1336 BIGNUM *p, *a, *b, *x, *y, *n, *m, *order;
1337 EC_GROUP *NISTP;
1338 EC_POINT *G, *P, *Q, *Q_CHECK;
1339
1340 fprintf(stdout, "\nNIST curve P-%d (optimised implementation):\n", test->degree);
1341 ctx = BN_CTX_new();
1342 p = BN_new();
1343 a = BN_new();
1344 b = BN_new();
1345 x = BN_new(); y = BN_new();
1346 m = BN_new(); n = BN_new(); order = BN_new();
1347
1348 NISTP = EC_GROUP_new(test->meth());
1349 if(!NISTP) ABORT;
1350 if (!BN_hex2bn(&p, test->p)) ABORT;
1351 if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
1352 if (!BN_hex2bn(&a, test->a)) ABORT;
1353 if (!BN_hex2bn(&b, test->b)) ABORT;
1354 if (!EC_GROUP_set_curve_GFp(NISTP, p, a, b, ctx)) ABORT;
1355 G = EC_POINT_new(NISTP);
1356 P = EC_POINT_new(NISTP);
1357 Q = EC_POINT_new(NISTP);
1358 Q_CHECK = EC_POINT_new(NISTP);
1359 if(!BN_hex2bn(&x, test->Qx)) ABORT;
1360 if(!BN_hex2bn(&y, test->Qy)) ABORT;
1361 if(!EC_POINT_set_affine_coordinates_GFp(NISTP, Q_CHECK, x, y, ctx)) ABORT;
1362 if (!BN_hex2bn(&x, test->Gx)) ABORT;
1363 if (!BN_hex2bn(&y, test->Gy)) ABORT;
1364 if (!EC_POINT_set_affine_coordinates_GFp(NISTP, G, x, y, ctx)) ABORT;
1365 if (!BN_hex2bn(&order, test->order)) ABORT;
1366 if (!EC_GROUP_set_generator(NISTP, G, order, BN_value_one())) ABORT;
1367
1368 fprintf(stdout, "verify degree ... ");
1369 if (EC_GROUP_get_degree(NISTP) != test->degree) ABORT;
1370 fprintf(stdout, "ok\n");
1371
1372 fprintf(stdout, "NIST test vectors ... ");
1373 if (!BN_hex2bn(&n, test->d)) ABORT;
1374 /* fixed point multiplication */
1375 EC_POINT_mul(NISTP, Q, n, NULL, NULL, ctx);
1376 if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
1377 /* random point multiplication */
1378 EC_POINT_mul(NISTP, Q, NULL, G, n, ctx);
1379 if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
1380
1381 /* set generator to P = 2*G, where G is the standard generator */
1382 if (!EC_POINT_dbl(NISTP, P, G, ctx)) ABORT;
1383 if (!EC_GROUP_set_generator(NISTP, P, order, BN_value_one())) ABORT;
1384 /* set the scalar to m=n/2, where n is the NIST test scalar */
1385 if (!BN_rshift(m, n, 1)) ABORT;
1386
1387 /* test the non-standard generator */
1388 /* fixed point multiplication */
1389 EC_POINT_mul(NISTP, Q, m, NULL, NULL, ctx);
1390 if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
1391 /* random point multiplication */
1392 EC_POINT_mul(NISTP, Q, NULL, P, m, ctx);
1393 if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
1394
1395 /* now repeat all tests with precomputation */
1396 if (!EC_GROUP_precompute_mult(NISTP, ctx)) ABORT;
1397
1398 /* fixed point multiplication */
1399 EC_POINT_mul(NISTP, Q, m, NULL, NULL, ctx);
1400 if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
1401 /* random point multiplication */
1402 EC_POINT_mul(NISTP, Q, NULL, P, m, ctx);
1403 if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
1404
1405 /* reset generator */
1406 if (!EC_GROUP_set_generator(NISTP, G, order, BN_value_one())) ABORT;
1407 /* fixed point multiplication */
1408 EC_POINT_mul(NISTP, Q, n, NULL, NULL, ctx);
1409 if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
1410 /* random point multiplication */
1411 EC_POINT_mul(NISTP, Q, NULL, G, n, ctx);
1412 if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
1413
1414 fprintf(stdout, "ok\n");
1415 group_order_tests(NISTP);
1416#if 0
1417 timings(NISTP, TIMING_BASE_PT, ctx);
1418 timings(NISTP, TIMING_RAND_PT, ctx);
1419#endif
1420 EC_GROUP_free(NISTP);
1421 EC_POINT_free(G);
1422 EC_POINT_free(P);
1423 EC_POINT_free(Q);
1424 EC_POINT_free(Q_CHECK);
1425 BN_free(n);
1426 BN_free(m);
1427 BN_free(p);
1428 BN_free(a);
1429 BN_free(b);
1430 BN_free(x);
1431 BN_free(y);
1432 BN_free(order);
1433 BN_CTX_free(ctx);
1434 }
1435
1436void nistp_tests()
1437 {
1438 unsigned i;
1439
1440 for (i = 0; i < sizeof(nistp_tests_params) / sizeof(struct nistp_test_params); i++)
1441 {
1442 nistp_single_test(&nistp_tests_params[i]);
1443 }
1444 }
1445#endif
1446
1297static const char rnd_seed[] = "string to make the random number generator think it has entropy"; 1447static const char rnd_seed[] = "string to make the random number generator think it has entropy";
1298 1448
1299int main(int argc, char *argv[]) 1449int main(int argc, char *argv[])
@@ -1317,7 +1467,12 @@ int main(int argc, char *argv[])
1317 1467
1318 prime_field_tests(); 1468 prime_field_tests();
1319 puts(""); 1469 puts("");
1470#ifndef OPENSSL_NO_EC2M
1320 char2_field_tests(); 1471 char2_field_tests();
1472#endif
1473#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
1474 nistp_tests();
1475#endif
1321 /* test the internal curves */ 1476 /* test the internal curves */
1322 internal_curve_test(); 1477 internal_curve_test();
1323 1478