summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/ec/ec2_smpl.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lib/libcrypto/ec/ec2_smpl.c667
1 files changed, 370 insertions, 297 deletions
diff --git a/src/lib/libcrypto/ec/ec2_smpl.c b/src/lib/libcrypto/ec/ec2_smpl.c
index 5682bfab37..71bacf71dd 100644
--- a/src/lib/libcrypto/ec/ec2_smpl.c
+++ b/src/lib/libcrypto/ec/ec2_smpl.c
@@ -21,7 +21,7 @@
21 * are met: 21 * are met:
22 * 22 *
23 * 1. Redistributions of source code must retain the above copyright 23 * 1. Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer. 24 * notice, this list of conditions and the following disclaimer.
25 * 25 *
26 * 2. Redistributions in binary form must reproduce the above copyright 26 * 2. Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in 27 * notice, this list of conditions and the following disclaimer in
@@ -87,16 +87,16 @@ EC_GF2m_simple_method(void)
87 .group_get_curve = ec_GF2m_simple_group_get_curve, 87 .group_get_curve = ec_GF2m_simple_group_get_curve,
88 .group_get_degree = ec_GF2m_simple_group_get_degree, 88 .group_get_degree = ec_GF2m_simple_group_get_degree,
89 .group_check_discriminant = 89 .group_check_discriminant =
90 ec_GF2m_simple_group_check_discriminant, 90 ec_GF2m_simple_group_check_discriminant,
91 .point_init = ec_GF2m_simple_point_init, 91 .point_init = ec_GF2m_simple_point_init,
92 .point_finish = ec_GF2m_simple_point_finish, 92 .point_finish = ec_GF2m_simple_point_finish,
93 .point_clear_finish = ec_GF2m_simple_point_clear_finish, 93 .point_clear_finish = ec_GF2m_simple_point_clear_finish,
94 .point_copy = ec_GF2m_simple_point_copy, 94 .point_copy = ec_GF2m_simple_point_copy,
95 .point_set_to_infinity = ec_GF2m_simple_point_set_to_infinity, 95 .point_set_to_infinity = ec_GF2m_simple_point_set_to_infinity,
96 .point_set_affine_coordinates = 96 .point_set_affine_coordinates =
97 ec_GF2m_simple_point_set_affine_coordinates, 97 ec_GF2m_simple_point_set_affine_coordinates,
98 .point_get_affine_coordinates = 98 .point_get_affine_coordinates =
99 ec_GF2m_simple_point_get_affine_coordinates, 99 ec_GF2m_simple_point_get_affine_coordinates,
100 .add = ec_GF2m_simple_add, 100 .add = ec_GF2m_simple_add,
101 .dbl = ec_GF2m_simple_dbl, 101 .dbl = ec_GF2m_simple_dbl,
102 .invert = ec_GF2m_simple_invert, 102 .invert = ec_GF2m_simple_invert,
@@ -106,7 +106,10 @@ EC_GF2m_simple_method(void)
106 .make_affine = ec_GF2m_simple_make_affine, 106 .make_affine = ec_GF2m_simple_make_affine,
107 .points_make_affine = ec_GF2m_simple_points_make_affine, 107 .points_make_affine = ec_GF2m_simple_points_make_affine,
108 108
109 /* the following three method functions are defined in ec2_mult.c */ 109 /*
110 * the following three method functions are defined in
111 * ec2_mult.c
112 */
110 .mul = ec_GF2m_simple_mul, 113 .mul = ec_GF2m_simple_mul,
111 .precompute_mult = ec_GF2m_precompute_mult, 114 .precompute_mult = ec_GF2m_precompute_mult,
112 .have_precompute_mult = ec_GF2m_have_precompute_mult, 115 .have_precompute_mult = ec_GF2m_have_precompute_mult,
@@ -123,31 +126,34 @@ EC_GF2m_simple_method(void)
123/* Initialize a GF(2^m)-based EC_GROUP structure. 126/* Initialize a GF(2^m)-based EC_GROUP structure.
124 * Note that all other members are handled by EC_GROUP_new. 127 * Note that all other members are handled by EC_GROUP_new.
125 */ 128 */
126int ec_GF2m_simple_group_init(EC_GROUP *group) 129int
127 { 130ec_GF2m_simple_group_init(EC_GROUP * group)
131{
128 BN_init(&group->field); 132 BN_init(&group->field);
129 BN_init(&group->a); 133 BN_init(&group->a);
130 BN_init(&group->b); 134 BN_init(&group->b);
131 return 1; 135 return 1;
132 } 136}
133 137
134 138
135/* Free a GF(2^m)-based EC_GROUP structure. 139/* Free a GF(2^m)-based EC_GROUP structure.
136 * Note that all other members are handled by EC_GROUP_free. 140 * Note that all other members are handled by EC_GROUP_free.
137 */ 141 */
138void ec_GF2m_simple_group_finish(EC_GROUP *group) 142void
139 { 143ec_GF2m_simple_group_finish(EC_GROUP * group)
144{
140 BN_free(&group->field); 145 BN_free(&group->field);
141 BN_free(&group->a); 146 BN_free(&group->a);
142 BN_free(&group->b); 147 BN_free(&group->b);
143 } 148}
144 149
145 150
146/* Clear and free a GF(2^m)-based EC_GROUP structure. 151/* Clear and free a GF(2^m)-based EC_GROUP structure.
147 * Note that all other members are handled by EC_GROUP_clear_free. 152 * Note that all other members are handled by EC_GROUP_clear_free.
148 */ 153 */
149void ec_GF2m_simple_group_clear_finish(EC_GROUP *group) 154void
150 { 155ec_GF2m_simple_group_clear_finish(EC_GROUP * group)
156{
151 BN_clear_free(&group->field); 157 BN_clear_free(&group->field);
152 BN_clear_free(&group->a); 158 BN_clear_free(&group->a);
153 BN_clear_free(&group->b); 159 BN_clear_free(&group->b);
@@ -157,127 +163,145 @@ void ec_GF2m_simple_group_clear_finish(EC_GROUP *group)
157 group->poly[3] = 0; 163 group->poly[3] = 0;
158 group->poly[4] = 0; 164 group->poly[4] = 0;
159 group->poly[5] = -1; 165 group->poly[5] = -1;
160 } 166}
161 167
162 168
163/* Copy a GF(2^m)-based EC_GROUP structure. 169/* Copy a GF(2^m)-based EC_GROUP structure.
164 * Note that all other members are handled by EC_GROUP_copy. 170 * Note that all other members are handled by EC_GROUP_copy.
165 */ 171 */
166int ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) 172int
167 { 173ec_GF2m_simple_group_copy(EC_GROUP * dest, const EC_GROUP * src)
174{
168 int i; 175 int i;
169 if (!BN_copy(&dest->field, &src->field)) return 0; 176
170 if (!BN_copy(&dest->a, &src->a)) return 0; 177 if (!BN_copy(&dest->field, &src->field))
171 if (!BN_copy(&dest->b, &src->b)) return 0; 178 return 0;
179 if (!BN_copy(&dest->a, &src->a))
180 return 0;
181 if (!BN_copy(&dest->b, &src->b))
182 return 0;
172 dest->poly[0] = src->poly[0]; 183 dest->poly[0] = src->poly[0];
173 dest->poly[1] = src->poly[1]; 184 dest->poly[1] = src->poly[1];
174 dest->poly[2] = src->poly[2]; 185 dest->poly[2] = src->poly[2];
175 dest->poly[3] = src->poly[3]; 186 dest->poly[3] = src->poly[3];
176 dest->poly[4] = src->poly[4]; 187 dest->poly[4] = src->poly[4];
177 dest->poly[5] = src->poly[5]; 188 dest->poly[5] = src->poly[5];
178 if (bn_wexpand(&dest->a, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) return 0; 189 if (bn_wexpand(&dest->a, (int) (dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL)
179 if (bn_wexpand(&dest->b, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) return 0; 190 return 0;
180 for (i = dest->a.top; i < dest->a.dmax; i++) dest->a.d[i] = 0; 191 if (bn_wexpand(&dest->b, (int) (dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL)
181 for (i = dest->b.top; i < dest->b.dmax; i++) dest->b.d[i] = 0; 192 return 0;
193 for (i = dest->a.top; i < dest->a.dmax; i++)
194 dest->a.d[i] = 0;
195 for (i = dest->b.top; i < dest->b.dmax; i++)
196 dest->b.d[i] = 0;
182 return 1; 197 return 1;
183 } 198}
184 199
185 200
186/* Set the curve parameters of an EC_GROUP structure. */ 201/* Set the curve parameters of an EC_GROUP structure. */
187int ec_GF2m_simple_group_set_curve(EC_GROUP *group, 202int
188 const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) 203ec_GF2m_simple_group_set_curve(EC_GROUP * group,
189 { 204 const BIGNUM * p, const BIGNUM * a, const BIGNUM * b, BN_CTX * ctx)
205{
190 int ret = 0, i; 206 int ret = 0, i;
191 207
192 /* group->field */ 208 /* group->field */
193 if (!BN_copy(&group->field, p)) goto err; 209 if (!BN_copy(&group->field, p))
210 goto err;
194 i = BN_GF2m_poly2arr(&group->field, group->poly, 6) - 1; 211 i = BN_GF2m_poly2arr(&group->field, group->poly, 6) - 1;
195 if ((i != 5) && (i != 3)) 212 if ((i != 5) && (i != 3)) {
196 {
197 ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIELD); 213 ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIELD);
198 goto err; 214 goto err;
199 } 215 }
200
201 /* group->a */ 216 /* group->a */
202 if (!BN_GF2m_mod_arr(&group->a, a, group->poly)) goto err; 217 if (!BN_GF2m_mod_arr(&group->a, a, group->poly))
203 if(bn_wexpand(&group->a, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) goto err; 218 goto err;
204 for (i = group->a.top; i < group->a.dmax; i++) group->a.d[i] = 0; 219 if (bn_wexpand(&group->a, (int) (group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL)
205 220 goto err;
221 for (i = group->a.top; i < group->a.dmax; i++)
222 group->a.d[i] = 0;
223
206 /* group->b */ 224 /* group->b */
207 if (!BN_GF2m_mod_arr(&group->b, b, group->poly)) goto err; 225 if (!BN_GF2m_mod_arr(&group->b, b, group->poly))
208 if(bn_wexpand(&group->b, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) goto err; 226 goto err;
209 for (i = group->b.top; i < group->b.dmax; i++) group->b.d[i] = 0; 227 if (bn_wexpand(&group->b, (int) (group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL)
210 228 goto err;
229 for (i = group->b.top; i < group->b.dmax; i++)
230 group->b.d[i] = 0;
231
211 ret = 1; 232 ret = 1;
212 err: 233err:
213 return ret; 234 return ret;
214 } 235}
215 236
216 237
217/* Get the curve parameters of an EC_GROUP structure. 238/* Get the curve parameters of an EC_GROUP structure.
218 * If p, a, or b are NULL then there values will not be set but the method will return with success. 239 * If p, a, or b are NULL then there values will not be set but the method will return with success.
219 */ 240 */
220int ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx) 241int
221 { 242ec_GF2m_simple_group_get_curve(const EC_GROUP *group,
243 BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
244{
222 int ret = 0; 245 int ret = 0;
223
224 if (p != NULL)
225 {
226 if (!BN_copy(p, &group->field)) return 0;
227 }
228 246
229 if (a != NULL) 247 if (p != NULL) {
230 { 248 if (!BN_copy(p, &group->field))
231 if (!BN_copy(a, &group->a)) goto err; 249 return 0;
232 } 250 }
233 251 if (a != NULL) {
234 if (b != NULL) 252 if (!BN_copy(a, &group->a))
235 { 253 goto err;
236 if (!BN_copy(b, &group->b)) goto err; 254 }
237 } 255 if (b != NULL) {
238 256 if (!BN_copy(b, &group->b))
257 goto err;
258 }
239 ret = 1; 259 ret = 1;
240 260
241 err: 261err:
242 return ret; 262 return ret;
243 } 263}
244 264
245 265
246/* Gets the degree of the field. For a curve over GF(2^m) this is the value m. */ 266/* Gets the degree of the field. For a curve over GF(2^m) this is the value m. */
247int ec_GF2m_simple_group_get_degree(const EC_GROUP *group) 267int
248 { 268ec_GF2m_simple_group_get_degree(const EC_GROUP * group)
249 return BN_num_bits(&group->field)-1; 269{
250 } 270 return BN_num_bits(&group->field) - 1;
271}
251 272
252 273
253/* Checks the discriminant of the curve. 274/* Checks the discriminant of the curve.
254 * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p) 275 * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p)
255 */ 276 */
256int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) 277int
257 { 278ec_GF2m_simple_group_check_discriminant(const EC_GROUP * group, BN_CTX * ctx)
279{
258 int ret = 0; 280 int ret = 0;
259 BIGNUM *b; 281 BIGNUM *b;
260 BN_CTX *new_ctx = NULL; 282 BN_CTX *new_ctx = NULL;
261 283
262 if (ctx == NULL) 284 if (ctx == NULL) {
263 {
264 ctx = new_ctx = BN_CTX_new(); 285 ctx = new_ctx = BN_CTX_new();
265 if (ctx == NULL) 286 if (ctx == NULL) {
266 {
267 ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT, ERR_R_MALLOC_FAILURE); 287 ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT, ERR_R_MALLOC_FAILURE);
268 goto err; 288 goto err;
269 }
270 } 289 }
290 }
271 BN_CTX_start(ctx); 291 BN_CTX_start(ctx);
272 b = BN_CTX_get(ctx); 292 b = BN_CTX_get(ctx);
273 if (b == NULL) goto err; 293 if (b == NULL)
294 goto err;
295
296 if (!BN_GF2m_mod_arr(b, &group->b, group->poly))
297 goto err;
274 298
275 if (!BN_GF2m_mod_arr(b, &group->b, group->poly)) goto err; 299 /*
276 300 * check the discriminant: y^2 + x*y = x^3 + a*x^2 + b is an elliptic
277 /* check the discriminant: 301 * curve <=> b != 0 (mod p)
278 * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p)
279 */ 302 */
280 if (BN_is_zero(b)) goto err; 303 if (BN_is_zero(b))
304 goto err;
281 305
282 ret = 1; 306 ret = 1;
283 307
@@ -287,151 +311,157 @@ err:
287 if (new_ctx != NULL) 311 if (new_ctx != NULL)
288 BN_CTX_free(new_ctx); 312 BN_CTX_free(new_ctx);
289 return ret; 313 return ret;
290 } 314}
291 315
292 316
293/* Initializes an EC_POINT. */ 317/* Initializes an EC_POINT. */
294int ec_GF2m_simple_point_init(EC_POINT *point) 318int
295 { 319ec_GF2m_simple_point_init(EC_POINT * point)
320{
296 BN_init(&point->X); 321 BN_init(&point->X);
297 BN_init(&point->Y); 322 BN_init(&point->Y);
298 BN_init(&point->Z); 323 BN_init(&point->Z);
299 return 1; 324 return 1;
300 } 325}
301 326
302 327
303/* Frees an EC_POINT. */ 328/* Frees an EC_POINT. */
304void ec_GF2m_simple_point_finish(EC_POINT *point) 329void
305 { 330ec_GF2m_simple_point_finish(EC_POINT * point)
331{
306 BN_free(&point->X); 332 BN_free(&point->X);
307 BN_free(&point->Y); 333 BN_free(&point->Y);
308 BN_free(&point->Z); 334 BN_free(&point->Z);
309 } 335}
310 336
311 337
312/* Clears and frees an EC_POINT. */ 338/* Clears and frees an EC_POINT. */
313void ec_GF2m_simple_point_clear_finish(EC_POINT *point) 339void
314 { 340ec_GF2m_simple_point_clear_finish(EC_POINT * point)
341{
315 BN_clear_free(&point->X); 342 BN_clear_free(&point->X);
316 BN_clear_free(&point->Y); 343 BN_clear_free(&point->Y);
317 BN_clear_free(&point->Z); 344 BN_clear_free(&point->Z);
318 point->Z_is_one = 0; 345 point->Z_is_one = 0;
319 } 346}
320 347
321 348
322/* Copy the contents of one EC_POINT into another. Assumes dest is initialized. */ 349/* Copy the contents of one EC_POINT into another. Assumes dest is initialized. */
323int ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src) 350int
324 { 351ec_GF2m_simple_point_copy(EC_POINT * dest, const EC_POINT * src)
325 if (!BN_copy(&dest->X, &src->X)) return 0; 352{
326 if (!BN_copy(&dest->Y, &src->Y)) return 0; 353 if (!BN_copy(&dest->X, &src->X))
327 if (!BN_copy(&dest->Z, &src->Z)) return 0; 354 return 0;
355 if (!BN_copy(&dest->Y, &src->Y))
356 return 0;
357 if (!BN_copy(&dest->Z, &src->Z))
358 return 0;
328 dest->Z_is_one = src->Z_is_one; 359 dest->Z_is_one = src->Z_is_one;
329 360
330 return 1; 361 return 1;
331 } 362}
332 363
333 364
334/* Set an EC_POINT to the point at infinity. 365/* Set an EC_POINT to the point at infinity.
335 * A point at infinity is represented by having Z=0. 366 * A point at infinity is represented by having Z=0.
336 */ 367 */
337int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point) 368int
338 { 369ec_GF2m_simple_point_set_to_infinity(const EC_GROUP * group, EC_POINT * point)
370{
339 point->Z_is_one = 0; 371 point->Z_is_one = 0;
340 BN_zero(&point->Z); 372 BN_zero(&point->Z);
341 return 1; 373 return 1;
342 } 374}
343 375
344 376
345/* Set the coordinates of an EC_POINT using affine coordinates. 377/* Set the coordinates of an EC_POINT using affine coordinates.
346 * Note that the simple implementation only uses affine coordinates. 378 * Note that the simple implementation only uses affine coordinates.
347 */ 379 */
348int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point, 380int
349 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) 381ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP * group, EC_POINT * point,
350 { 382 const BIGNUM * x, const BIGNUM * y, BN_CTX * ctx)
351 int ret = 0; 383{
352 if (x == NULL || y == NULL) 384 int ret = 0;
353 { 385 if (x == NULL || y == NULL) {
354 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER); 386 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER);
355 return 0; 387 return 0;
356 } 388 }
357 389 if (!BN_copy(&point->X, x))
358 if (!BN_copy(&point->X, x)) goto err; 390 goto err;
359 BN_set_negative(&point->X, 0); 391 BN_set_negative(&point->X, 0);
360 if (!BN_copy(&point->Y, y)) goto err; 392 if (!BN_copy(&point->Y, y))
393 goto err;
361 BN_set_negative(&point->Y, 0); 394 BN_set_negative(&point->Y, 0);
362 if (!BN_copy(&point->Z, BN_value_one())) goto err; 395 if (!BN_copy(&point->Z, BN_value_one()))
396 goto err;
363 BN_set_negative(&point->Z, 0); 397 BN_set_negative(&point->Z, 0);
364 point->Z_is_one = 1; 398 point->Z_is_one = 1;
365 ret = 1; 399 ret = 1;
366 400
367 err: 401err:
368 return ret; 402 return ret;
369 } 403}
370 404
371 405
372/* Gets the affine coordinates of an EC_POINT. 406/* Gets the affine coordinates of an EC_POINT.
373 * Note that the simple implementation only uses affine coordinates. 407 * Note that the simple implementation only uses affine coordinates.
374 */ 408 */
375int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point, 409int
376 BIGNUM *x, BIGNUM *y, BN_CTX *ctx) 410ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group,
377 { 411 const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
412{
378 int ret = 0; 413 int ret = 0;
379 414
380 if (EC_POINT_is_at_infinity(group, point)) 415 if (EC_POINT_is_at_infinity(group, point)) {
381 {
382 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY); 416 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY);
383 return 0; 417 return 0;
384 } 418 }
385 419 if (BN_cmp(&point->Z, BN_value_one())) {
386 if (BN_cmp(&point->Z, BN_value_one()))
387 {
388 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 420 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
389 return 0; 421 return 0;
390 } 422 }
391 if (x != NULL) 423 if (x != NULL) {
392 { 424 if (!BN_copy(x, &point->X))
393 if (!BN_copy(x, &point->X)) goto err; 425 goto err;
394 BN_set_negative(x, 0); 426 BN_set_negative(x, 0);
395 } 427 }
396 if (y != NULL) 428 if (y != NULL) {
397 { 429 if (!BN_copy(y, &point->Y))
398 if (!BN_copy(y, &point->Y)) goto err; 430 goto err;
399 BN_set_negative(y, 0); 431 BN_set_negative(y, 0);
400 } 432 }
401 ret = 1; 433 ret = 1;
402 434
403 err: 435err:
404 return ret; 436 return ret;
405 } 437}
406 438
407/* Computes a + b and stores the result in r. r could be a or b, a could be b. 439/* Computes a + b and stores the result in r. r could be a or b, a could be b.
408 * Uses algorithm A.10.2 of IEEE P1363. 440 * Uses algorithm A.10.2 of IEEE P1363.
409 */ 441 */
410int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) 442int
411 { 443ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
444 const EC_POINT *b, BN_CTX *ctx)
445{
412 BN_CTX *new_ctx = NULL; 446 BN_CTX *new_ctx = NULL;
413 BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t; 447 BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t;
414 int ret = 0; 448 int ret = 0;
415
416 if (EC_POINT_is_at_infinity(group, a))
417 {
418 if (!EC_POINT_copy(r, b)) return 0;
419 return 1;
420 }
421 449
422 if (EC_POINT_is_at_infinity(group, b)) 450 if (EC_POINT_is_at_infinity(group, a)) {
423 { 451 if (!EC_POINT_copy(r, b))
424 if (!EC_POINT_copy(r, a)) return 0; 452 return 0;
425 return 1; 453 return 1;
426 } 454 }
427 455 if (EC_POINT_is_at_infinity(group, b)) {
428 if (ctx == NULL) 456 if (!EC_POINT_copy(r, a))
429 { 457 return 0;
458 return 1;
459 }
460 if (ctx == NULL) {
430 ctx = new_ctx = BN_CTX_new(); 461 ctx = new_ctx = BN_CTX_new();
431 if (ctx == NULL) 462 if (ctx == NULL)
432 return 0; 463 return 0;
433 } 464 }
434
435 BN_CTX_start(ctx); 465 BN_CTX_start(ctx);
436 x0 = BN_CTX_get(ctx); 466 x0 = BN_CTX_get(ctx);
437 y0 = BN_CTX_get(ctx); 467 y0 = BN_CTX_get(ctx);
@@ -441,149 +471,178 @@ int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, co
441 y2 = BN_CTX_get(ctx); 471 y2 = BN_CTX_get(ctx);
442 s = BN_CTX_get(ctx); 472 s = BN_CTX_get(ctx);
443 t = BN_CTX_get(ctx); 473 t = BN_CTX_get(ctx);
444 if (t == NULL) goto err; 474 if (t == NULL)
475 goto err;
445 476
446 if (a->Z_is_one) 477 if (a->Z_is_one) {
447 { 478 if (!BN_copy(x0, &a->X))
448 if (!BN_copy(x0, &a->X)) goto err; 479 goto err;
449 if (!BN_copy(y0, &a->Y)) goto err; 480 if (!BN_copy(y0, &a->Y))
450 } 481 goto err;
451 else 482 } else {
452 { 483 if (!EC_POINT_get_affine_coordinates_GF2m(group, a, x0, y0, ctx))
453 if (!EC_POINT_get_affine_coordinates_GF2m(group, a, x0, y0, ctx)) goto err; 484 goto err;
454 } 485 }
455 if (b->Z_is_one) 486 if (b->Z_is_one) {
456 { 487 if (!BN_copy(x1, &b->X))
457 if (!BN_copy(x1, &b->X)) goto err; 488 goto err;
458 if (!BN_copy(y1, &b->Y)) goto err; 489 if (!BN_copy(y1, &b->Y))
459 } 490 goto err;
460 else 491 } else {
461 { 492 if (!EC_POINT_get_affine_coordinates_GF2m(group, b, x1, y1, ctx))
462 if (!EC_POINT_get_affine_coordinates_GF2m(group, b, x1, y1, ctx)) goto err; 493 goto err;
463 } 494 }
464 495
465 496
466 if (BN_GF2m_cmp(x0, x1)) 497 if (BN_GF2m_cmp(x0, x1)) {
467 { 498 if (!BN_GF2m_add(t, x0, x1))
468 if (!BN_GF2m_add(t, x0, x1)) goto err; 499 goto err;
469 if (!BN_GF2m_add(s, y0, y1)) goto err; 500 if (!BN_GF2m_add(s, y0, y1))
470 if (!group->meth->field_div(group, s, s, t, ctx)) goto err; 501 goto err;
471 if (!group->meth->field_sqr(group, x2, s, ctx)) goto err; 502 if (!group->meth->field_div(group, s, s, t, ctx))
472 if (!BN_GF2m_add(x2, x2, &group->a)) goto err; 503 goto err;
473 if (!BN_GF2m_add(x2, x2, s)) goto err; 504 if (!group->meth->field_sqr(group, x2, s, ctx))
474 if (!BN_GF2m_add(x2, x2, t)) goto err; 505 goto err;
475 } 506 if (!BN_GF2m_add(x2, x2, &group->a))
476 else 507 goto err;
477 { 508 if (!BN_GF2m_add(x2, x2, s))
478 if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1)) 509 goto err;
479 { 510 if (!BN_GF2m_add(x2, x2, t))
480 if (!EC_POINT_set_to_infinity(group, r)) goto err; 511 goto err;
512 } else {
513 if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1)) {
514 if (!EC_POINT_set_to_infinity(group, r))
515 goto err;
481 ret = 1; 516 ret = 1;
482 goto err; 517 goto err;
483 }
484 if (!group->meth->field_div(group, s, y1, x1, ctx)) goto err;
485 if (!BN_GF2m_add(s, s, x1)) goto err;
486
487 if (!group->meth->field_sqr(group, x2, s, ctx)) goto err;
488 if (!BN_GF2m_add(x2, x2, s)) goto err;
489 if (!BN_GF2m_add(x2, x2, &group->a)) goto err;
490 } 518 }
519 if (!group->meth->field_div(group, s, y1, x1, ctx))
520 goto err;
521 if (!BN_GF2m_add(s, s, x1))
522 goto err;
491 523
492 if (!BN_GF2m_add(y2, x1, x2)) goto err; 524 if (!group->meth->field_sqr(group, x2, s, ctx))
493 if (!group->meth->field_mul(group, y2, y2, s, ctx)) goto err; 525 goto err;
494 if (!BN_GF2m_add(y2, y2, x2)) goto err; 526 if (!BN_GF2m_add(x2, x2, s))
495 if (!BN_GF2m_add(y2, y2, y1)) goto err; 527 goto err;
528 if (!BN_GF2m_add(x2, x2, &group->a))
529 goto err;
530 }
496 531
497 if (!EC_POINT_set_affine_coordinates_GF2m(group, r, x2, y2, ctx)) goto err; 532 if (!BN_GF2m_add(y2, x1, x2))
533 goto err;
534 if (!group->meth->field_mul(group, y2, y2, s, ctx))
535 goto err;
536 if (!BN_GF2m_add(y2, y2, x2))
537 goto err;
538 if (!BN_GF2m_add(y2, y2, y1))
539 goto err;
540
541 if (!EC_POINT_set_affine_coordinates_GF2m(group, r, x2, y2, ctx))
542 goto err;
498 543
499 ret = 1; 544 ret = 1;
500 545
501 err: 546err:
502 BN_CTX_end(ctx); 547 BN_CTX_end(ctx);
503 if (new_ctx != NULL) 548 if (new_ctx != NULL)
504 BN_CTX_free(new_ctx); 549 BN_CTX_free(new_ctx);
505 return ret; 550 return ret;
506 } 551}
507 552
508 553
509/* Computes 2 * a and stores the result in r. r could be a. 554/* Computes 2 * a and stores the result in r. r could be a.
510 * Uses algorithm A.10.2 of IEEE P1363. 555 * Uses algorithm A.10.2 of IEEE P1363.
511 */ 556 */
512int ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx) 557int
513 { 558ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
559 BN_CTX *ctx)
560{
514 return ec_GF2m_simple_add(group, r, a, a, ctx); 561 return ec_GF2m_simple_add(group, r, a, a, ctx);
515 } 562}
516
517 563
518int ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) 564int
519 { 565ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
566{
520 if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y)) 567 if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y))
521 /* point is its own inverse */ 568 /* point is its own inverse */
522 return 1; 569 return 1;
523 570
524 if (!EC_POINT_make_affine(group, point, ctx)) return 0; 571 if (!EC_POINT_make_affine(group, point, ctx))
572 return 0;
525 return BN_GF2m_add(&point->Y, &point->X, &point->Y); 573 return BN_GF2m_add(&point->Y, &point->X, &point->Y);
526 } 574}
527 575
528 576
529/* Indicates whether the given point is the point at infinity. */ 577/* Indicates whether the given point is the point at infinity. */
530int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) 578int
531 { 579ec_GF2m_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
580{
532 return BN_is_zero(&point->Z); 581 return BN_is_zero(&point->Z);
533 } 582}
534 583
535 584
536/* Determines whether the given EC_POINT is an actual point on the curve defined 585/* Determines whether the given EC_POINT is an actual point on the curve defined
537 * in the EC_GROUP. A point is valid if it satisfies the Weierstrass equation: 586 * in the EC_GROUP. A point is valid if it satisfies the Weierstrass equation:
538 * y^2 + x*y = x^3 + a*x^2 + b. 587 * y^2 + x*y = x^3 + a*x^2 + b.
539 */ 588 */
540int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx) 589int
541 { 590ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
591{
542 int ret = -1; 592 int ret = -1;
543 BN_CTX *new_ctx = NULL; 593 BN_CTX *new_ctx = NULL;
544 BIGNUM *lh, *y2; 594 BIGNUM *lh, *y2;
545 int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); 595 int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
546 int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); 596 int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
547 597
548 if (EC_POINT_is_at_infinity(group, point)) 598 if (EC_POINT_is_at_infinity(group, point))
549 return 1; 599 return 1;
550 600
551 field_mul = group->meth->field_mul; 601 field_mul = group->meth->field_mul;
552 field_sqr = group->meth->field_sqr; 602 field_sqr = group->meth->field_sqr;
553 603
554 /* only support affine coordinates */ 604 /* only support affine coordinates */
555 if (!point->Z_is_one) return -1; 605 if (!point->Z_is_one)
606 return -1;
556 607
557 if (ctx == NULL) 608 if (ctx == NULL) {
558 {
559 ctx = new_ctx = BN_CTX_new(); 609 ctx = new_ctx = BN_CTX_new();
560 if (ctx == NULL) 610 if (ctx == NULL)
561 return -1; 611 return -1;
562 } 612 }
563
564 BN_CTX_start(ctx); 613 BN_CTX_start(ctx);
565 y2 = BN_CTX_get(ctx); 614 y2 = BN_CTX_get(ctx);
566 lh = BN_CTX_get(ctx); 615 lh = BN_CTX_get(ctx);
567 if (lh == NULL) goto err; 616 if (lh == NULL)
617 goto err;
568 618
569 /* We have a curve defined by a Weierstrass equation 619 /*
570 * y^2 + x*y = x^3 + a*x^2 + b. 620 * We have a curve defined by a Weierstrass equation y^2 + x*y = x^3
571 * <=> x^3 + a*x^2 + x*y + b + y^2 = 0 621 * + a*x^2 + b. <=> x^3 + a*x^2 + x*y + b + y^2 = 0 <=> ((x + a) * x
572 * <=> ((x + a) * x + y ) * x + b + y^2 = 0 622 * + y ) * x + b + y^2 = 0
573 */ 623 */
574 if (!BN_GF2m_add(lh, &point->X, &group->a)) goto err; 624 if (!BN_GF2m_add(lh, &point->X, &group->a))
575 if (!field_mul(group, lh, lh, &point->X, ctx)) goto err; 625 goto err;
576 if (!BN_GF2m_add(lh, lh, &point->Y)) goto err; 626 if (!field_mul(group, lh, lh, &point->X, ctx))
577 if (!field_mul(group, lh, lh, &point->X, ctx)) goto err; 627 goto err;
578 if (!BN_GF2m_add(lh, lh, &group->b)) goto err; 628 if (!BN_GF2m_add(lh, lh, &point->Y))
579 if (!field_sqr(group, y2, &point->Y, ctx)) goto err; 629 goto err;
580 if (!BN_GF2m_add(lh, lh, y2)) goto err; 630 if (!field_mul(group, lh, lh, &point->X, ctx))
631 goto err;
632 if (!BN_GF2m_add(lh, lh, &group->b))
633 goto err;
634 if (!field_sqr(group, y2, &point->Y, ctx))
635 goto err;
636 if (!BN_GF2m_add(lh, lh, y2))
637 goto err;
581 ret = BN_is_zero(lh); 638 ret = BN_is_zero(lh);
582 err: 639err:
583 if (ctx) BN_CTX_end(ctx); 640 if (ctx)
584 if (new_ctx) BN_CTX_free(new_ctx); 641 BN_CTX_end(ctx);
642 if (new_ctx)
643 BN_CTX_free(new_ctx);
585 return ret; 644 return ret;
586 } 645}
587 646
588 647
589/* Indicates whether two points are equal. 648/* Indicates whether two points are equal.
@@ -592,118 +651,132 @@ int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_
592 * 0 equal (in affine coordinates) 651 * 0 equal (in affine coordinates)
593 * 1 not equal 652 * 1 not equal
594 */ 653 */
595int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) 654int
596 { 655ec_GF2m_simple_cmp(const EC_GROUP * group, const EC_POINT * a, const EC_POINT * b, BN_CTX * ctx)
656{
597 BIGNUM *aX, *aY, *bX, *bY; 657 BIGNUM *aX, *aY, *bX, *bY;
598 BN_CTX *new_ctx = NULL; 658 BN_CTX *new_ctx = NULL;
599 int ret = -1; 659 int ret = -1;
600 660
601 if (EC_POINT_is_at_infinity(group, a)) 661 if (EC_POINT_is_at_infinity(group, a)) {
602 {
603 return EC_POINT_is_at_infinity(group, b) ? 0 : 1; 662 return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
604 } 663 }
605
606 if (EC_POINT_is_at_infinity(group, b)) 664 if (EC_POINT_is_at_infinity(group, b))
607 return 1; 665 return 1;
608
609 if (a->Z_is_one && b->Z_is_one)
610 {
611 return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
612 }
613 666
614 if (ctx == NULL) 667 if (a->Z_is_one && b->Z_is_one) {
615 { 668 return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
669 }
670 if (ctx == NULL) {
616 ctx = new_ctx = BN_CTX_new(); 671 ctx = new_ctx = BN_CTX_new();
617 if (ctx == NULL) 672 if (ctx == NULL)
618 return -1; 673 return -1;
619 } 674 }
620
621 BN_CTX_start(ctx); 675 BN_CTX_start(ctx);
622 aX = BN_CTX_get(ctx); 676 aX = BN_CTX_get(ctx);
623 aY = BN_CTX_get(ctx); 677 aY = BN_CTX_get(ctx);
624 bX = BN_CTX_get(ctx); 678 bX = BN_CTX_get(ctx);
625 bY = BN_CTX_get(ctx); 679 bY = BN_CTX_get(ctx);
626 if (bY == NULL) goto err; 680 if (bY == NULL)
681 goto err;
627 682
628 if (!EC_POINT_get_affine_coordinates_GF2m(group, a, aX, aY, ctx)) goto err; 683 if (!EC_POINT_get_affine_coordinates_GF2m(group, a, aX, aY, ctx))
629 if (!EC_POINT_get_affine_coordinates_GF2m(group, b, bX, bY, ctx)) goto err; 684 goto err;
685 if (!EC_POINT_get_affine_coordinates_GF2m(group, b, bX, bY, ctx))
686 goto err;
630 ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1; 687 ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1;
631 688
632 err: 689err:
633 if (ctx) BN_CTX_end(ctx); 690 if (ctx)
634 if (new_ctx) BN_CTX_free(new_ctx); 691 BN_CTX_end(ctx);
692 if (new_ctx)
693 BN_CTX_free(new_ctx);
635 return ret; 694 return ret;
636 } 695}
637 696
638 697
639/* Forces the given EC_POINT to internally use affine coordinates. */ 698/* Forces the given EC_POINT to internally use affine coordinates. */
640int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) 699int
641 { 700ec_GF2m_simple_make_affine(const EC_GROUP * group, EC_POINT * point, BN_CTX * ctx)
701{
642 BN_CTX *new_ctx = NULL; 702 BN_CTX *new_ctx = NULL;
643 BIGNUM *x, *y; 703 BIGNUM *x, *y;
644 int ret = 0; 704 int ret = 0;
645 705
646 if (point->Z_is_one || EC_POINT_is_at_infinity(group, point)) 706 if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
647 return 1; 707 return 1;
648 708
649 if (ctx == NULL) 709 if (ctx == NULL) {
650 {
651 ctx = new_ctx = BN_CTX_new(); 710 ctx = new_ctx = BN_CTX_new();
652 if (ctx == NULL) 711 if (ctx == NULL)
653 return 0; 712 return 0;
654 } 713 }
655
656 BN_CTX_start(ctx); 714 BN_CTX_start(ctx);
657 x = BN_CTX_get(ctx); 715 x = BN_CTX_get(ctx);
658 y = BN_CTX_get(ctx); 716 y = BN_CTX_get(ctx);
659 if (y == NULL) goto err; 717 if (y == NULL)
660 718 goto err;
661 if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err; 719
662 if (!BN_copy(&point->X, x)) goto err; 720 if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx))
663 if (!BN_copy(&point->Y, y)) goto err; 721 goto err;
664 if (!BN_one(&point->Z)) goto err; 722 if (!BN_copy(&point->X, x))
665 723 goto err;
666 ret = 1; 724 if (!BN_copy(&point->Y, y))
667 725 goto err;
668 err: 726 if (!BN_one(&point->Z))
669 if (ctx) BN_CTX_end(ctx); 727 goto err;
670 if (new_ctx) BN_CTX_free(new_ctx); 728
729 ret = 1;
730
731err:
732 if (ctx)
733 BN_CTX_end(ctx);
734 if (new_ctx)
735 BN_CTX_free(new_ctx);
671 return ret; 736 return ret;
672 } 737}
673 738
674 739
675/* Forces each of the EC_POINTs in the given array to use affine coordinates. */ 740/* Forces each of the EC_POINTs in the given array to use affine coordinates. */
676int ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx) 741int
677 { 742ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num,
743 EC_POINT *points[], BN_CTX *ctx)
744{
678 size_t i; 745 size_t i;
679 746
680 for (i = 0; i < num; i++) 747 for (i = 0; i < num; i++) {
681 { 748 if (!group->meth->make_affine(group, points[i], ctx))
682 if (!group->meth->make_affine(group, points[i], ctx)) return 0; 749 return 0;
683 } 750 }
684 751
685 return 1; 752 return 1;
686 } 753}
687 754
688 755
689/* Wrapper to simple binary polynomial field multiplication implementation. */ 756/* Wrapper to simple binary polynomial field multiplication implementation. */
690int ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) 757int
691 { 758ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
759 const BIGNUM *b, BN_CTX *ctx)
760{
692 return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx); 761 return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx);
693 } 762}
694 763
695 764
696/* Wrapper to simple binary polynomial field squaring implementation. */ 765/* Wrapper to simple binary polynomial field squaring implementation. */
697int ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) 766int
698 { 767ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
768 BN_CTX *ctx)
769{
699 return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx); 770 return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx);
700 } 771}
701 772
702 773
703/* Wrapper to simple binary polynomial field division implementation. */ 774/* Wrapper to simple binary polynomial field division implementation. */
704int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) 775int
705 { 776ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
777 const BIGNUM *b, BN_CTX *ctx)
778{
706 return BN_GF2m_mod_div(r, a, b, &group->field, ctx); 779 return BN_GF2m_mod_div(r, a, b, &group->field, ctx);
707 } 780}
708 781
709#endif 782#endif