diff options
Diffstat (limited to 'src/lib/libcrypto/ec/ecp_smpl.c')
| -rw-r--r-- | src/lib/libcrypto/ec/ecp_smpl.c | 335 |
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 | |||
| 63 | const EC_METHOD *EC_GFp_simple_method(void) | 70 | const 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 | |||
| 106 | int ec_GFp_simple_group_init(EC_GROUP *group) | 130 | int 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 | ||
| 180 | int ec_GFp_simple_group_set_curve_GFp(EC_GROUP *group, | 168 | int 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 | ||
| 235 | int ec_GFp_simple_group_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx) | 223 | int 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 | ||
| 274 | int ec_GFp_simple_group_get_degree(const EC_GROUP *group) | ||
| 275 | { | ||
| 276 | return BN_num_bits(&group->field); | ||
| 277 | } | ||
| 278 | |||
| 286 | 279 | ||
| 287 | int ec_GFp_simple_group_set_generator(EC_GROUP *group, const EC_POINT *generator, | 280 | int 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: | |
| 317 | EC_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 | } | |
| 323 | int 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 | ||
| 332 | int 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); | 338 | err: |
| 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) | |||
| 380 | int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point) | 386 | int 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 | ||
| 500 | int ec_GFp_simple_point_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, | 507 | int 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 | ||
| 514 | int ec_GFp_simple_point_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point, | 521 | int 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 | ||
| 629 | int ec_GFp_simple_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, | 637 | int 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); |
