]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/ec/ecp_smpl.c
More method functions.
[thirdparty/openssl.git] / crypto / ec / ecp_smpl.c
CommitLineData
f8fe20e0 1/* crypto/ec/ecp_smpl.c */
60428dbf
BM
2/* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de>
3 * for the OpenSSL project. */
f8fe20e0
BM
4/* ====================================================================
5 * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * 3. All advertising materials mentioning features or use of this
20 * software must display the following acknowledgment:
21 * "This product includes software developed by the OpenSSL Project
22 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
23 *
24 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25 * endorse or promote products derived from this software without
26 * prior written permission. For written permission, please contact
27 * openssl-core@openssl.org.
28 *
29 * 5. Products derived from this software may not be called "OpenSSL"
30 * nor may "OpenSSL" appear in their names without prior written
31 * permission of the OpenSSL Project.
32 *
33 * 6. Redistributions of any form whatsoever must retain the following
34 * acknowledgment:
35 * "This product includes software developed by the OpenSSL Project
36 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
37 *
38 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
42 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49 * OF THE POSSIBILITY OF SUCH DAMAGE.
50 * ====================================================================
51 *
52 * This product includes cryptographic software written by Eric Young
53 * (eay@cryptsoft.com). This product includes software written by Tim
54 * Hudson (tjh@cryptsoft.com).
55 *
56 */
57
60428dbf
BM
58#include <openssl/err.h>
59
f8fe20e0 60#include "ec_lcl.h"
0657bf9c
BM
61
62
63const EC_METHOD *EC_GFp_simple_method(void)
64 {
58fc6229
BM
65 static const EC_METHOD ret = {
66 ec_GFp_simple_group_init,
67 ec_GFp_simple_group_set_curve_GFp,
68 ec_GFp_simple_group_finish,
69 ec_GFp_simple_group_clear_finish,
70 ec_GFp_simple_group_copy,
71 ec_GFp_simple_group_set_generator,
72 /* TODO: 'set' and 'get' functions for EC_GROUPs */
73 ec_GFp_simple_point_init,
74 ec_GFp_simple_point_finish,
75 ec_GFp_simple_point_clear_finish,
76 ec_GFp_simple_point_copy,
77 /* TODO: 'set' and 'get' functions for EC_POINTs */
78 ec_GFp_simple_point2oct,
79 ec_GFp_simple_oct2point,
80 ec_GFp_simple_add,
81 ec_GFp_simple_dbl,
82 ec_GFp_simple_is_at_infinity,
83 ec_GFp_simple_is_on_curve,
84 ec_GFp_simple_make_affine,
60428dbf 85 ec_GFp_simple_field_mul,
58fc6229
BM
86 ec_GFp_simple_field_sqr,
87 0 /* field_encode */,
88 0 /* field_decode */ };
0657bf9c
BM
89
90 return &ret;
91 }
60428dbf
BM
92
93
94int ec_GFp_simple_group_init(EC_GROUP *group)
95 {
96 BN_init(&group->field);
97 BN_init(&group->a);
98 BN_init(&group->b);
99 group->a_is_minus3 = 0;
100 group->generator = NULL;
101 BN_init(&group->order);
102 BN_init(&group->cofactor);
103 return 1;
104 }
105
106
107int ec_GFp_simple_group_set_curve_GFp(EC_GROUP *group,
108 const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
109 {
110 int ret = 0;
111 BN_CTX *new_ctx = NULL;
112 BIGNUM *tmp_a;
113
114 if (ctx == NULL)
115 {
116 ctx = new_ctx = BN_CTX_new();
117 if (ctx == NULL)
118 return 0;
119 }
120 BN_CTX_start(ctx);
121
122 tmp_a = BN_CTX_get(ctx);
123 if (tmp_a == NULL) goto err;
124
125 /* group->field */
126 if (!BN_copy(&group->field, p)) goto err;
127 group->field.neg = 0;
128
129 /* group->a */
130 if (!BN_nnmod(tmp_a, a, p, ctx)) goto err;
131 if (group->meth->field_encode)
132 { if (!group->meth->field_encode(group, &group->a, tmp_a, ctx)) goto err; }
133 else
134 if (!BN_copy(&group->a, tmp_a)) goto err;
135
136 /* group->b */
137 if (!BN_nnmod(&group->b, b, p, ctx)) goto err;
138 if (group->meth->field_encode)
139 if (!group->meth->field_encode(group, &group->b, &group->b, ctx)) goto err;
140
141 /* group->a_is_minus3 */
142 if (!BN_add_word(tmp_a, 3)) goto err;
143 group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field));
144
145 ret = 1;
146
147 err:
148 BN_CTX_end(ctx);
149 if (new_ctx != NULL)
150 BN_CTX_free(new_ctx);
151 return ret;
152 }
153
154
155void ec_GFp_simple_group_finish(EC_GROUP *group)
156 {
157 BN_free(&group->field);
158 BN_free(&group->a);
159 BN_free(&group->b);
160 if (group->generator != NULL)
161 EC_POINT_free(group->generator);
162 BN_free(&group->order);
163 BN_free(&group->cofactor);
164 }
165
166
167void ec_GFp_simple_group_clear_finish(EC_GROUP *group)
168 {
169 BN_clear_free(&group->field);
170 BN_clear_free(&group->a);
171 BN_clear_free(&group->b);
172 if (group->generator != NULL)
173 {
174 EC_POINT_clear_free(group->generator);
175 group->generator = NULL;
176 }
177 BN_clear_free(&group->order);
178 BN_clear_free(&group->cofactor);
179 }
180
181
182int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
183 {
184 if (!BN_copy(&dest->field, &src->field)) return 0;
185 if (!BN_copy(&dest->a, &src->a)) return 0;
186 if (!BN_copy(&dest->b, &src->b)) return 0;
187
188 dest->a_is_minus3 = src->a_is_minus3;
189
190 if (src->generator != NULL)
191 {
192 if (dest->generator == NULL)
193 {
194 dest->generator = EC_POINT_new(dest);
195 if (dest->generator == NULL) return 0;
196 }
197 if (!EC_POINT_copy(dest->generator, src->generator)) return 0;
198 }
199 else
200 {
201 /* src->generator == NULL */
202 if (dest->generator != NULL)
203 {
204 EC_POINT_clear_free(dest->generator);
205 dest->generator = NULL;
206 }
207 }
208
209 if (!BN_copy(&dest->order, &src->order)) return 0;
210 if (!BN_copy(&dest->cofactor, &src->cofactor)) return 0;
211
212 return 1;
213 }
214
215
216int ec_GFp_simple_group_set_generator(EC_GROUP *group, const EC_POINT *generator,
217 const BIGNUM *order, const BIGNUM *cofactor)
218 {
219 if (generator)
220 {
221 ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER);
222 return 0 ;
223 }
224
225 if (group->generator == NULL)
226 {
227 group->generator = EC_POINT_new(group);
228 if (group->generator == NULL) return 0;
229 }
230 if (!EC_POINT_copy(group->generator, generator)) return 0;
231
232 if (order != NULL)
233 { if (!BN_copy(&group->order, order)) return 0; }
234 else
235 { if (!BN_zero(&group->order)) return 0; }
236
237 if (cofactor != NULL)
238 { if (!BN_copy(&group->cofactor, cofactor)) return 0; }
239 else
240 { if (!BN_zero(&group->cofactor)) return 0; }
241
242 return 1;
243 }
244
245
246/* TODO: 'set' and 'get' functions for EC_GROUPs */
247
248
249int ec_GFp_simple_point_init(EC_POINT *point)
250 {
251 BN_init(&point->X);
252 BN_init(&point->Y);
253 BN_init(&point->Z);
254 point->Z_is_one = 0;
255
256 return 1;
257 }
258
259
260void ec_GFp_simple_point_finish(EC_POINT *point)
261 {
262 BN_free(&point->X);
263 BN_free(&point->Y);
264 BN_free(&point->Z);
265 }
266
267
268void ec_GFp_simple_point_clear_finish(EC_POINT *point)
269 {
270 BN_clear_free(&point->X);
271 BN_clear_free(&point->Y);
272 BN_clear_free(&point->Z);
273 point->Z_is_one = 0;
274 }
275
276
277int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
278 {
279 if (!BN_copy(&dest->X, &src->X)) return 0;
280 if (!BN_copy(&dest->Y, &src->Y)) return 0;
281 if (!BN_copy(&dest->Z, &src->Z)) return 0;
282 dest->Z_is_one = src->Z_is_one;
283
284 return 1;
285 }
286
287
288/* TODO: 'set' and 'get' functions for EC_POINTs */
289
290
291size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
292 unsigned char *buf, size_t len, BN_CTX *ctx);
293/* TODO */
294
295
296int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
297 const unsigned char *buf, size_t len, BN_CTX *);
298/* TODO */
299
300
301int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
302 {
303 int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
304 int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
305 const BIGNUM *p;
306 BN_CTX *new_ctx = NULL;
307 BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6;
308 int ret = 0;
309
310 if (a == b)
311 return EC_POINT_dbl(group, r, a, ctx);
312 if (EC_POINT_is_at_infinity(group, a))
313 return EC_POINT_copy(r, b);
314 if (EC_POINT_is_at_infinity(group, b))
315 return EC_POINT_copy(r, a);
316
317 field_mul = group->meth->field_mul;
318 field_sqr = group->meth->field_sqr;
319 p = &group->field;
320
321 if (ctx == NULL)
322 {
323 ctx = new_ctx = BN_CTX_new();
324 if (ctx == NULL)
325 return 0;
326 }
327 BN_CTX_start(ctx);
328
329 n0 = BN_CTX_get(ctx);
330 n1 = BN_CTX_get(ctx);
331 n2 = BN_CTX_get(ctx);
332 n3 = BN_CTX_get(ctx);
333 n4 = BN_CTX_get(ctx);
334 n5 = BN_CTX_get(ctx);
335 n6 = BN_CTX_get(ctx);
336 if (n6 == NULL) goto end;
337
338 /* n1, n2 */
339 if (b->Z_is_one)
340 {
341 if (!BN_copy(n1, &a->X)) goto end;
342 if (!BN_copy(n2, &a->Y)) goto end;
343 /* n1 = X_a */
344 /* n2 = Y_a */
345 }
346 else
347 {
348 if (!field_sqr(group, n0, &b->Z, ctx)) goto end;
349 if (!field_mul(group, n1, &a->X, n0, ctx)) goto end;
350 /* n1 = X_a * Z_b^2 */
351
352 if (!field_mul(group, n0, n0, &b->Z, ctx)) goto end;
353 if (!field_mul(group, n2, &a->Y, n0, ctx)) goto end;
354 /* n2 = Y_a * Z_b^3 */
355 }
356
357 /* n3, n4 */
358 if (a->Z_is_one)
359 {
360 if (!BN_copy(n3, &b->X)) goto end;
361 if (!BN_copy(n4, &b->Y)) goto end;
362 /* n3 = X_b */
363 /* n4 = Y_b */
364 }
365 else
366 {
367 if (!field_sqr(group, n0, &a->Z, ctx)) goto end;
368 if (!field_mul(group, n3, &b->X, n0, ctx)) goto end;
369 /* n3 = X_b * Z_a^2 */
370
371 if (!field_mul(group, n0, n0, &a->Z, ctx)) goto end;
372 if (!field_mul(group, n4, &b->Y, n0, ctx)) goto end;
373 /* n4 = Y_b * Z_a^3 */
374 }
375
376 /* n5, n6 */
377 if (!BN_mod_sub_quick(n5, n1, n3, p)) goto end;
378 if (!BN_mod_sub_quick(n6, n2, n4, p)) goto end;
379 /* n5 = n1 - n3 */
380 /* n6 = n2 - n4 */
381
382 if (BN_is_zero(n5))
383 {
384 if (BN_is_zero(n6))
385 {
386 /* a is the same point as b */
387 BN_CTX_end(ctx);
60428dbf 388 ret = EC_POINT_dbl(group, r, a, ctx);
e869d4bd 389 ctx = NULL;
60428dbf
BM
390 goto end;
391 }
392 else
393 {
394 /* a is the inverse of b */
395 if (!BN_zero(&r->Z)) goto end;
396 r->Z_is_one = 0;
397 ret = 1;
398 goto end;
399 }
400 }
401
402 /* 'n7', 'n8' */
403 if (!BN_mod_add_quick(n1, n1, n3, p)) goto end;
404 if (!BN_mod_add_quick(n2, n2, n4, p)) goto end;
405 /* 'n7' = n1 + n3 */
406 /* 'n8' = n2 + n4 */
407
408 /* Z_r */
409 if (a->Z_is_one && b->Z_is_one)
410 {
411 if (!BN_copy(&r->Z, n5)) goto end;
412 }
413 else
414 {
415 if (a->Z_is_one)
416 { if (!BN_copy(n0, &b->Z)) goto end; }
417 else if (b->Z_is_one)
418 { if (!BN_copy(n0, &a->Z)) goto end; }
419 else
420 { if (!field_mul(group, n0, &a->Z, &b->Z, ctx)) goto end; }
421 if (!field_mul(group, &r->Z, n0, n5, ctx)) goto end;
422 }
423 r->Z_is_one = 0;
424 /* Z_r = Z_a * Z_b * n5 */
425
426 /* X_r */
427 if (!field_sqr(group, n0, n6, ctx)) goto end;
428 if (!field_sqr(group, n4, n5, ctx)) goto end;
429 if (!field_mul(group, n3, n1, n4, ctx)) goto end;
430 if (!BN_mod_sub_quick(&r->X, n0, n3, p)) goto end;
431 /* X_r = n6^2 - n5^2 * 'n7' */
432
433 /* 'n9' */
434 if (!BN_mod_lshift1_quick(n0, &r->X, p)) goto end;
435 if (!BN_mod_sub_quick(n0, n3, n0, p)) goto end;
436 /* n9 = n5^2 * 'n7' - 2 * X_r */
437
438 /* Y_r */
439 if (!field_mul(group, n0, n0, n6, ctx)) goto end;
440 if (!field_mul(group, n5, n4, n5, ctx)) goto end; /* now n5 is n5^3 */
441 if (!field_mul(group, n1, n2, n5, ctx)) goto end;
442 if (!BN_mod_sub_quick(n0, n0, n1, p)) goto end;
443 if (BN_is_odd(n0))
444 if (!BN_add(n0, n0, p)) goto end;
445 /* now 0 <= n0 < 2*p, and n0 is even */
446 if (!BN_rshift1(&r->Y, n0)) goto end;
447 /* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */
448
449 ret = 1;
450
451 end:
452 if (ctx) /* otherwise we already called BN_CTX_end */
453 BN_CTX_end(ctx);
454 if (new_ctx != NULL)
455 BN_CTX_free(new_ctx);
456 return ret;
457 }
458
459
460int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
461 {
462 int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
463 int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
464 const BIGNUM *p;
465 BN_CTX *new_ctx = NULL;
466 BIGNUM *n0, *n1, *n2, *n3;
467 int ret = 0;
468
469 if (EC_POINT_is_at_infinity(group, a))
470 {
471 if (!BN_zero(&r->Z)) return 0;
472 r->Z_is_one = 0;
473 return 1;
474 }
475
476 field_mul = group->meth->field_mul;
477 field_sqr = group->meth->field_sqr;
478 p = &group->field;
479
480 if (ctx == NULL)
481 {
482 ctx = new_ctx = BN_CTX_new();
483 if (ctx == NULL)
484 return 0;
485 }
486 BN_CTX_start(ctx);
487
488 n0 = BN_CTX_get(ctx);
489 n1 = BN_CTX_get(ctx);
490 n2 = BN_CTX_get(ctx);
491 n3 = BN_CTX_get(ctx);
492 if (n3 == NULL) goto err;
493
60428dbf
BM
494 /* n1 */
495 if (a->Z_is_one)
496 {
497 if (!field_sqr(group, n0, &a->X, ctx)) goto err;
498 if (!BN_mod_lshift1_quick(n1, n0, p)) goto err;
499 if (!BN_mod_add_quick(n0, n0, n1, p)) goto err;
500 if (!BN_mod_add_quick(n1, n0, &group->a, p)) goto err;
501 /* n1 = 3 * X_a^2 + a_curve */
502 }
503 else if (group->a_is_minus3)
504 {
505 if (!field_sqr(group, n1, &a->Z, ctx)) goto err;
506 if (!BN_mod_add_quick(n0, &a->X, n1, p)) goto err;
507 if (!BN_mod_sub_quick(n2, &a->X, n1, p)) goto err;
508 if (!field_mul(group, n1, n0, n2, ctx)) goto err;
509 if (!BN_mod_lshift1_quick(n0, n1, p)) goto err;
510 if (!BN_mod_add_quick(n1, n0, n1, p)) goto err;
511 /* n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2)
512 * = 3 * X_a^2 - 3 * Z_a^4 */
513 }
514 else
515 {
516 if (!field_sqr(group, n0, &a->X, ctx)) goto err;
517 if (!BN_mod_lshift1_quick(n1, n0, p)) goto err;
518 if (!BN_mod_add_quick(n0, n0, n1, p)) goto err;
519 if (!field_sqr(group, n1, &a->Z, ctx)) goto err;
520 if (!field_sqr(group, n1, n1, ctx)) goto err;
521 if (!field_mul(group, n1, n1, &group->a, ctx)) goto err;
522 if (!BN_mod_add_quick(n1, n1, n0, p)) goto err;
523 /* n1 = 3 * X_a^2 + a_curve * Z_a^4 */
524 }
525
526 /* Z_r */
527 if (a->Z_is_one)
528 {
529 if (!BN_copy(n0, &a->Y)) goto err;
530 }
531 else
532 {
533 if (!field_mul(group, n0, &a->Y, &a->Z, ctx)) goto err;
534 }
535 if (!BN_mod_lshift1_quick(&r->Z, n0, p)) goto err;
536 r->Z_is_one = 0;
537 /* Z_r = 2 * Y_a * Z_a */
538
539 /* n2 */
540 if (!field_sqr(group, n3, &a->Y, ctx)) goto err;
541 if (!field_mul(group, n2, &a->X, n3, ctx)) goto err;
542 if (!BN_mod_lshift_quick(n2, n2, 2, p)) goto err;
543 /* n2 = 4 * X_a * Y_a^2 */
544
545 /* X_r */
546 if (!BN_mod_lshift1_quick(n0, n2, p)) goto err;
547 if (!field_sqr(group, &r->X, n1, ctx)) goto err;
548 if (!BN_mod_sub_quick(&r->X, &r->X, n0, p)) goto err;
549 /* X_r = n1^2 - 2 * n2 */
550
551 /* n3 */
552 if (!field_sqr(group, n0, n3, ctx)) goto err;
553 if (!BN_mod_lshift_quick(n3, n0, 3, p)) goto err;
554 /* n3 = 8 * Y_a^4 */
555
556 /* Y_r */
557 if (!BN_mod_sub_quick(n0, n2, &r->X, p)) goto err;
558 if (!field_mul(group, n0, n1, n0, ctx)) goto err;
559 if (!BN_mod_sub_quick(&r->Y, n0, n3, p)) goto err;
560 /* Y_r = n1 * (n2 - X_r) - n3 */
561
562 ret = 1;
563
564 err:
565 BN_CTX_end(ctx);
566 if (new_ctx != NULL)
567 BN_CTX_free(new_ctx);
568 return ret;
569 }
570
571
572int ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
573 {
574 return BN_is_zero(&point->Z);
575 }
576
577
e869d4bd
BM
578int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
579 {
580 int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
581 int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
582 const BIGNUM *p;
583 BN_CTX *new_ctx = NULL;
584 BIGNUM *rh, *tmp1, *tmp2, *Z4, *Z6;
585 int ret = -1;
60428dbf 586
e869d4bd
BM
587 if (EC_POINT_is_at_infinity(group, point))
588 return 1;
589
590 field_mul = group->meth->field_mul;
591 field_sqr = group->meth->field_sqr;
592 p = &group->field;
60428dbf 593
e869d4bd
BM
594 if (ctx == NULL)
595 {
596 ctx = new_ctx = BN_CTX_new();
597 if (ctx == NULL)
598 return 0;
599 }
600 BN_CTX_start(ctx);
601
602 rh = BN_CTX_get(ctx);
603 tmp1 = BN_CTX_get(ctx);
604 tmp2 = BN_CTX_get(ctx);
605 Z4 = BN_CTX_get(ctx);
606 Z6 = BN_CTX_get(ctx);
607 if (Z6 == NULL) goto err;
608
609 /* We have a curve defined by a Weierstrass equation
610 * y^2 = x^3 + a*x + b.
611 * The point to consider is given in Jacobian projective coordinates
612 * where (X, Y, Z) represents (x, y) = (X/Z^2, Y/Z^3).
613 * Substituting this and multiplying by Z^6 transforms the above equation into
614 * Y^2 = X^3 + a*X*Z^4 + b*Z^6.
615 * To test this, we add up the right-hand side in 'rh'.
616 */
617
618 /* rh := X^3 */
619 if (!field_sqr(group, rh, &point->X, ctx)) goto err;
620 if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
621
622 if (!point->Z_is_one)
623 {
624 if (!field_sqr(group, tmp1, &point->Z, ctx)) goto err;
625 if (!field_sqr(group, Z4, tmp1, ctx)) goto err;
626 if (!field_mul(group, Z6, Z4, tmp1, ctx)) goto err;
627
628 /* rh := rh + a*X*Z^4 */
629 if (!field_mul(group, tmp1, &point->X, Z4, ctx)) goto err;
630 if (&group->a_is_minus3)
631 {
632 if (!BN_mod_lshift1_quick(tmp2, tmp1, p)) goto err;
633 if (!BN_mod_add_quick(tmp2, tmp2, tmp1, p)) goto err;
634 if (!BN_mod_sub_quick(rh, rh, tmp2, p)) goto err;
635 }
636 else
637 {
638 if (!field_mul(group, tmp2, tmp1, &group->a, ctx)) goto err;
639 if (!BN_mod_add_quick(rh, rh, tmp2, p)) goto err;
640 }
641
642 /* rh := rh + b*Z^6 */
643 if (!field_mul(group, tmp1, &group->b, Z6, ctx)) goto err;
644 if (!BN_mod_add_quick(rh, rh, tmp1, p)) goto err;
645 }
646 else
647 {
648 /* point->Z_is_one */
649
650 /* rh := rh + a*X */
651 if (&group->a_is_minus3)
652 {
653 if (!BN_mod_lshift1_quick(tmp2, &point->X, p)) goto err;
654 if (!BN_mod_add_quick(tmp2, tmp2, &point->X, p)) goto err;
655 if (!BN_mod_sub_quick(rh, rh, tmp2, p)) goto err;
656 }
657 else
658 {
659 if (!field_mul(group, tmp2, &point->X, &group->a, ctx)) goto err;
660 if (!BN_mod_add_quick(rh, rh, tmp2, p)) goto err;
661 }
662
663 /* rh := rh + b */
664 if (!BN_mod_add_quick(rh, rh, &group->b, p)) goto err;
665 }
666
667 /* 'lh' := Y^2 */
668 if (!field_sqr(group, tmp1, &point->Y, ctx)) goto err;
669
670 ret = (0 == BN_cmp(tmp1, rh));
671
672 err:
673 BN_CTX_end(ctx);
674 if (new_ctx != NULL)
675 BN_CTX_free(new_ctx);
676 return ret;
677 }
678
679
680int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
681 {
682 BN_CTX *new_ctx = NULL;
683 BIGNUM *Z, *Z_1, *Z_2, *Z_3;
684 int ret = 0;
685
686 if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
687 return 1;
688
689 if (ctx == NULL)
690 {
691 ctx = new_ctx = BN_CTX_new();
692 if (ctx == NULL)
693 return 0;
694 }
695 BN_CTX_start(ctx);
696
697 Z = BN_CTX_get(ctx);
698 Z_1 = BN_CTX_get(ctx);
699 Z_2 = BN_CTX_get(ctx);
700 Z_3 = BN_CTX_get(ctx);
701 if (Z_3 == NULL) goto end;
702
703 /* transform (X, Y, Z) into (X/Z^2, Y/Z^3, 1) */
704
705 if (group->meth->field_decode)
706 {
707 if (!group->meth->field_decode(group, Z, &point->Z, ctx)) goto end;
708 }
709 else
710 Z = &point->Z;
711
712 if (BN_is_one(Z))
713 {
714 point->Z_is_one = 1;
715 ret = 1;
716 goto end;
717 }
718
719 if (!BN_mod_inverse(Z_1, Z, &group->field, ctx))
720 {
721 ECerr(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE, ERR_R_BN_LIB);
722 goto end;
723 }
724 if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) goto end;
725 if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) goto end;
726
727 if (!BN_mod_mul(&point->X, &point->X, Z_2, &group->field, ctx)) goto end;
728 if (!BN_mod_mul(&point->Y, &point->Y, Z_2, &group->field, ctx)) goto end;
729 if (!BN_set_word(&point->Z, 1)) goto end;
730 point->Z_is_one = 1;
731
732 ret = 1;
733
734 end:
735 BN_CTX_end(ctx);
736 if (new_ctx != NULL)
737 BN_CTX_free(new_ctx);
738 return ret;
739 }
60428dbf
BM
740
741
742int ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
743 {
744 return BN_mod_mul(r, a, b, &group->field, ctx);
745 }
746
747
748int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
749 {
750 return BN_mod_sqr(r, a, &group->field, ctx);
751 }