Coverage Report

Created: 2022-11-30 06:20

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