Additional comment changes for reformat of 1.0.0
[openssl.git] / crypto / ec / ec2_smpl.c
1 /* crypto/ec/ec2_smpl.c */
2 /* ====================================================================
3  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
4  *
5  * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
6  * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
7  * to the OpenSSL project.
8  *
9  * The ECC Code is licensed pursuant to the OpenSSL open source
10  * license provided below.
11  *
12  * The software is originally written by Sheueling Chang Shantz and
13  * Douglas Stebila of Sun Microsystems Laboratories.
14  *
15  */
16 /* ====================================================================
17  * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
18  *
19  * Redistribution and use in source and binary forms, with or without
20  * modification, are permitted provided that the following conditions
21  * are met:
22  *
23  * 1. Redistributions of source code must retain the above copyright
24  *    notice, this list of conditions and the following disclaimer. 
25  *
26  * 2. Redistributions in binary form must reproduce the above copyright
27  *    notice, this list of conditions and the following disclaimer in
28  *    the documentation and/or other materials provided with the
29  *    distribution.
30  *
31  * 3. All advertising materials mentioning features or use of this
32  *    software must display the following acknowledgment:
33  *    "This product includes software developed by the OpenSSL Project
34  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
35  *
36  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
37  *    endorse or promote products derived from this software without
38  *    prior written permission. For written permission, please contact
39  *    openssl-core@openssl.org.
40  *
41  * 5. Products derived from this software may not be called "OpenSSL"
42  *    nor may "OpenSSL" appear in their names without prior written
43  *    permission of the OpenSSL Project.
44  *
45  * 6. Redistributions of any form whatsoever must retain the following
46  *    acknowledgment:
47  *    "This product includes software developed by the OpenSSL Project
48  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
49  *
50  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
51  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
54  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
56  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
59  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
61  * OF THE POSSIBILITY OF SUCH DAMAGE.
62  * ====================================================================
63  *
64  * This product includes cryptographic software written by Eric Young
65  * (eay@cryptsoft.com).  This product includes software written by Tim
66  * Hudson (tjh@cryptsoft.com).
67  *
68  */
69
70 #include <openssl/err.h>
71
72 #include "ec_lcl.h"
73
74
75 const EC_METHOD *EC_GF2m_simple_method(void)
76         {
77         static const EC_METHOD ret = {
78                 NID_X9_62_characteristic_two_field,
79                 ec_GF2m_simple_group_init,
80                 ec_GF2m_simple_group_finish,
81                 ec_GF2m_simple_group_clear_finish,
82                 ec_GF2m_simple_group_copy,
83                 ec_GF2m_simple_group_set_curve,
84                 ec_GF2m_simple_group_get_curve,
85                 ec_GF2m_simple_group_get_degree,
86                 ec_GF2m_simple_group_check_discriminant,
87                 ec_GF2m_simple_point_init,
88                 ec_GF2m_simple_point_finish,
89                 ec_GF2m_simple_point_clear_finish,
90                 ec_GF2m_simple_point_copy,
91                 ec_GF2m_simple_point_set_to_infinity,
92                 0 /* set_Jprojective_coordinates_GFp */,
93                 0 /* get_Jprojective_coordinates_GFp */,
94                 ec_GF2m_simple_point_set_affine_coordinates,
95                 ec_GF2m_simple_point_get_affine_coordinates,
96                 ec_GF2m_simple_set_compressed_coordinates,
97                 ec_GF2m_simple_point2oct,
98                 ec_GF2m_simple_oct2point,
99                 ec_GF2m_simple_add,
100                 ec_GF2m_simple_dbl,
101                 ec_GF2m_simple_invert,
102                 ec_GF2m_simple_is_at_infinity,
103                 ec_GF2m_simple_is_on_curve,
104                 ec_GF2m_simple_cmp,
105                 ec_GF2m_simple_make_affine,
106                 ec_GF2m_simple_points_make_affine,
107
108                 /* the following three method functions are defined in ec2_mult.c */
109                 ec_GF2m_simple_mul,
110                 ec_GF2m_precompute_mult,
111                 ec_GF2m_have_precompute_mult,
112
113                 ec_GF2m_simple_field_mul,
114                 ec_GF2m_simple_field_sqr,
115                 ec_GF2m_simple_field_div,
116                 0 /* field_encode */,
117                 0 /* field_decode */,
118                 0 /* field_set_to_one */ };
119
120         return &ret;
121         }
122
123
124 /* Initialize a GF(2^m)-based EC_GROUP structure.
125  * Note that all other members are handled by EC_GROUP_new.
126  */
127 int ec_GF2m_simple_group_init(EC_GROUP *group)
128         {
129         BN_init(&group->field);
130         BN_init(&group->a);
131         BN_init(&group->b);
132         return 1;
133         }
134
135
136 /* Free a GF(2^m)-based EC_GROUP structure.
137  * Note that all other members are handled by EC_GROUP_free.
138  */
139 void ec_GF2m_simple_group_finish(EC_GROUP *group)
140         {
141         BN_free(&group->field);
142         BN_free(&group->a);
143         BN_free(&group->b);
144         }
145
146
147 /* Clear and free a GF(2^m)-based EC_GROUP structure.
148  * Note that all other members are handled by EC_GROUP_clear_free.
149  */
150 void ec_GF2m_simple_group_clear_finish(EC_GROUP *group)
151         {
152         BN_clear_free(&group->field);
153         BN_clear_free(&group->a);
154         BN_clear_free(&group->b);
155         group->poly[0] = 0;
156         group->poly[1] = 0;
157         group->poly[2] = 0;
158         group->poly[3] = 0;
159         group->poly[4] = 0;
160         group->poly[5] = -1;
161         }
162
163
164 /* Copy a GF(2^m)-based EC_GROUP structure.
165  * Note that all other members are handled by EC_GROUP_copy.
166  */
167 int ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
168         {
169         int i;
170         if (!BN_copy(&dest->field, &src->field)) return 0;
171         if (!BN_copy(&dest->a, &src->a)) return 0;
172         if (!BN_copy(&dest->b, &src->b)) return 0;
173         dest->poly[0] = src->poly[0];
174         dest->poly[1] = src->poly[1];
175         dest->poly[2] = src->poly[2];
176         dest->poly[3] = src->poly[3];
177         dest->poly[4] = src->poly[4];
178         dest->poly[5] = src->poly[5];
179         if (bn_wexpand(&dest->a, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) return 0;
180         if (bn_wexpand(&dest->b, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) return 0;
181         for (i = dest->a.top; i < dest->a.dmax; i++) dest->a.d[i] = 0;
182         for (i = dest->b.top; i < dest->b.dmax; i++) dest->b.d[i] = 0;
183         return 1;
184         }
185
186
187 /* Set the curve parameters of an EC_GROUP structure. */
188 int ec_GF2m_simple_group_set_curve(EC_GROUP *group,
189         const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
190         {
191         int ret = 0, i;
192
193         /* group->field */
194         if (!BN_copy(&group->field, p)) goto err;
195         i = BN_GF2m_poly2arr(&group->field, group->poly, 6) - 1;
196         if ((i != 5) && (i != 3))
197                 {
198                 ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIELD);
199                 goto err;
200                 }
201
202         /* group->a */
203         if (!BN_GF2m_mod_arr(&group->a, a, group->poly)) goto err;
204         if(bn_wexpand(&group->a, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) goto err;
205         for (i = group->a.top; i < group->a.dmax; i++) group->a.d[i] = 0;
206         
207         /* group->b */
208         if (!BN_GF2m_mod_arr(&group->b, b, group->poly)) goto err;
209         if(bn_wexpand(&group->b, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) goto err;
210         for (i = group->b.top; i < group->b.dmax; i++) group->b.d[i] = 0;
211                 
212         ret = 1;
213   err:
214         return ret;
215         }
216
217
218 /* Get the curve parameters of an EC_GROUP structure.
219  * If p, a, or b are NULL then there values will not be set but the method will return with success.
220  */
221 int ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
222         {
223         int ret = 0;
224         
225         if (p != NULL)
226                 {
227                 if (!BN_copy(p, &group->field)) return 0;
228                 }
229
230         if (a != NULL)
231                 {
232                 if (!BN_copy(a, &group->a)) goto err;
233                 }
234
235         if (b != NULL)
236                 {
237                 if (!BN_copy(b, &group->b)) goto err;
238                 }
239         
240         ret = 1;
241         
242   err:
243         return ret;
244         }
245
246
247 /* Gets the degree of the field.  For a curve over GF(2^m) this is the value m. */
248 int ec_GF2m_simple_group_get_degree(const EC_GROUP *group)
249         {
250         return BN_num_bits(&group->field)-1;
251         }
252
253
254 /* Checks the discriminant of the curve.
255  * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p) 
256  */
257 int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
258         {
259         int ret = 0;
260         BIGNUM *b;
261         BN_CTX *new_ctx = NULL;
262
263         if (ctx == NULL)
264                 {
265                 ctx = new_ctx = BN_CTX_new();
266                 if (ctx == NULL)
267                         {
268                         ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT, ERR_R_MALLOC_FAILURE);
269                         goto err;
270                         }
271                 }
272         BN_CTX_start(ctx);
273         b = BN_CTX_get(ctx);
274         if (b == NULL) goto err;
275
276         if (!BN_GF2m_mod_arr(b, &group->b, group->poly)) goto err;
277         
278         /* check the discriminant:
279          * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p) 
280          */
281         if (BN_is_zero(b)) goto err;
282
283         ret = 1;
284
285 err:
286         if (ctx != NULL)
287                 BN_CTX_end(ctx);
288         if (new_ctx != NULL)
289                 BN_CTX_free(new_ctx);
290         return ret;
291         }
292
293
294 /* Initializes an EC_POINT. */
295 int ec_GF2m_simple_point_init(EC_POINT *point)
296         {
297         BN_init(&point->X);
298         BN_init(&point->Y);
299         BN_init(&point->Z);
300         return 1;
301         }
302
303
304 /* Frees an EC_POINT. */
305 void ec_GF2m_simple_point_finish(EC_POINT *point)
306         {
307         BN_free(&point->X);
308         BN_free(&point->Y);
309         BN_free(&point->Z);
310         }
311
312
313 /* Clears and frees an EC_POINT. */
314 void ec_GF2m_simple_point_clear_finish(EC_POINT *point)
315         {
316         BN_clear_free(&point->X);
317         BN_clear_free(&point->Y);
318         BN_clear_free(&point->Z);
319         point->Z_is_one = 0;
320         }
321
322
323 /* Copy the contents of one EC_POINT into another.  Assumes dest is initialized. */
324 int ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
325         {
326         if (!BN_copy(&dest->X, &src->X)) return 0;
327         if (!BN_copy(&dest->Y, &src->Y)) return 0;
328         if (!BN_copy(&dest->Z, &src->Z)) return 0;
329         dest->Z_is_one = src->Z_is_one;
330
331         return 1;
332         }
333
334
335 /* Set an EC_POINT to the point at infinity.  
336  * A point at infinity is represented by having Z=0.
337  */
338 int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
339         {
340         point->Z_is_one = 0;
341         BN_zero(&point->Z);
342         return 1;
343         }
344
345
346 /* Set the coordinates of an EC_POINT using affine coordinates. 
347  * Note that the simple implementation only uses affine coordinates.
348  */
349 int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
350         const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
351         {
352         int ret = 0;    
353         if (x == NULL || y == NULL)
354                 {
355                 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER);
356                 return 0;
357                 }
358
359         if (!BN_copy(&point->X, x)) goto err;
360         BN_set_negative(&point->X, 0);
361         if (!BN_copy(&point->Y, y)) goto err;
362         BN_set_negative(&point->Y, 0);
363         if (!BN_copy(&point->Z, BN_value_one())) goto err;
364         BN_set_negative(&point->Z, 0);
365         point->Z_is_one = 1;
366         ret = 1;
367
368   err:
369         return ret;
370         }
371
372
373 /* Gets the affine coordinates of an EC_POINT. 
374  * Note that the simple implementation only uses affine coordinates.
375  */
376 int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point,
377         BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
378         {
379         int ret = 0;
380
381         if (EC_POINT_is_at_infinity(group, point))
382                 {
383                 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY);
384                 return 0;
385                 }
386
387         if (BN_cmp(&point->Z, BN_value_one())) 
388                 {
389                 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
390                 return 0;
391                 }
392         if (x != NULL)
393                 {
394                 if (!BN_copy(x, &point->X)) goto err;
395                 BN_set_negative(x, 0);
396                 }
397         if (y != NULL)
398                 {
399                 if (!BN_copy(y, &point->Y)) goto err;
400                 BN_set_negative(y, 0);
401                 }
402         ret = 1;
403                 
404  err:
405         return ret;
406         }
407
408
409 /*-
410  * Calculates and sets the affine coordinates of an EC_POINT from the given
411  * compressed coordinates.  Uses algorithm 2.3.4 of SEC 1. 
412  * Note that the simple implementation only uses affine coordinates.
413  *
414  * The method is from the following publication:
415  * 
416  *     Harper, Menezes, Vanstone:
417  *     "Public-Key Cryptosystems with Very Small Key Lengths",
418  *     EUROCRYPT '92, Springer-Verlag LNCS 658,
419  *     published February 1993
420  *
421  * US Patents 6,141,420 and 6,618,483 (Vanstone, Mullin, Agnew) describe
422  * the same method, but claim no priority date earlier than July 29, 1994
423  * (and additionally fail to cite the EUROCRYPT '92 publication as prior art).
424  */
425 int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
426         const BIGNUM *x_, int y_bit, BN_CTX *ctx)
427         {
428         BN_CTX *new_ctx = NULL;
429         BIGNUM *tmp, *x, *y, *z;
430         int ret = 0, z0;
431
432         /* clear error queue */
433         ERR_clear_error();
434
435         if (ctx == NULL)
436                 {
437                 ctx = new_ctx = BN_CTX_new();
438                 if (ctx == NULL)
439                         return 0;
440                 }
441
442         y_bit = (y_bit != 0) ? 1 : 0;
443
444         BN_CTX_start(ctx);
445         tmp = BN_CTX_get(ctx);
446         x = BN_CTX_get(ctx);
447         y = BN_CTX_get(ctx);
448         z = BN_CTX_get(ctx);
449         if (z == NULL) goto err;
450
451         if (!BN_GF2m_mod_arr(x, x_, group->poly)) goto err;
452         if (BN_is_zero(x))
453                 {
454                 if (!BN_GF2m_mod_sqrt_arr(y, &group->b, group->poly, ctx)) goto err;
455                 }
456         else
457                 {
458                 if (!group->meth->field_sqr(group, tmp, x, ctx)) goto err;
459                 if (!group->meth->field_div(group, tmp, &group->b, tmp, ctx)) goto err;
460                 if (!BN_GF2m_add(tmp, &group->a, tmp)) goto err;
461                 if (!BN_GF2m_add(tmp, x, tmp)) goto err;
462                 if (!BN_GF2m_mod_solve_quad_arr(z, tmp, group->poly, ctx))
463                         {
464                         unsigned long err = ERR_peek_last_error();
465                         
466                         if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NO_SOLUTION)
467                                 {
468                                 ERR_clear_error();
469                                 ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
470                                 }
471                         else
472                                 ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
473                         goto err;
474                         }
475                 z0 = (BN_is_odd(z)) ? 1 : 0;
476                 if (!group->meth->field_mul(group, y, x, z, ctx)) goto err;
477                 if (z0 != y_bit)
478                         {
479                         if (!BN_GF2m_add(y, y, x)) goto err;
480                         }
481                 }
482
483         if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
484
485         ret = 1;
486
487  err:
488         BN_CTX_end(ctx);
489         if (new_ctx != NULL)
490                 BN_CTX_free(new_ctx);
491         return ret;
492         }
493
494
495 /* Converts an EC_POINT to an octet string.  
496  * If buf is NULL, the encoded length will be returned.
497  * If the length len of buf is smaller than required an error will be returned.
498  */
499 size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
500         unsigned char *buf, size_t len, BN_CTX *ctx)
501         {
502         size_t ret;
503         BN_CTX *new_ctx = NULL;
504         int used_ctx = 0;
505         BIGNUM *x, *y, *yxi;
506         size_t field_len, i, skip;
507
508         if ((form != POINT_CONVERSION_COMPRESSED)
509                 && (form != POINT_CONVERSION_UNCOMPRESSED)
510                 && (form != POINT_CONVERSION_HYBRID))
511                 {
512                 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
513                 goto err;
514                 }
515
516         if (EC_POINT_is_at_infinity(group, point))
517                 {
518                 /* encodes to a single 0 octet */
519                 if (buf != NULL)
520                         {
521                         if (len < 1)
522                                 {
523                                 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
524                                 return 0;
525                                 }
526                         buf[0] = 0;
527                         }
528                 return 1;
529                 }
530
531
532         /* ret := required output buffer length */
533         field_len = (EC_GROUP_get_degree(group) + 7) / 8;
534         ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
535
536         /* if 'buf' is NULL, just return required length */
537         if (buf != NULL)
538                 {
539                 if (len < ret)
540                         {
541                         ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
542                         goto err;
543                         }
544
545                 if (ctx == NULL)
546                         {
547                         ctx = new_ctx = BN_CTX_new();
548                         if (ctx == NULL)
549                                 return 0;
550                         }
551
552                 BN_CTX_start(ctx);
553                 used_ctx = 1;
554                 x = BN_CTX_get(ctx);
555                 y = BN_CTX_get(ctx);
556                 yxi = BN_CTX_get(ctx);
557                 if (yxi == NULL) goto err;
558
559                 if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
560
561                 buf[0] = form;
562                 if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x))
563                         {
564                         if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
565                         if (BN_is_odd(yxi)) buf[0]++;
566                         }
567
568                 i = 1;
569                 
570                 skip = field_len - BN_num_bytes(x);
571                 if (skip > field_len)
572                         {
573                         ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
574                         goto err;
575                         }
576                 while (skip > 0)
577                         {
578                         buf[i++] = 0;
579                         skip--;
580                         }
581                 skip = BN_bn2bin(x, buf + i);
582                 i += skip;
583                 if (i != 1 + field_len)
584                         {
585                         ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
586                         goto err;
587                         }
588
589                 if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
590                         {
591                         skip = field_len - BN_num_bytes(y);
592                         if (skip > field_len)
593                                 {
594                                 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
595                                 goto err;
596                                 }
597                         while (skip > 0)
598                                 {
599                                 buf[i++] = 0;
600                                 skip--;
601                                 }
602                         skip = BN_bn2bin(y, buf + i);
603                         i += skip;
604                         }
605
606                 if (i != ret)
607                         {
608                         ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
609                         goto err;
610                         }
611                 }
612         
613         if (used_ctx)
614                 BN_CTX_end(ctx);
615         if (new_ctx != NULL)
616                 BN_CTX_free(new_ctx);
617         return ret;
618
619  err:
620         if (used_ctx)
621                 BN_CTX_end(ctx);
622         if (new_ctx != NULL)
623                 BN_CTX_free(new_ctx);
624         return 0;
625         }
626
627
628 /* Converts an octet string representation to an EC_POINT. 
629  * Note that the simple implementation only uses affine coordinates.
630  */
631 int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
632         const unsigned char *buf, size_t len, BN_CTX *ctx)
633         {
634         point_conversion_form_t form;
635         int y_bit;
636         BN_CTX *new_ctx = NULL;
637         BIGNUM *x, *y, *yxi;
638         size_t field_len, enc_len;
639         int ret = 0;
640
641         if (len == 0)
642                 {
643                 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
644                 return 0;
645                 }
646         form = buf[0];
647         y_bit = form & 1;
648         form = form & ~1U;
649         if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
650                 && (form != POINT_CONVERSION_UNCOMPRESSED)
651                 && (form != POINT_CONVERSION_HYBRID))
652                 {
653                 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
654                 return 0;
655                 }
656         if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
657                 {
658                 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
659                 return 0;
660                 }
661
662         if (form == 0)
663                 {
664                 if (len != 1)
665                         {
666                         ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
667                         return 0;
668                         }
669
670                 return EC_POINT_set_to_infinity(group, point);
671                 }
672         
673         field_len = (EC_GROUP_get_degree(group) + 7) / 8;
674         enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
675
676         if (len != enc_len)
677                 {
678                 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
679                 return 0;
680                 }
681
682         if (ctx == NULL)
683                 {
684                 ctx = new_ctx = BN_CTX_new();
685                 if (ctx == NULL)
686                         return 0;
687                 }
688
689         BN_CTX_start(ctx);
690         x = BN_CTX_get(ctx);
691         y = BN_CTX_get(ctx);
692         yxi = BN_CTX_get(ctx);
693         if (yxi == NULL) goto err;
694
695         if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
696         if (BN_ucmp(x, &group->field) >= 0)
697                 {
698                 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
699                 goto err;
700                 }
701
702         if (form == POINT_CONVERSION_COMPRESSED)
703                 {
704                 if (!EC_POINT_set_compressed_coordinates_GF2m(group, point, x, y_bit, ctx)) goto err;
705                 }
706         else
707                 {
708                 if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
709                 if (BN_ucmp(y, &group->field) >= 0)
710                         {
711                         ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
712                         goto err;
713                         }
714                 if (form == POINT_CONVERSION_HYBRID)
715                         {
716                         if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
717                         if (y_bit != BN_is_odd(yxi))
718                                 {
719                                 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
720                                 goto err;
721                                 }
722                         }
723
724                 if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
725                 }
726         
727         if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
728                 {
729                 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
730                 goto err;
731                 }
732
733         ret = 1;
734         
735  err:
736         BN_CTX_end(ctx);
737         if (new_ctx != NULL)
738                 BN_CTX_free(new_ctx);
739         return ret;
740         }
741
742
743 /* Computes a + b and stores the result in r.  r could be a or b, a could be b.
744  * Uses algorithm A.10.2 of IEEE P1363.
745  */
746 int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
747         {
748         BN_CTX *new_ctx = NULL;
749         BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t;
750         int ret = 0;
751         
752         if (EC_POINT_is_at_infinity(group, a))
753                 {
754                 if (!EC_POINT_copy(r, b)) return 0;
755                 return 1;
756                 }
757
758         if (EC_POINT_is_at_infinity(group, b))
759                 {
760                 if (!EC_POINT_copy(r, a)) return 0;
761                 return 1;
762                 }
763
764         if (ctx == NULL)
765                 {
766                 ctx = new_ctx = BN_CTX_new();
767                 if (ctx == NULL)
768                         return 0;
769                 }
770
771         BN_CTX_start(ctx);
772         x0 = BN_CTX_get(ctx);
773         y0 = BN_CTX_get(ctx);
774         x1 = BN_CTX_get(ctx);
775         y1 = BN_CTX_get(ctx);
776         x2 = BN_CTX_get(ctx);
777         y2 = BN_CTX_get(ctx);
778         s = BN_CTX_get(ctx);
779         t = BN_CTX_get(ctx);
780         if (t == NULL) goto err;
781
782         if (a->Z_is_one) 
783                 {
784                 if (!BN_copy(x0, &a->X)) goto err;
785                 if (!BN_copy(y0, &a->Y)) goto err;
786                 }
787         else
788                 {
789                 if (!EC_POINT_get_affine_coordinates_GF2m(group, a, x0, y0, ctx)) goto err;
790                 }
791         if (b->Z_is_one) 
792                 {
793                 if (!BN_copy(x1, &b->X)) goto err;
794                 if (!BN_copy(y1, &b->Y)) goto err;
795                 }
796         else
797                 {
798                 if (!EC_POINT_get_affine_coordinates_GF2m(group, b, x1, y1, ctx)) goto err;
799                 }
800
801
802         if (BN_GF2m_cmp(x0, x1))
803                 {
804                 if (!BN_GF2m_add(t, x0, x1)) goto err;
805                 if (!BN_GF2m_add(s, y0, y1)) goto err;
806                 if (!group->meth->field_div(group, s, s, t, ctx)) goto err;
807                 if (!group->meth->field_sqr(group, x2, s, ctx)) goto err;
808                 if (!BN_GF2m_add(x2, x2, &group->a)) goto err;
809                 if (!BN_GF2m_add(x2, x2, s)) goto err;
810                 if (!BN_GF2m_add(x2, x2, t)) goto err;
811                 }
812         else
813                 {
814                 if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1))
815                         {
816                         if (!EC_POINT_set_to_infinity(group, r)) goto err;
817                         ret = 1;
818                         goto err;
819                         }
820                 if (!group->meth->field_div(group, s, y1, x1, ctx)) goto err;
821                 if (!BN_GF2m_add(s, s, x1)) goto err;
822                 
823                 if (!group->meth->field_sqr(group, x2, s, ctx)) goto err;
824                 if (!BN_GF2m_add(x2, x2, s)) goto err;
825                 if (!BN_GF2m_add(x2, x2, &group->a)) goto err;
826                 }
827
828         if (!BN_GF2m_add(y2, x1, x2)) goto err;
829         if (!group->meth->field_mul(group, y2, y2, s, ctx)) goto err;
830         if (!BN_GF2m_add(y2, y2, x2)) goto err;
831         if (!BN_GF2m_add(y2, y2, y1)) goto err;
832
833         if (!EC_POINT_set_affine_coordinates_GF2m(group, r, x2, y2, ctx)) goto err;
834
835         ret = 1;
836
837  err:
838         BN_CTX_end(ctx);
839         if (new_ctx != NULL)
840                 BN_CTX_free(new_ctx);
841         return ret;
842         }
843
844
845 /* Computes 2 * a and stores the result in r.  r could be a.
846  * Uses algorithm A.10.2 of IEEE P1363.
847  */
848 int ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
849         {
850         return ec_GF2m_simple_add(group, r, a, a, ctx);
851         }
852
853
854 int ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
855         {
856         if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y))
857                 /* point is its own inverse */
858                 return 1;
859         
860         if (!EC_POINT_make_affine(group, point, ctx)) return 0;
861         return BN_GF2m_add(&point->Y, &point->X, &point->Y);
862         }
863
864
865 /* Indicates whether the given point is the point at infinity. */
866 int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
867         {
868         return BN_is_zero(&point->Z);
869         }
870
871
872 /*-
873  * Determines whether the given EC_POINT is an actual point on the curve defined
874  * in the EC_GROUP.  A point is valid if it satisfies the Weierstrass equation:
875  *      y^2 + x*y = x^3 + a*x^2 + b.
876  */
877 int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
878         {
879         int ret = -1;
880         BN_CTX *new_ctx = NULL;
881         BIGNUM *lh, *y2;
882         int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
883         int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
884
885         if (EC_POINT_is_at_infinity(group, point))
886                 return 1;
887
888         field_mul = group->meth->field_mul;
889         field_sqr = group->meth->field_sqr;     
890
891         /* only support affine coordinates */
892         if (!point->Z_is_one) return -1;
893
894         if (ctx == NULL)
895                 {
896                 ctx = new_ctx = BN_CTX_new();
897                 if (ctx == NULL)
898                         return -1;
899                 }
900
901         BN_CTX_start(ctx);
902         y2 = BN_CTX_get(ctx);
903         lh = BN_CTX_get(ctx);
904         if (lh == NULL) goto err;
905
906         /*-
907          * We have a curve defined by a Weierstrass equation
908          *      y^2 + x*y = x^3 + a*x^2 + b.
909          *  <=> x^3 + a*x^2 + x*y + b + y^2 = 0
910          *  <=> ((x + a) * x + y ) * x + b + y^2 = 0
911          */
912         if (!BN_GF2m_add(lh, &point->X, &group->a)) goto err;
913         if (!field_mul(group, lh, lh, &point->X, ctx)) goto err;
914         if (!BN_GF2m_add(lh, lh, &point->Y)) goto err;
915         if (!field_mul(group, lh, lh, &point->X, ctx)) goto err;
916         if (!BN_GF2m_add(lh, lh, &group->b)) goto err;
917         if (!field_sqr(group, y2, &point->Y, ctx)) goto err;
918         if (!BN_GF2m_add(lh, lh, y2)) goto err;
919         ret = BN_is_zero(lh);
920  err:
921         if (ctx) BN_CTX_end(ctx);
922         if (new_ctx) BN_CTX_free(new_ctx);
923         return ret;
924         }
925
926
927 /*-
928  * Indicates whether two points are equal.
929  * Return values:
930  *  -1   error
931  *   0   equal (in affine coordinates)
932  *   1   not equal
933  */
934 int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
935         {
936         BIGNUM *aX, *aY, *bX, *bY;
937         BN_CTX *new_ctx = NULL;
938         int ret = -1;
939
940         if (EC_POINT_is_at_infinity(group, a))
941                 {
942                 return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
943                 }
944
945         if (EC_POINT_is_at_infinity(group, b))
946                 return 1;
947         
948         if (a->Z_is_one && b->Z_is_one)
949                 {
950                 return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
951                 }
952
953         if (ctx == NULL)
954                 {
955                 ctx = new_ctx = BN_CTX_new();
956                 if (ctx == NULL)
957                         return -1;
958                 }
959
960         BN_CTX_start(ctx);
961         aX = BN_CTX_get(ctx);
962         aY = BN_CTX_get(ctx);
963         bX = BN_CTX_get(ctx);
964         bY = BN_CTX_get(ctx);
965         if (bY == NULL) goto err;
966
967         if (!EC_POINT_get_affine_coordinates_GF2m(group, a, aX, aY, ctx)) goto err;
968         if (!EC_POINT_get_affine_coordinates_GF2m(group, b, bX, bY, ctx)) goto err;
969         ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1;
970
971   err:  
972         if (ctx) BN_CTX_end(ctx);
973         if (new_ctx) BN_CTX_free(new_ctx);
974         return ret;
975         }
976
977
978 /* Forces the given EC_POINT to internally use affine coordinates. */
979 int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
980         {
981         BN_CTX *new_ctx = NULL;
982         BIGNUM *x, *y;
983         int ret = 0;
984
985         if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
986                 return 1;
987         
988         if (ctx == NULL)
989                 {
990                 ctx = new_ctx = BN_CTX_new();
991                 if (ctx == NULL)
992                         return 0;
993                 }
994
995         BN_CTX_start(ctx);
996         x = BN_CTX_get(ctx);
997         y = BN_CTX_get(ctx);
998         if (y == NULL) goto err;
999         
1000         if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
1001         if (!BN_copy(&point->X, x)) goto err;
1002         if (!BN_copy(&point->Y, y)) goto err;
1003         if (!BN_one(&point->Z)) goto err;
1004         
1005         ret = 1;                
1006
1007   err:
1008         if (ctx) BN_CTX_end(ctx);
1009         if (new_ctx) BN_CTX_free(new_ctx);
1010         return ret;
1011         }
1012
1013
1014 /* Forces each of the EC_POINTs in the given array to use affine coordinates. */
1015 int ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
1016         {
1017         size_t i;
1018
1019         for (i = 0; i < num; i++)
1020                 {
1021                 if (!group->meth->make_affine(group, points[i], ctx)) return 0;
1022                 }
1023
1024         return 1;
1025         }
1026
1027
1028 /* Wrapper to simple binary polynomial field multiplication implementation. */
1029 int ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
1030         {
1031         return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx);
1032         }
1033
1034
1035 /* Wrapper to simple binary polynomial field squaring implementation. */
1036 int ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
1037         {
1038         return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx);
1039         }
1040
1041
1042 /* Wrapper to simple binary polynomial field division implementation. */
1043 int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
1044         {
1045         return BN_GF2m_mod_div(r, a, b, &group->field, ctx);
1046         }