Add additional parameter to dsa_builtin_paramgen to output the generated
[oweals/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         if (BN_num_bits(x) > BN_num_bits(&group->field))
367                 ret = 2;
368         else if (BN_num_bits(y) > BN_num_bits(&group->field))
369                 ret = 2;
370         else
371                 ret = 1;
372
373   err:
374         return ret;
375         }
376
377
378 /* Gets the affine coordinates of an EC_POINT. 
379  * Note that the simple implementation only uses affine coordinates.
380  */
381 int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point,
382         BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
383         {
384         int ret = 0;
385
386         if (EC_POINT_is_at_infinity(group, point))
387                 {
388                 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY);
389                 return 0;
390                 }
391
392         if (BN_cmp(&point->Z, BN_value_one())) 
393                 {
394                 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
395                 return 0;
396                 }
397         if (x != NULL)
398                 {
399                 if (!BN_copy(x, &point->X)) goto err;
400                 BN_set_negative(x, 0);
401                 }
402         if (y != NULL)
403                 {
404                 if (!BN_copy(y, &point->Y)) goto err;
405                 BN_set_negative(y, 0);
406                 }
407         ret = 1;
408                 
409  err:
410         return ret;
411         }
412
413
414 /* Calculates and sets the affine coordinates of an EC_POINT from the given
415  * compressed coordinates.  Uses algorithm 2.3.4 of SEC 1. 
416  * Note that the simple implementation only uses affine coordinates.
417  *
418  * The method is from the following publication:
419  * 
420  *     Harper, Menezes, Vanstone:
421  *     "Public-Key Cryptosystems with Very Small Key Lengths",
422  *     EUROCRYPT '92, Springer-Verlag LNCS 658,
423  *     published February 1993
424  *
425  * US Patents 6,141,420 and 6,618,483 (Vanstone, Mullin, Agnew) describe
426  * the same method, but claim no priority date earlier than July 29, 1994
427  * (and additionally fail to cite the EUROCRYPT '92 publication as prior art).
428  */
429 int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
430         const BIGNUM *x_, int y_bit, BN_CTX *ctx)
431         {
432         BN_CTX *new_ctx = NULL;
433         BIGNUM *tmp, *x, *y, *z;
434         int ret = 0, z0;
435
436         /* clear error queue */
437         ERR_clear_error();
438
439         if (ctx == NULL)
440                 {
441                 ctx = new_ctx = BN_CTX_new();
442                 if (ctx == NULL)
443                         return 0;
444                 }
445
446         y_bit = (y_bit != 0) ? 1 : 0;
447
448         BN_CTX_start(ctx);
449         tmp = BN_CTX_get(ctx);
450         x = BN_CTX_get(ctx);
451         y = BN_CTX_get(ctx);
452         z = BN_CTX_get(ctx);
453         if (z == NULL) goto err;
454
455         if (!BN_GF2m_mod_arr(x, x_, group->poly)) goto err;
456         if (BN_is_zero(x))
457                 {
458                 if (!BN_GF2m_mod_sqrt_arr(y, &group->b, group->poly, ctx)) goto err;
459                 }
460         else
461                 {
462                 if (!group->meth->field_sqr(group, tmp, x, ctx)) goto err;
463                 if (!group->meth->field_div(group, tmp, &group->b, tmp, ctx)) goto err;
464                 if (!BN_GF2m_add(tmp, &group->a, tmp)) goto err;
465                 if (!BN_GF2m_add(tmp, x, tmp)) goto err;
466                 if (!BN_GF2m_mod_solve_quad_arr(z, tmp, group->poly, ctx))
467                         {
468                         unsigned long err = ERR_peek_last_error();
469                         
470                         if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NO_SOLUTION)
471                                 {
472                                 ERR_clear_error();
473                                 ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
474                                 }
475                         else
476                                 ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
477                         goto err;
478                         }
479                 z0 = (BN_is_odd(z)) ? 1 : 0;
480                 if (!group->meth->field_mul(group, y, x, z, ctx)) goto err;
481                 if (z0 != y_bit)
482                         {
483                         if (!BN_GF2m_add(y, y, x)) goto err;
484                         }
485                 }
486
487         if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
488
489         ret = 1;
490
491  err:
492         BN_CTX_end(ctx);
493         if (new_ctx != NULL)
494                 BN_CTX_free(new_ctx);
495         return ret;
496         }
497
498
499 /* Converts an EC_POINT to an octet string.  
500  * If buf is NULL, the encoded length will be returned.
501  * If the length len of buf is smaller than required an error will be returned.
502  */
503 size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
504         unsigned char *buf, size_t len, BN_CTX *ctx)
505         {
506         size_t ret;
507         BN_CTX *new_ctx = NULL;
508         int used_ctx = 0;
509         BIGNUM *x, *y, *yxi;
510         size_t field_len, i, skip;
511
512         if ((form != POINT_CONVERSION_COMPRESSED)
513                 && (form != POINT_CONVERSION_UNCOMPRESSED)
514                 && (form != POINT_CONVERSION_HYBRID))
515                 {
516                 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
517                 goto err;
518                 }
519
520         if (EC_POINT_is_at_infinity(group, point))
521                 {
522                 /* encodes to a single 0 octet */
523                 if (buf != NULL)
524                         {
525                         if (len < 1)
526                                 {
527                                 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
528                                 return 0;
529                                 }
530                         buf[0] = 0;
531                         }
532                 return 1;
533                 }
534
535
536         /* ret := required output buffer length */
537         field_len = (EC_GROUP_get_degree(group) + 7) / 8;
538         ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
539
540         /* if 'buf' is NULL, just return required length */
541         if (buf != NULL)
542                 {
543                 if (len < ret)
544                         {
545                         ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
546                         goto err;
547                         }
548
549                 if (ctx == NULL)
550                         {
551                         ctx = new_ctx = BN_CTX_new();
552                         if (ctx == NULL)
553                                 return 0;
554                         }
555
556                 BN_CTX_start(ctx);
557                 used_ctx = 1;
558                 x = BN_CTX_get(ctx);
559                 y = BN_CTX_get(ctx);
560                 yxi = BN_CTX_get(ctx);
561                 if (yxi == NULL) goto err;
562
563                 if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
564
565                 buf[0] = form;
566                 if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x))
567                         {
568                         if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
569                         if (BN_is_odd(yxi)) buf[0]++;
570                         }
571
572                 i = 1;
573                 
574                 skip = field_len - BN_num_bytes(x);
575                 if (skip > field_len)
576                         {
577                         ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
578                         goto err;
579                         }
580                 while (skip > 0)
581                         {
582                         buf[i++] = 0;
583                         skip--;
584                         }
585                 skip = BN_bn2bin(x, buf + i);
586                 i += skip;
587                 if (i != 1 + field_len)
588                         {
589                         ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
590                         goto err;
591                         }
592
593                 if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
594                         {
595                         skip = field_len - BN_num_bytes(y);
596                         if (skip > field_len)
597                                 {
598                                 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
599                                 goto err;
600                                 }
601                         while (skip > 0)
602                                 {
603                                 buf[i++] = 0;
604                                 skip--;
605                                 }
606                         skip = BN_bn2bin(y, buf + i);
607                         i += skip;
608                         }
609
610                 if (i != ret)
611                         {
612                         ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
613                         goto err;
614                         }
615                 }
616         
617         if (used_ctx)
618                 BN_CTX_end(ctx);
619         if (new_ctx != NULL)
620                 BN_CTX_free(new_ctx);
621         return ret;
622
623  err:
624         if (used_ctx)
625                 BN_CTX_end(ctx);
626         if (new_ctx != NULL)
627                 BN_CTX_free(new_ctx);
628         return 0;
629         }
630
631
632 /* Converts an octet string representation to an EC_POINT. 
633  * Note that the simple implementation only uses affine coordinates.
634  */
635 int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
636         const unsigned char *buf, size_t len, BN_CTX *ctx)
637         {
638         point_conversion_form_t form;
639         int y_bit;
640         BN_CTX *new_ctx = NULL;
641         BIGNUM *x, *y, *yxi;
642         size_t field_len, enc_len;
643         int ret = 0;
644
645         if (len == 0)
646                 {
647                 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
648                 return 0;
649                 }
650         form = buf[0];
651         y_bit = form & 1;
652         form = form & ~1U;
653         if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
654                 && (form != POINT_CONVERSION_UNCOMPRESSED)
655                 && (form != POINT_CONVERSION_HYBRID))
656                 {
657                 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
658                 return 0;
659                 }
660         if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
661                 {
662                 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
663                 return 0;
664                 }
665
666         if (form == 0)
667                 {
668                 if (len != 1)
669                         {
670                         ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
671                         return 0;
672                         }
673
674                 return EC_POINT_set_to_infinity(group, point);
675                 }
676         
677         field_len = (EC_GROUP_get_degree(group) + 7) / 8;
678         enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
679
680         if (len != enc_len)
681                 {
682                 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
683                 return 0;
684                 }
685
686         if (ctx == NULL)
687                 {
688                 ctx = new_ctx = BN_CTX_new();
689                 if (ctx == NULL)
690                         return 0;
691                 }
692
693         BN_CTX_start(ctx);
694         x = BN_CTX_get(ctx);
695         y = BN_CTX_get(ctx);
696         yxi = BN_CTX_get(ctx);
697         if (yxi == NULL) goto err;
698
699         if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
700         if (BN_ucmp(x, &group->field) >= 0)
701                 {
702                 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
703                 goto err;
704                 }
705
706         if (form == POINT_CONVERSION_COMPRESSED)
707                 {
708                 if (!EC_POINT_set_compressed_coordinates_GF2m(group, point, x, y_bit, ctx)) goto err;
709                 }
710         else
711                 {
712                 if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
713                 if (BN_ucmp(y, &group->field) >= 0)
714                         {
715                         ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
716                         goto err;
717                         }
718                 if (form == POINT_CONVERSION_HYBRID)
719                         {
720                         if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
721                         if (y_bit != BN_is_odd(yxi))
722                                 {
723                                 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
724                                 goto err;
725                                 }
726                         }
727
728                 if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
729                 }
730         
731         if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
732                 {
733                 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
734                 goto err;
735                 }
736
737         ret = 1;
738         
739  err:
740         BN_CTX_end(ctx);
741         if (new_ctx != NULL)
742                 BN_CTX_free(new_ctx);
743         return ret;
744         }
745
746
747 /* Computes a + b and stores the result in r.  r could be a or b, a could be b.
748  * Uses algorithm A.10.2 of IEEE P1363.
749  */
750 int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
751         {
752         BN_CTX *new_ctx = NULL;
753         BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t;
754         int ret = 0;
755         
756         if (EC_POINT_is_at_infinity(group, a))
757                 {
758                 if (!EC_POINT_copy(r, b)) return 0;
759                 return 1;
760                 }
761
762         if (EC_POINT_is_at_infinity(group, b))
763                 {
764                 if (!EC_POINT_copy(r, a)) return 0;
765                 return 1;
766                 }
767
768         if (ctx == NULL)
769                 {
770                 ctx = new_ctx = BN_CTX_new();
771                 if (ctx == NULL)
772                         return 0;
773                 }
774
775         BN_CTX_start(ctx);
776         x0 = BN_CTX_get(ctx);
777         y0 = BN_CTX_get(ctx);
778         x1 = BN_CTX_get(ctx);
779         y1 = BN_CTX_get(ctx);
780         x2 = BN_CTX_get(ctx);
781         y2 = BN_CTX_get(ctx);
782         s = BN_CTX_get(ctx);
783         t = BN_CTX_get(ctx);
784         if (t == NULL) goto err;
785
786         if (a->Z_is_one) 
787                 {
788                 if (!BN_copy(x0, &a->X)) goto err;
789                 if (!BN_copy(y0, &a->Y)) goto err;
790                 }
791         else
792                 {
793                 if (!EC_POINT_get_affine_coordinates_GF2m(group, a, x0, y0, ctx)) goto err;
794                 }
795         if (b->Z_is_one) 
796                 {
797                 if (!BN_copy(x1, &b->X)) goto err;
798                 if (!BN_copy(y1, &b->Y)) goto err;
799                 }
800         else
801                 {
802                 if (!EC_POINT_get_affine_coordinates_GF2m(group, b, x1, y1, ctx)) goto err;
803                 }
804
805
806         if (BN_GF2m_cmp(x0, x1))
807                 {
808                 if (!BN_GF2m_add(t, x0, x1)) goto err;
809                 if (!BN_GF2m_add(s, y0, y1)) goto err;
810                 if (!group->meth->field_div(group, s, s, t, ctx)) goto err;
811                 if (!group->meth->field_sqr(group, x2, s, ctx)) goto err;
812                 if (!BN_GF2m_add(x2, x2, &group->a)) goto err;
813                 if (!BN_GF2m_add(x2, x2, s)) goto err;
814                 if (!BN_GF2m_add(x2, x2, t)) goto err;
815                 }
816         else
817                 {
818                 if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1))
819                         {
820                         if (!EC_POINT_set_to_infinity(group, r)) goto err;
821                         ret = 1;
822                         goto err;
823                         }
824                 if (!group->meth->field_div(group, s, y1, x1, ctx)) goto err;
825                 if (!BN_GF2m_add(s, s, x1)) goto err;
826                 
827                 if (!group->meth->field_sqr(group, x2, s, ctx)) goto err;
828                 if (!BN_GF2m_add(x2, x2, s)) goto err;
829                 if (!BN_GF2m_add(x2, x2, &group->a)) goto err;
830                 }
831
832         if (!BN_GF2m_add(y2, x1, x2)) goto err;
833         if (!group->meth->field_mul(group, y2, y2, s, ctx)) goto err;
834         if (!BN_GF2m_add(y2, y2, x2)) goto err;
835         if (!BN_GF2m_add(y2, y2, y1)) goto err;
836
837         if (!EC_POINT_set_affine_coordinates_GF2m(group, r, x2, y2, ctx)) goto err;
838
839         ret = 1;
840
841  err:
842         BN_CTX_end(ctx);
843         if (new_ctx != NULL)
844                 BN_CTX_free(new_ctx);
845         return ret;
846         }
847
848
849 /* Computes 2 * a and stores the result in r.  r could be a.
850  * Uses algorithm A.10.2 of IEEE P1363.
851  */
852 int ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
853         {
854         return ec_GF2m_simple_add(group, r, a, a, ctx);
855         }
856
857
858 int ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
859         {
860         if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y))
861                 /* point is its own inverse */
862                 return 1;
863         
864         if (!EC_POINT_make_affine(group, point, ctx)) return 0;
865         return BN_GF2m_add(&point->Y, &point->X, &point->Y);
866         }
867
868
869 /* Indicates whether the given point is the point at infinity. */
870 int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
871         {
872         return BN_is_zero(&point->Z);
873         }
874
875
876 /* Determines whether the given EC_POINT is an actual point on the curve defined
877  * in the EC_GROUP.  A point is valid if it satisfies the Weierstrass equation:
878  *      y^2 + x*y = x^3 + a*x^2 + b.
879  */
880 int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
881         {
882         int ret = -1;
883         BN_CTX *new_ctx = NULL;
884         BIGNUM *lh, *y2;
885         int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
886         int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
887
888         if (EC_POINT_is_at_infinity(group, point))
889                 return 1;
890
891         field_mul = group->meth->field_mul;
892         field_sqr = group->meth->field_sqr;     
893
894         /* only support affine coordinates */
895         if (!point->Z_is_one) goto err;
896
897         if (ctx == NULL)
898                 {
899                 ctx = new_ctx = BN_CTX_new();
900                 if (ctx == NULL)
901                         return -1;
902                 }
903
904         BN_CTX_start(ctx);
905         y2 = BN_CTX_get(ctx);
906         lh = BN_CTX_get(ctx);
907         if (lh == NULL) goto err;
908
909         /* We have a curve defined by a Weierstrass equation
910          *      y^2 + x*y = x^3 + a*x^2 + b.
911          *  <=> x^3 + a*x^2 + x*y + b + y^2 = 0
912          *  <=> ((x + a) * x + y ) * x + b + y^2 = 0
913          */
914         if (!BN_GF2m_add(lh, &point->X, &group->a)) goto err;
915         if (!field_mul(group, lh, lh, &point->X, ctx)) goto err;
916         if (!BN_GF2m_add(lh, lh, &point->Y)) goto err;
917         if (!field_mul(group, lh, lh, &point->X, ctx)) goto err;
918         if (!BN_GF2m_add(lh, lh, &group->b)) goto err;
919         if (!field_sqr(group, y2, &point->Y, ctx)) goto err;
920         if (!BN_GF2m_add(lh, lh, y2)) goto err;
921         ret = BN_is_zero(lh);
922  err:
923         if (ctx) BN_CTX_end(ctx);
924         if (new_ctx) BN_CTX_free(new_ctx);
925         return ret;
926         }
927
928
929 /* Indicates whether two points are equal.
930  * Return values:
931  *  -1   error
932  *   0   equal (in affine coordinates)
933  *   1   not equal
934  */
935 int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
936         {
937         BIGNUM *aX, *aY, *bX, *bY;
938         BN_CTX *new_ctx = NULL;
939         int ret = -1;
940
941         if (EC_POINT_is_at_infinity(group, a))
942                 {
943                 return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
944                 }
945
946         if (EC_POINT_is_at_infinity(group, b))
947                 return 1;
948         
949         if (a->Z_is_one && b->Z_is_one)
950                 {
951                 return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
952                 }
953
954         if (ctx == NULL)
955                 {
956                 ctx = new_ctx = BN_CTX_new();
957                 if (ctx == NULL)
958                         return -1;
959                 }
960
961         BN_CTX_start(ctx);
962         aX = BN_CTX_get(ctx);
963         aY = BN_CTX_get(ctx);
964         bX = BN_CTX_get(ctx);
965         bY = BN_CTX_get(ctx);
966         if (bY == NULL) goto err;
967
968         if (!EC_POINT_get_affine_coordinates_GF2m(group, a, aX, aY, ctx)) goto err;
969         if (!EC_POINT_get_affine_coordinates_GF2m(group, b, bX, bY, ctx)) goto err;
970         ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1;
971
972   err:  
973         if (ctx) BN_CTX_end(ctx);
974         if (new_ctx) BN_CTX_free(new_ctx);
975         return ret;
976         }
977
978 int ec_GF2m_simple_range(const EC_GROUP *group, const EC_POINT *a)
979         {
980         if (BN_num_bits(&a->X) > BN_num_bits(&group->field))
981                 return 0;
982         if (BN_num_bits(&a->Y) > BN_num_bits(&group->field))
983                 return 0;
984         return 1;
985         }
986
987
988 /* Forces the given EC_POINT to internally use affine coordinates. */
989 int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
990         {
991         BN_CTX *new_ctx = NULL;
992         BIGNUM *x, *y;
993         int ret = 0;
994
995         if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
996                 return 1;
997         
998         if (ctx == NULL)
999                 {
1000                 ctx = new_ctx = BN_CTX_new();
1001                 if (ctx == NULL)
1002                         return 0;
1003                 }
1004
1005         BN_CTX_start(ctx);
1006         x = BN_CTX_get(ctx);
1007         y = BN_CTX_get(ctx);
1008         if (y == NULL) goto err;
1009         
1010         if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
1011         if (!BN_copy(&point->X, x)) goto err;
1012         if (!BN_copy(&point->Y, y)) goto err;
1013         if (!BN_one(&point->Z)) goto err;
1014         
1015         ret = 1;                
1016
1017   err:
1018         if (ctx) BN_CTX_end(ctx);
1019         if (new_ctx) BN_CTX_free(new_ctx);
1020         return ret;
1021         }
1022
1023
1024 /* Forces each of the EC_POINTs in the given array to use affine coordinates. */
1025 int ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
1026         {
1027         size_t i;
1028
1029         for (i = 0; i < num; i++)
1030                 {
1031                 if (!group->meth->make_affine(group, points[i], ctx)) return 0;
1032                 }
1033
1034         return 1;
1035         }
1036
1037
1038 /* Wrapper to simple binary polynomial field multiplication implementation. */
1039 int ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
1040         {
1041         return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx);
1042         }
1043
1044
1045 /* Wrapper to simple binary polynomial field squaring implementation. */
1046 int ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
1047         {
1048         return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx);
1049         }
1050
1051
1052 /* Wrapper to simple binary polynomial field division implementation. */
1053 int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
1054         {
1055         return BN_GF2m_mod_div(r, a, b, &group->field, ctx);
1056         }