summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/ec/ecp_smpl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/ec/ecp_smpl.c')
-rw-r--r--src/lib/libcrypto/ec/ecp_smpl.c335
1 files changed, 167 insertions, 168 deletions
diff --git a/src/lib/libcrypto/ec/ecp_smpl.c b/src/lib/libcrypto/ec/ecp_smpl.c
index e9a51fb87a..4d26f8bdf6 100644
--- a/src/lib/libcrypto/ec/ecp_smpl.c
+++ b/src/lib/libcrypto/ec/ecp_smpl.c
@@ -1,8 +1,10 @@
1/* crypto/ec/ecp_smpl.c */ 1/* crypto/ec/ecp_smpl.c */
2/* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de> 2/* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de>
3 * for the OpenSSL project. */ 3 * for the OpenSSL project.
4 * Includes code written by Bodo Moeller for the OpenSSL project.
5*/
4/* ==================================================================== 6/* ====================================================================
5 * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. 7 * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
6 * 8 *
7 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
@@ -54,25 +56,29 @@
54 * Hudson (tjh@cryptsoft.com). 56 * Hudson (tjh@cryptsoft.com).
55 * 57 *
56 */ 58 */
59/* ====================================================================
60 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
61 * Portions of this software developed by SUN MICROSYSTEMS, INC.,
62 * and contributed to the OpenSSL project.
63 */
57 64
58#include <openssl/err.h> 65#include <openssl/err.h>
66#include <openssl/symhacks.h>
59 67
60#include "ec_lcl.h" 68#include "ec_lcl.h"
61 69
62
63const EC_METHOD *EC_GFp_simple_method(void) 70const EC_METHOD *EC_GFp_simple_method(void)
64 { 71 {
65 static const EC_METHOD ret = { 72 static const EC_METHOD ret = {
73 NID_X9_62_prime_field,
66 ec_GFp_simple_group_init, 74 ec_GFp_simple_group_init,
67 ec_GFp_simple_group_finish, 75 ec_GFp_simple_group_finish,
68 ec_GFp_simple_group_clear_finish, 76 ec_GFp_simple_group_clear_finish,
69 ec_GFp_simple_group_copy, 77 ec_GFp_simple_group_copy,
70 ec_GFp_simple_group_set_curve_GFp, 78 ec_GFp_simple_group_set_curve,
71 ec_GFp_simple_group_get_curve_GFp, 79 ec_GFp_simple_group_get_curve,
72 ec_GFp_simple_group_set_generator, 80 ec_GFp_simple_group_get_degree,
73 ec_GFp_simple_group_get0_generator, 81 ec_GFp_simple_group_check_discriminant,
74 ec_GFp_simple_group_get_order,
75 ec_GFp_simple_group_get_cofactor,
76 ec_GFp_simple_point_init, 82 ec_GFp_simple_point_init,
77 ec_GFp_simple_point_finish, 83 ec_GFp_simple_point_finish,
78 ec_GFp_simple_point_clear_finish, 84 ec_GFp_simple_point_clear_finish,
@@ -80,9 +86,9 @@ const EC_METHOD *EC_GFp_simple_method(void)
80 ec_GFp_simple_point_set_to_infinity, 86 ec_GFp_simple_point_set_to_infinity,
81 ec_GFp_simple_set_Jprojective_coordinates_GFp, 87 ec_GFp_simple_set_Jprojective_coordinates_GFp,
82 ec_GFp_simple_get_Jprojective_coordinates_GFp, 88 ec_GFp_simple_get_Jprojective_coordinates_GFp,
83 ec_GFp_simple_point_set_affine_coordinates_GFp, 89 ec_GFp_simple_point_set_affine_coordinates,
84 ec_GFp_simple_point_get_affine_coordinates_GFp, 90 ec_GFp_simple_point_get_affine_coordinates,
85 ec_GFp_simple_set_compressed_coordinates_GFp, 91 ec_GFp_simple_set_compressed_coordinates,
86 ec_GFp_simple_point2oct, 92 ec_GFp_simple_point2oct,
87 ec_GFp_simple_oct2point, 93 ec_GFp_simple_oct2point,
88 ec_GFp_simple_add, 94 ec_GFp_simple_add,
@@ -93,8 +99,12 @@ const EC_METHOD *EC_GFp_simple_method(void)
93 ec_GFp_simple_cmp, 99 ec_GFp_simple_cmp,
94 ec_GFp_simple_make_affine, 100 ec_GFp_simple_make_affine,
95 ec_GFp_simple_points_make_affine, 101 ec_GFp_simple_points_make_affine,
102 0 /* mul */,
103 0 /* precompute_mult */,
104 0 /* have_precompute_mult */,
96 ec_GFp_simple_field_mul, 105 ec_GFp_simple_field_mul,
97 ec_GFp_simple_field_sqr, 106 ec_GFp_simple_field_sqr,
107 0 /* field_div */,
98 0 /* field_encode */, 108 0 /* field_encode */,
99 0 /* field_decode */, 109 0 /* field_decode */,
100 0 /* field_set_to_one */ }; 110 0 /* field_set_to_one */ };
@@ -103,15 +113,26 @@ const EC_METHOD *EC_GFp_simple_method(void)
103 } 113 }
104 114
105 115
116/* Most method functions in this file are designed to work with
117 * non-trivial representations of field elements if necessary
118 * (see ecp_mont.c): while standard modular addition and subtraction
119 * are used, the field_mul and field_sqr methods will be used for
120 * multiplication, and field_encode and field_decode (if defined)
121 * will be used for converting between representations.
122
123 * Functions ec_GFp_simple_points_make_affine() and
124 * ec_GFp_simple_point_get_affine_coordinates() specifically assume
125 * that if a non-trivial representation is used, it is a Montgomery
126 * representation (i.e. 'encoding' means multiplying by some factor R).
127 */
128
129
106int ec_GFp_simple_group_init(EC_GROUP *group) 130int ec_GFp_simple_group_init(EC_GROUP *group)
107 { 131 {
108 BN_init(&group->field); 132 BN_init(&group->field);
109 BN_init(&group->a); 133 BN_init(&group->a);
110 BN_init(&group->b); 134 BN_init(&group->b);
111 group->a_is_minus3 = 0; 135 group->a_is_minus3 = 0;
112 group->generator = NULL;
113 BN_init(&group->order);
114 BN_init(&group->cofactor);
115 return 1; 136 return 1;
116 } 137 }
117 138
@@ -121,10 +142,6 @@ void ec_GFp_simple_group_finish(EC_GROUP *group)
121 BN_free(&group->field); 142 BN_free(&group->field);
122 BN_free(&group->a); 143 BN_free(&group->a);
123 BN_free(&group->b); 144 BN_free(&group->b);
124 if (group->generator != NULL)
125 EC_POINT_free(group->generator);
126 BN_free(&group->order);
127 BN_free(&group->cofactor);
128 } 145 }
129 146
130 147
@@ -133,13 +150,6 @@ void ec_GFp_simple_group_clear_finish(EC_GROUP *group)
133 BN_clear_free(&group->field); 150 BN_clear_free(&group->field);
134 BN_clear_free(&group->a); 151 BN_clear_free(&group->a);
135 BN_clear_free(&group->b); 152 BN_clear_free(&group->b);
136 if (group->generator != NULL)
137 {
138 EC_POINT_clear_free(group->generator);
139 group->generator = NULL;
140 }
141 BN_clear_free(&group->order);
142 BN_clear_free(&group->cofactor);
143 } 153 }
144 154
145 155
@@ -151,33 +161,11 @@ int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
151 161
152 dest->a_is_minus3 = src->a_is_minus3; 162 dest->a_is_minus3 = src->a_is_minus3;
153 163
154 if (src->generator != NULL)
155 {
156 if (dest->generator == NULL)
157 {
158 dest->generator = EC_POINT_new(dest);
159 if (dest->generator == NULL) return 0;
160 }
161 if (!EC_POINT_copy(dest->generator, src->generator)) return 0;
162 }
163 else
164 {
165 /* src->generator == NULL */
166 if (dest->generator != NULL)
167 {
168 EC_POINT_clear_free(dest->generator);
169 dest->generator = NULL;
170 }
171 }
172
173 if (!BN_copy(&dest->order, &src->order)) return 0;
174 if (!BN_copy(&dest->cofactor, &src->cofactor)) return 0;
175
176 return 1; 164 return 1;
177 } 165 }
178 166
179 167
180int ec_GFp_simple_group_set_curve_GFp(EC_GROUP *group, 168int ec_GFp_simple_group_set_curve(EC_GROUP *group,
181 const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) 169 const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
182 { 170 {
183 int ret = 0; 171 int ret = 0;
@@ -187,7 +175,7 @@ int ec_GFp_simple_group_set_curve_GFp(EC_GROUP *group,
187 /* p must be a prime > 3 */ 175 /* p must be a prime > 3 */
188 if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) 176 if (BN_num_bits(p) <= 2 || !BN_is_odd(p))
189 { 177 {
190 ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP, EC_R_INVALID_FIELD); 178 ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, EC_R_INVALID_FIELD);
191 return 0; 179 return 0;
192 } 180 }
193 181
@@ -204,7 +192,7 @@ int ec_GFp_simple_group_set_curve_GFp(EC_GROUP *group,
204 192
205 /* group->field */ 193 /* group->field */
206 if (!BN_copy(&group->field, p)) goto err; 194 if (!BN_copy(&group->field, p)) goto err;
207 group->field.neg = 0; 195 BN_set_negative(&group->field, 0);
208 196
209 /* group->a */ 197 /* group->a */
210 if (!BN_nnmod(tmp_a, a, p, ctx)) goto err; 198 if (!BN_nnmod(tmp_a, a, p, ctx)) goto err;
@@ -232,7 +220,7 @@ int ec_GFp_simple_group_set_curve_GFp(EC_GROUP *group,
232 } 220 }
233 221
234 222
235int ec_GFp_simple_group_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx) 223int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
236 { 224 {
237 int ret = 0; 225 int ret = 0;
238 BN_CTX *new_ctx = NULL; 226 BN_CTX *new_ctx = NULL;
@@ -283,58 +271,76 @@ int ec_GFp_simple_group_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *
283 } 271 }
284 272
285 273
274int ec_GFp_simple_group_get_degree(const EC_GROUP *group)
275 {
276 return BN_num_bits(&group->field);
277 }
278
286 279
287int ec_GFp_simple_group_set_generator(EC_GROUP *group, const EC_POINT *generator, 280int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
288 const BIGNUM *order, const BIGNUM *cofactor)
289 { 281 {
290 if (generator == NULL) 282 int ret = 0;
283 BIGNUM *a,*b,*order,*tmp_1,*tmp_2;
284 const BIGNUM *p = &group->field;
285 BN_CTX *new_ctx = NULL;
286
287 if (ctx == NULL)
291 { 288 {
292 ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER); 289 ctx = new_ctx = BN_CTX_new();
293 return 0 ; 290 if (ctx == NULL)
291 {
292 ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT, ERR_R_MALLOC_FAILURE);
293 goto err;
294 }
294 } 295 }
296 BN_CTX_start(ctx);
297 a = BN_CTX_get(ctx);
298 b = BN_CTX_get(ctx);
299 tmp_1 = BN_CTX_get(ctx);
300 tmp_2 = BN_CTX_get(ctx);
301 order = BN_CTX_get(ctx);
302 if (order == NULL) goto err;
295 303
296 if (group->generator == NULL) 304 if (group->meth->field_decode)
297 { 305 {
298 group->generator = EC_POINT_new(group); 306 if (!group->meth->field_decode(group, a, &group->a, ctx)) goto err;
299 if (group->generator == NULL) return 0; 307 if (!group->meth->field_decode(group, b, &group->b, ctx)) goto err;
300 } 308 }
301 if (!EC_POINT_copy(group->generator, generator)) return 0;
302
303 if (order != NULL)
304 { if (!BN_copy(&group->order, order)) return 0; }
305 else
306 { if (!BN_zero(&group->order)) return 0; }
307
308 if (cofactor != NULL)
309 { if (!BN_copy(&group->cofactor, cofactor)) return 0; }
310 else 309 else
311 { if (!BN_zero(&group->cofactor)) return 0; } 310 {
312 311 if (!BN_copy(a, &group->a)) goto err;
313 return 1; 312 if (!BN_copy(b, &group->b)) goto err;
314 } 313 }
315 314
316 315 /* check the discriminant:
317EC_POINT *ec_GFp_simple_group_get0_generator(const EC_GROUP *group) 316 * y^2 = x^3 + a*x + b is an elliptic curve <=> 4*a^3 + 27*b^2 != 0 (mod p)
318 { 317 * 0 =< a, b < p */
319 return group->generator; 318 if (BN_is_zero(a))
320 } 319 {
321 320 if (BN_is_zero(b)) goto err;
322 321 }
323int ec_GFp_simple_group_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) 322 else if (!BN_is_zero(b))
324 { 323 {
325 if (!BN_copy(order, &group->order)) 324 if (!BN_mod_sqr(tmp_1, a, p, ctx)) goto err;
326 return 0; 325 if (!BN_mod_mul(tmp_2, tmp_1, a, p, ctx)) goto err;
327 326 if (!BN_lshift(tmp_1, tmp_2, 2)) goto err;
328 return !BN_is_zero(&group->order); 327 /* tmp_1 = 4*a^3 */
329 }
330 328
329 if (!BN_mod_sqr(tmp_2, b, p, ctx)) goto err;
330 if (!BN_mul_word(tmp_2, 27)) goto err;
331 /* tmp_2 = 27*b^2 */
331 332
332int ec_GFp_simple_group_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx) 333 if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx)) goto err;
333 { 334 if (BN_is_zero(a)) goto err;
334 if (!BN_copy(cofactor, &group->cofactor)) 335 }
335 return 0; 336 ret = 1;
336 337
337 return !BN_is_zero(&group->cofactor); 338err:
339 if (ctx != NULL)
340 BN_CTX_end(ctx);
341 if (new_ctx != NULL)
342 BN_CTX_free(new_ctx);
343 return ret;
338 } 344 }
339 345
340 346
@@ -380,7 +386,8 @@ int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
380int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point) 386int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
381 { 387 {
382 point->Z_is_one = 0; 388 point->Z_is_one = 0;
383 return (BN_zero(&point->Z)); 389 BN_zero(&point->Z);
390 return 1;
384 } 391 }
385 392
386 393
@@ -497,13 +504,13 @@ int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group, const E
497 } 504 }
498 505
499 506
500int ec_GFp_simple_point_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, 507int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
501 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) 508 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
502 { 509 {
503 if (x == NULL || y == NULL) 510 if (x == NULL || y == NULL)
504 { 511 {
505 /* unlike for projective coordinates, we do not tolerate this */ 512 /* unlike for projective coordinates, we do not tolerate this */
506 ECerr(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP, ERR_R_PASSED_NULL_PARAMETER); 513 ECerr(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER);
507 return 0; 514 return 0;
508 } 515 }
509 516
@@ -511,17 +518,17 @@ int ec_GFp_simple_point_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POI
511 } 518 }
512 519
513 520
514int ec_GFp_simple_point_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point, 521int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point,
515 BIGNUM *x, BIGNUM *y, BN_CTX *ctx) 522 BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
516 { 523 {
517 BN_CTX *new_ctx = NULL; 524 BN_CTX *new_ctx = NULL;
518 BIGNUM *X, *Y, *Z, *Z_1, *Z_2, *Z_3; 525 BIGNUM *Z, *Z_1, *Z_2, *Z_3;
519 const BIGNUM *X_, *Y_, *Z_; 526 const BIGNUM *Z_;
520 int ret = 0; 527 int ret = 0;
521 528
522 if (EC_POINT_is_at_infinity(group, point)) 529 if (EC_POINT_is_at_infinity(group, point))
523 { 530 {
524 ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP, EC_R_POINT_AT_INFINITY); 531 ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY);
525 return 0; 532 return 0;
526 } 533 }
527 534
@@ -533,8 +540,6 @@ int ec_GFp_simple_point_get_affine_coordinates_GFp(const EC_GROUP *group, const
533 } 540 }
534 541
535 BN_CTX_start(ctx); 542 BN_CTX_start(ctx);
536 X = BN_CTX_get(ctx);
537 Y = BN_CTX_get(ctx);
538 Z = BN_CTX_get(ctx); 543 Z = BN_CTX_get(ctx);
539 Z_1 = BN_CTX_get(ctx); 544 Z_1 = BN_CTX_get(ctx);
540 Z_2 = BN_CTX_get(ctx); 545 Z_2 = BN_CTX_get(ctx);
@@ -545,34 +550,44 @@ int ec_GFp_simple_point_get_affine_coordinates_GFp(const EC_GROUP *group, const
545 550
546 if (group->meth->field_decode) 551 if (group->meth->field_decode)
547 { 552 {
548 if (!group->meth->field_decode(group, X, &point->X, ctx)) goto err;
549 if (!group->meth->field_decode(group, Y, &point->Y, ctx)) goto err;
550 if (!group->meth->field_decode(group, Z, &point->Z, ctx)) goto err; 553 if (!group->meth->field_decode(group, Z, &point->Z, ctx)) goto err;
551 X_ = X; Y_ = Y; Z_ = Z; 554 Z_ = Z;
552 } 555 }
553 else 556 else
554 { 557 {
555 X_ = &point->X;
556 Y_ = &point->Y;
557 Z_ = &point->Z; 558 Z_ = &point->Z;
558 } 559 }
559 560
560 if (BN_is_one(Z_)) 561 if (BN_is_one(Z_))
561 { 562 {
562 if (x != NULL) 563 if (group->meth->field_decode)
563 { 564 {
564 if (!BN_copy(x, X_)) goto err; 565 if (x != NULL)
566 {
567 if (!group->meth->field_decode(group, x, &point->X, ctx)) goto err;
568 }
569 if (y != NULL)
570 {
571 if (!group->meth->field_decode(group, y, &point->Y, ctx)) goto err;
572 }
565 } 573 }
566 if (y != NULL) 574 else
567 { 575 {
568 if (!BN_copy(y, Y_)) goto err; 576 if (x != NULL)
577 {
578 if (!BN_copy(x, &point->X)) goto err;
579 }
580 if (y != NULL)
581 {
582 if (!BN_copy(y, &point->Y)) goto err;
583 }
569 } 584 }
570 } 585 }
571 else 586 else
572 { 587 {
573 if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx)) 588 if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx))
574 { 589 {
575 ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP, ERR_R_BN_LIB); 590 ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_BN_LIB);
576 goto err; 591 goto err;
577 } 592 }
578 593
@@ -588,15 +603,8 @@ int ec_GFp_simple_point_get_affine_coordinates_GFp(const EC_GROUP *group, const
588 603
589 if (x != NULL) 604 if (x != NULL)
590 { 605 {
591 if (group->meth->field_encode == 0) 606 /* in the Montgomery case, field_mul will cancel out Montgomery factor in X: */
592 { 607 if (!group->meth->field_mul(group, x, &point->X, Z_2, ctx)) goto err;
593 /* field_mul works on standard representation */
594 if (!group->meth->field_mul(group, x, X_, Z_2, ctx)) goto err;
595 }
596 else
597 {
598 if (!BN_mod_mul(x, X_, Z_2, &group->field, ctx)) goto err;
599 }
600 } 608 }
601 609
602 if (y != NULL) 610 if (y != NULL)
@@ -605,14 +613,14 @@ int ec_GFp_simple_point_get_affine_coordinates_GFp(const EC_GROUP *group, const
605 { 613 {
606 /* field_mul works on standard representation */ 614 /* field_mul works on standard representation */
607 if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) goto err; 615 if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) goto err;
608 if (!group->meth->field_mul(group, y, Y_, Z_3, ctx)) goto err;
609
610 } 616 }
611 else 617 else
612 { 618 {
613 if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) goto err; 619 if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) goto err;
614 if (!BN_mod_mul(y, Y_, Z_3, &group->field, ctx)) goto err;
615 } 620 }
621
622 /* in the Montgomery case, field_mul will cancel out Montgomery factor in Y: */
623 if (!group->meth->field_mul(group, y, &point->Y, Z_3, ctx)) goto err;
616 } 624 }
617 } 625 }
618 626
@@ -626,13 +634,16 @@ int ec_GFp_simple_point_get_affine_coordinates_GFp(const EC_GROUP *group, const
626 } 634 }
627 635
628 636
629int ec_GFp_simple_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, 637int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
630 const BIGNUM *x_, int y_bit, BN_CTX *ctx) 638 const BIGNUM *x_, int y_bit, BN_CTX *ctx)
631 { 639 {
632 BN_CTX *new_ctx = NULL; 640 BN_CTX *new_ctx = NULL;
633 BIGNUM *tmp1, *tmp2, *x, *y; 641 BIGNUM *tmp1, *tmp2, *x, *y;
634 int ret = 0; 642 int ret = 0;
635 643
644 /* clear error queue*/
645 ERR_clear_error();
646
636 if (ctx == NULL) 647 if (ctx == NULL)
637 { 648 {
638 ctx = new_ctx = BN_CTX_new(); 649 ctx = new_ctx = BN_CTX_new();
@@ -704,19 +715,17 @@ int ec_GFp_simple_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT
704 715
705 if (!BN_mod_sqrt(y, tmp1, &group->field, ctx)) 716 if (!BN_mod_sqrt(y, tmp1, &group->field, ctx))
706 { 717 {
707 unsigned long err = ERR_peek_error(); 718 unsigned long err = ERR_peek_last_error();
708 719
709 if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE) 720 if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE)
710 { 721 {
711 (void)ERR_get_error(); 722 ERR_clear_error();
712 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP, EC_R_INVALID_COMPRESSED_POINT); 723 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
713 } 724 }
714 else 725 else
715 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP, ERR_R_BN_LIB); 726 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
716 goto err; 727 goto err;
717 } 728 }
718 /* If tmp1 is not a square (i.e. there is no point on the curve with
719 * our x), then y now is a nonsense value too */
720 729
721 if (y_bit != BN_is_odd(y)) 730 if (y_bit != BN_is_odd(y))
722 { 731 {
@@ -728,16 +737,17 @@ int ec_GFp_simple_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT
728 if (kron == -2) goto err; 737 if (kron == -2) goto err;
729 738
730 if (kron == 1) 739 if (kron == 1)
731 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP, EC_R_INVALID_COMPRESSION_BIT); 740 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSION_BIT);
732 else 741 else
733 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP, EC_R_INVALID_COMPRESSED_POINT); 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);
734 goto err; 744 goto err;
735 } 745 }
736 if (!BN_usub(y, &group->field, y)) goto err; 746 if (!BN_usub(y, &group->field, y)) goto err;
737 } 747 }
738 if (y_bit != BN_is_odd(y)) 748 if (y_bit != BN_is_odd(y))
739 { 749 {
740 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP, ERR_R_INTERNAL_ERROR); 750 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_INTERNAL_ERROR);
741 goto err; 751 goto err;
742 } 752 }
743 753
@@ -1088,7 +1098,7 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, con
1088 else 1098 else
1089 { 1099 {
1090 /* a is the inverse of b */ 1100 /* a is the inverse of b */
1091 if (!BN_zero(&r->Z)) goto end; 1101 BN_zero(&r->Z);
1092 r->Z_is_one = 0; 1102 r->Z_is_one = 0;
1093 ret = 1; 1103 ret = 1;
1094 goto end; 1104 goto end;
@@ -1164,7 +1174,7 @@ int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_
1164 1174
1165 if (EC_POINT_is_at_infinity(group, a)) 1175 if (EC_POINT_is_at_infinity(group, a))
1166 { 1176 {
1167 if (!BN_zero(&r->Z)) return 0; 1177 BN_zero(&r->Z);
1168 r->Z_is_one = 0; 1178 r->Z_is_one = 0;
1169 return 1; 1179 return 1;
1170 } 1180 }
@@ -1292,7 +1302,7 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_C
1292 int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); 1302 int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
1293 const BIGNUM *p; 1303 const BIGNUM *p;
1294 BN_CTX *new_ctx = NULL; 1304 BN_CTX *new_ctx = NULL;
1295 BIGNUM *rh, *tmp1, *tmp2, *Z4, *Z6; 1305 BIGNUM *rh, *tmp, *Z4, *Z6;
1296 int ret = -1; 1306 int ret = -1;
1297 1307
1298 if (EC_POINT_is_at_infinity(group, point)) 1308 if (EC_POINT_is_at_infinity(group, point))
@@ -1311,8 +1321,7 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_C
1311 1321
1312 BN_CTX_start(ctx); 1322 BN_CTX_start(ctx);
1313 rh = BN_CTX_get(ctx); 1323 rh = BN_CTX_get(ctx);
1314 tmp1 = BN_CTX_get(ctx); 1324 tmp = BN_CTX_get(ctx);
1315 tmp2 = BN_CTX_get(ctx);
1316 Z4 = BN_CTX_get(ctx); 1325 Z4 = BN_CTX_get(ctx);
1317 Z6 = BN_CTX_get(ctx); 1326 Z6 = BN_CTX_get(ctx);
1318 if (Z6 == NULL) goto err; 1327 if (Z6 == NULL) goto err;
@@ -1326,59 +1335,49 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_C
1326 * To test this, we add up the right-hand side in 'rh'. 1335 * To test this, we add up the right-hand side in 'rh'.
1327 */ 1336 */
1328 1337
1329 /* rh := X^3 */ 1338 /* rh := X^2 */
1330 if (!field_sqr(group, rh, &point->X, ctx)) goto err; 1339 if (!field_sqr(group, rh, &point->X, ctx)) goto err;
1331 if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
1332 1340
1333 if (!point->Z_is_one) 1341 if (!point->Z_is_one)
1334 { 1342 {
1335 if (!field_sqr(group, tmp1, &point->Z, ctx)) goto err; 1343 if (!field_sqr(group, tmp, &point->Z, ctx)) goto err;
1336 if (!field_sqr(group, Z4, tmp1, ctx)) goto err; 1344 if (!field_sqr(group, Z4, tmp, ctx)) goto err;
1337 if (!field_mul(group, Z6, Z4, tmp1, ctx)) goto err; 1345 if (!field_mul(group, Z6, Z4, tmp, ctx)) goto err;
1338 1346
1339 /* rh := rh + a*X*Z^4 */ 1347 /* rh := (rh + a*Z^4)*X */
1340 if (!field_mul(group, tmp1, &point->X, Z4, ctx)) goto err;
1341 if (group->a_is_minus3) 1348 if (group->a_is_minus3)
1342 { 1349 {
1343 if (!BN_mod_lshift1_quick(tmp2, tmp1, p)) goto err; 1350 if (!BN_mod_lshift1_quick(tmp, Z4, p)) goto err;
1344 if (!BN_mod_add_quick(tmp2, tmp2, tmp1, p)) goto err; 1351 if (!BN_mod_add_quick(tmp, tmp, Z4, p)) goto err;
1345 if (!BN_mod_sub_quick(rh, rh, tmp2, p)) goto err; 1352 if (!BN_mod_sub_quick(rh, rh, tmp, p)) goto err;
1353 if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
1346 } 1354 }
1347 else 1355 else
1348 { 1356 {
1349 if (!field_mul(group, tmp2, tmp1, &group->a, ctx)) goto err; 1357 if (!field_mul(group, tmp, Z4, &group->a, ctx)) goto err;
1350 if (!BN_mod_add_quick(rh, rh, tmp2, p)) goto err; 1358 if (!BN_mod_add_quick(rh, rh, tmp, p)) goto err;
1359 if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
1351 } 1360 }
1352 1361
1353 /* rh := rh + b*Z^6 */ 1362 /* rh := rh + b*Z^6 */
1354 if (!field_mul(group, tmp1, &group->b, Z6, ctx)) goto err; 1363 if (!field_mul(group, tmp, &group->b, Z6, ctx)) goto err;
1355 if (!BN_mod_add_quick(rh, rh, tmp1, p)) goto err; 1364 if (!BN_mod_add_quick(rh, rh, tmp, p)) goto err;
1356 } 1365 }
1357 else 1366 else
1358 { 1367 {
1359 /* point->Z_is_one */ 1368 /* point->Z_is_one */
1360 1369
1361 /* rh := rh + a*X */ 1370 /* rh := (rh + a)*X */
1362 if (group->a_is_minus3) 1371 if (!BN_mod_add_quick(rh, rh, &group->a, p)) goto err;
1363 { 1372 if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
1364 if (!BN_mod_lshift1_quick(tmp2, &point->X, p)) goto err;
1365 if (!BN_mod_add_quick(tmp2, tmp2, &point->X, p)) goto err;
1366 if (!BN_mod_sub_quick(rh, rh, tmp2, p)) goto err;
1367 }
1368 else
1369 {
1370 if (!field_mul(group, tmp2, &point->X, &group->a, ctx)) goto err;
1371 if (!BN_mod_add_quick(rh, rh, tmp2, p)) goto err;
1372 }
1373
1374 /* rh := rh + b */ 1373 /* rh := rh + b */
1375 if (!BN_mod_add_quick(rh, rh, &group->b, p)) goto err; 1374 if (!BN_mod_add_quick(rh, rh, &group->b, p)) goto err;
1376 } 1375 }
1377 1376
1378 /* 'lh' := Y^2 */ 1377 /* 'lh' := Y^2 */
1379 if (!field_sqr(group, tmp1, &point->Y, ctx)) goto err; 1378 if (!field_sqr(group, tmp, &point->Y, ctx)) goto err;
1380 1379
1381 ret = (0 == BN_cmp(tmp1, rh)); 1380 ret = (0 == BN_ucmp(tmp, rh));
1382 1381
1383 err: 1382 err:
1384 BN_CTX_end(ctx); 1383 BN_CTX_end(ctx);