Coverage Report

Created: 2023-06-08 06:41

/src/openssl111/crypto/ec/ec2_smpl.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved.
3
 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
4
 *
5
 * Licensed under the OpenSSL license (the "License").  You may not use
6
 * this file except in compliance with the License.  You can obtain a copy
7
 * in the file LICENSE in the source distribution or at
8
 * https://www.openssl.org/source/license.html
9
 */
10
11
#include <openssl/err.h>
12
13
#include "crypto/bn.h"
14
#include "ec_local.h"
15
16
#ifndef OPENSSL_NO_EC2M
17
18
/*
19
 * Initialize a GF(2^m)-based EC_GROUP structure. Note that all other members
20
 * are handled by EC_GROUP_new.
21
 */
22
int ec_GF2m_simple_group_init(EC_GROUP *group)
23
30.3k
{
24
30.3k
    group->field = BN_new();
25
30.3k
    group->a = BN_new();
26
30.3k
    group->b = BN_new();
27
28
30.3k
    if (group->field == NULL || group->a == NULL || group->b == NULL) {
29
0
        BN_free(group->field);
30
0
        BN_free(group->a);
31
0
        BN_free(group->b);
32
0
        return 0;
33
0
    }
34
30.3k
    return 1;
35
30.3k
}
36
37
/*
38
 * Free a GF(2^m)-based EC_GROUP structure. Note that all other members are
39
 * handled by EC_GROUP_free.
40
 */
41
void ec_GF2m_simple_group_finish(EC_GROUP *group)
42
30.3k
{
43
30.3k
    BN_free(group->field);
44
30.3k
    BN_free(group->a);
45
30.3k
    BN_free(group->b);
46
30.3k
}
47
48
/*
49
 * Clear and free a GF(2^m)-based EC_GROUP structure. Note that all other
50
 * members are handled by EC_GROUP_clear_free.
51
 */
52
void ec_GF2m_simple_group_clear_finish(EC_GROUP *group)
53
0
{
54
0
    BN_clear_free(group->field);
55
0
    BN_clear_free(group->a);
56
0
    BN_clear_free(group->b);
57
0
    group->poly[0] = 0;
58
0
    group->poly[1] = 0;
59
0
    group->poly[2] = 0;
60
0
    group->poly[3] = 0;
61
0
    group->poly[4] = 0;
62
0
    group->poly[5] = -1;
63
0
}
64
65
/*
66
 * Copy a GF(2^m)-based EC_GROUP structure. Note that all other members are
67
 * handled by EC_GROUP_copy.
68
 */
69
int ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
70
15.1k
{
71
15.1k
    if (!BN_copy(dest->field, src->field))
72
0
        return 0;
73
15.1k
    if (!BN_copy(dest->a, src->a))
74
0
        return 0;
75
15.1k
    if (!BN_copy(dest->b, src->b))
76
0
        return 0;
77
15.1k
    dest->poly[0] = src->poly[0];
78
15.1k
    dest->poly[1] = src->poly[1];
79
15.1k
    dest->poly[2] = src->poly[2];
80
15.1k
    dest->poly[3] = src->poly[3];
81
15.1k
    dest->poly[4] = src->poly[4];
82
15.1k
    dest->poly[5] = src->poly[5];
83
15.1k
    if (bn_wexpand(dest->a, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) ==
84
15.1k
        NULL)
85
0
        return 0;
86
15.1k
    if (bn_wexpand(dest->b, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) ==
87
15.1k
        NULL)
88
0
        return 0;
89
15.1k
    bn_set_all_zero(dest->a);
90
15.1k
    bn_set_all_zero(dest->b);
91
15.1k
    return 1;
92
15.1k
}
93
94
/* Set the curve parameters of an EC_GROUP structure. */
95
int ec_GF2m_simple_group_set_curve(EC_GROUP *group,
96
                                   const BIGNUM *p, const BIGNUM *a,
97
                                   const BIGNUM *b, BN_CTX *ctx)
98
15.1k
{
99
15.1k
    int ret = 0, i;
100
101
    /* group->field */
102
15.1k
    if (!BN_copy(group->field, p))
103
0
        goto err;
104
15.1k
    i = BN_GF2m_poly2arr(group->field, group->poly, 6) - 1;
105
15.1k
    if ((i != 5) && (i != 3)) {
106
0
        ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIELD);
107
0
        goto err;
108
0
    }
109
110
    /* group->a */
111
15.1k
    if (!BN_GF2m_mod_arr(group->a, a, group->poly))
112
0
        goto err;
113
15.1k
    if (bn_wexpand(group->a, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2)
114
15.1k
        == NULL)
115
0
        goto err;
116
15.1k
    bn_set_all_zero(group->a);
117
118
    /* group->b */
119
15.1k
    if (!BN_GF2m_mod_arr(group->b, b, group->poly))
120
0
        goto err;
121
15.1k
    if (bn_wexpand(group->b, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2)
122
15.1k
        == NULL)
123
0
        goto err;
124
15.1k
    bn_set_all_zero(group->b);
125
126
15.1k
    ret = 1;
127
15.1k
 err:
128
15.1k
    return ret;
129
15.1k
}
130
131
/*
132
 * Get the curve parameters of an EC_GROUP structure. If p, a, or b are NULL
133
 * then there values will not be set but the method will return with success.
134
 */
135
int ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p,
136
                                   BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
137
0
{
138
0
    int ret = 0;
139
140
0
    if (p != NULL) {
141
0
        if (!BN_copy(p, group->field))
142
0
            return 0;
143
0
    }
144
145
0
    if (a != NULL) {
146
0
        if (!BN_copy(a, group->a))
147
0
            goto err;
148
0
    }
149
150
0
    if (b != NULL) {
151
0
        if (!BN_copy(b, group->b))
152
0
            goto err;
153
0
    }
154
155
0
    ret = 1;
156
157
0
 err:
158
0
    return ret;
159
0
}
160
161
/*
162
 * Gets the degree of the field.  For a curve over GF(2^m) this is the value
163
 * m.
164
 */
165
int ec_GF2m_simple_group_get_degree(const EC_GROUP *group)
166
13.9k
{
167
13.9k
    return BN_num_bits(group->field) - 1;
168
13.9k
}
169
170
/*
171
 * Checks the discriminant of the curve. y^2 + x*y = x^3 + a*x^2 + b is an
172
 * elliptic curve <=> b != 0 (mod p)
173
 */
174
int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group,
175
                                            BN_CTX *ctx)
176
0
{
177
0
    int ret = 0;
178
0
    BIGNUM *b;
179
0
    BN_CTX *new_ctx = NULL;
180
181
0
    if (ctx == NULL) {
182
0
        ctx = new_ctx = BN_CTX_new();
183
0
        if (ctx == NULL) {
184
0
            ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT,
185
0
                  ERR_R_MALLOC_FAILURE);
186
0
            goto err;
187
0
        }
188
0
    }
189
0
    BN_CTX_start(ctx);
190
0
    b = BN_CTX_get(ctx);
191
0
    if (b == NULL)
192
0
        goto err;
193
194
0
    if (!BN_GF2m_mod_arr(b, group->b, group->poly))
195
0
        goto err;
196
197
    /*
198
     * check the discriminant: y^2 + x*y = x^3 + a*x^2 + b is an elliptic
199
     * curve <=> b != 0 (mod p)
200
     */
201
0
    if (BN_is_zero(b))
202
0
        goto err;
203
204
0
    ret = 1;
205
206
0
 err:
207
0
    BN_CTX_end(ctx);
208
0
    BN_CTX_free(new_ctx);
209
0
    return ret;
210
0
}
211
212
/* Initializes an EC_POINT. */
213
int ec_GF2m_simple_point_init(EC_POINT *point)
214
60.7k
{
215
60.7k
    point->X = BN_new();
216
60.7k
    point->Y = BN_new();
217
60.7k
    point->Z = BN_new();
218
219
60.7k
    if (point->X == NULL || point->Y == NULL || point->Z == NULL) {
220
0
        BN_free(point->X);
221
0
        BN_free(point->Y);
222
0
        BN_free(point->Z);
223
0
        return 0;
224
0
    }
225
60.7k
    return 1;
226
60.7k
}
227
228
/* Frees an EC_POINT. */
229
void ec_GF2m_simple_point_finish(EC_POINT *point)
230
60.7k
{
231
60.7k
    BN_free(point->X);
232
60.7k
    BN_free(point->Y);
233
60.7k
    BN_free(point->Z);
234
60.7k
}
235
236
/* Clears and frees an EC_POINT. */
237
void ec_GF2m_simple_point_clear_finish(EC_POINT *point)
238
0
{
239
0
    BN_clear_free(point->X);
240
0
    BN_clear_free(point->Y);
241
0
    BN_clear_free(point->Z);
242
0
    point->Z_is_one = 0;
243
0
}
244
245
/*
246
 * Copy the contents of one EC_POINT into another.  Assumes dest is
247
 * initialized.
248
 */
249
int ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
250
30.3k
{
251
30.3k
    if (!BN_copy(dest->X, src->X))
252
0
        return 0;
253
30.3k
    if (!BN_copy(dest->Y, src->Y))
254
0
        return 0;
255
30.3k
    if (!BN_copy(dest->Z, src->Z))
256
0
        return 0;
257
30.3k
    dest->Z_is_one = src->Z_is_one;
258
30.3k
    dest->curve_name = src->curve_name;
259
260
30.3k
    return 1;
261
30.3k
}
262
263
/*
264
 * Set an EC_POINT to the point at infinity. A point at infinity is
265
 * represented by having Z=0.
266
 */
267
int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group,
268
                                         EC_POINT *point)
269
135
{
270
135
    point->Z_is_one = 0;
271
135
    BN_zero(point->Z);
272
135
    return 1;
273
135
}
274
275
/*
276
 * Set the coordinates of an EC_POINT using affine coordinates. Note that
277
 * the simple implementation only uses affine coordinates.
278
 */
279
int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group,
280
                                                EC_POINT *point,
281
                                                const BIGNUM *x,
282
                                                const BIGNUM *y, BN_CTX *ctx)
283
22.7k
{
284
22.7k
    int ret = 0;
285
22.7k
    if (x == NULL || y == NULL) {
286
0
        ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES,
287
0
              ERR_R_PASSED_NULL_PARAMETER);
288
0
        return 0;
289
0
    }
290
291
22.7k
    if (!BN_copy(point->X, x))
292
0
        goto err;
293
22.7k
    BN_set_negative(point->X, 0);
294
22.7k
    if (!BN_copy(point->Y, y))
295
0
        goto err;
296
22.7k
    BN_set_negative(point->Y, 0);
297
22.7k
    if (!BN_copy(point->Z, BN_value_one()))
298
0
        goto err;
299
22.7k
    BN_set_negative(point->Z, 0);
300
22.7k
    point->Z_is_one = 1;
301
22.7k
    ret = 1;
302
303
22.7k
 err:
304
22.7k
    return ret;
305
22.7k
}
306
307
/*
308
 * Gets the affine coordinates of an EC_POINT. Note that the simple
309
 * implementation only uses affine coordinates.
310
 */
311
int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group,
312
                                                const EC_POINT *point,
313
                                                BIGNUM *x, BIGNUM *y,
314
                                                BN_CTX *ctx)
315
0
{
316
0
    int ret = 0;
317
318
0
    if (EC_POINT_is_at_infinity(group, point)) {
319
0
        ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES,
320
0
              EC_R_POINT_AT_INFINITY);
321
0
        return 0;
322
0
    }
323
324
0
    if (BN_cmp(point->Z, BN_value_one())) {
325
0
        ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES,
326
0
              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
327
0
        return 0;
328
0
    }
329
0
    if (x != NULL) {
330
0
        if (!BN_copy(x, point->X))
331
0
            goto err;
332
0
        BN_set_negative(x, 0);
333
0
    }
334
0
    if (y != NULL) {
335
0
        if (!BN_copy(y, point->Y))
336
0
            goto err;
337
0
        BN_set_negative(y, 0);
338
0
    }
339
0
    ret = 1;
340
341
0
 err:
342
0
    return ret;
343
0
}
344
345
/*
346
 * Computes a + b and stores the result in r.  r could be a or b, a could be
347
 * b. Uses algorithm A.10.2 of IEEE P1363.
348
 */
349
int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
350
                       const EC_POINT *b, BN_CTX *ctx)
351
0
{
352
0
    BN_CTX *new_ctx = NULL;
353
0
    BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t;
354
0
    int ret = 0;
355
356
0
    if (EC_POINT_is_at_infinity(group, a)) {
357
0
        if (!EC_POINT_copy(r, b))
358
0
            return 0;
359
0
        return 1;
360
0
    }
361
362
0
    if (EC_POINT_is_at_infinity(group, b)) {
363
0
        if (!EC_POINT_copy(r, a))
364
0
            return 0;
365
0
        return 1;
366
0
    }
367
368
0
    if (ctx == NULL) {
369
0
        ctx = new_ctx = BN_CTX_new();
370
0
        if (ctx == NULL)
371
0
            return 0;
372
0
    }
373
374
0
    BN_CTX_start(ctx);
375
0
    x0 = BN_CTX_get(ctx);
376
0
    y0 = BN_CTX_get(ctx);
377
0
    x1 = BN_CTX_get(ctx);
378
0
    y1 = BN_CTX_get(ctx);
379
0
    x2 = BN_CTX_get(ctx);
380
0
    y2 = BN_CTX_get(ctx);
381
0
    s = BN_CTX_get(ctx);
382
0
    t = BN_CTX_get(ctx);
383
0
    if (t == NULL)
384
0
        goto err;
385
386
0
    if (a->Z_is_one) {
387
0
        if (!BN_copy(x0, a->X))
388
0
            goto err;
389
0
        if (!BN_copy(y0, a->Y))
390
0
            goto err;
391
0
    } else {
392
0
        if (!EC_POINT_get_affine_coordinates(group, a, x0, y0, ctx))
393
0
            goto err;
394
0
    }
395
0
    if (b->Z_is_one) {
396
0
        if (!BN_copy(x1, b->X))
397
0
            goto err;
398
0
        if (!BN_copy(y1, b->Y))
399
0
            goto err;
400
0
    } else {
401
0
        if (!EC_POINT_get_affine_coordinates(group, b, x1, y1, ctx))
402
0
            goto err;
403
0
    }
404
405
0
    if (BN_GF2m_cmp(x0, x1)) {
406
0
        if (!BN_GF2m_add(t, x0, x1))
407
0
            goto err;
408
0
        if (!BN_GF2m_add(s, y0, y1))
409
0
            goto err;
410
0
        if (!group->meth->field_div(group, s, s, t, ctx))
411
0
            goto err;
412
0
        if (!group->meth->field_sqr(group, x2, s, ctx))
413
0
            goto err;
414
0
        if (!BN_GF2m_add(x2, x2, group->a))
415
0
            goto err;
416
0
        if (!BN_GF2m_add(x2, x2, s))
417
0
            goto err;
418
0
        if (!BN_GF2m_add(x2, x2, t))
419
0
            goto err;
420
0
    } else {
421
0
        if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1)) {
422
0
            if (!EC_POINT_set_to_infinity(group, r))
423
0
                goto err;
424
0
            ret = 1;
425
0
            goto err;
426
0
        }
427
0
        if (!group->meth->field_div(group, s, y1, x1, ctx))
428
0
            goto err;
429
0
        if (!BN_GF2m_add(s, s, x1))
430
0
            goto err;
431
432
0
        if (!group->meth->field_sqr(group, x2, s, ctx))
433
0
            goto err;
434
0
        if (!BN_GF2m_add(x2, x2, s))
435
0
            goto err;
436
0
        if (!BN_GF2m_add(x2, x2, group->a))
437
0
            goto err;
438
0
    }
439
440
0
    if (!BN_GF2m_add(y2, x1, x2))
441
0
        goto err;
442
0
    if (!group->meth->field_mul(group, y2, y2, s, ctx))
443
0
        goto err;
444
0
    if (!BN_GF2m_add(y2, y2, x2))
445
0
        goto err;
446
0
    if (!BN_GF2m_add(y2, y2, y1))
447
0
        goto err;
448
449
0
    if (!EC_POINT_set_affine_coordinates(group, r, x2, y2, ctx))
450
0
        goto err;
451
452
0
    ret = 1;
453
454
0
 err:
455
0
    BN_CTX_end(ctx);
456
0
    BN_CTX_free(new_ctx);
457
0
    return ret;
458
0
}
459
460
/*
461
 * Computes 2 * a and stores the result in r.  r could be a. Uses algorithm
462
 * A.10.2 of IEEE P1363.
463
 */
464
int ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
465
                       BN_CTX *ctx)
466
0
{
467
0
    return ec_GF2m_simple_add(group, r, a, a, ctx);
468
0
}
469
470
int ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
471
0
{
472
0
    if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(point->Y))
473
        /* point is its own inverse */
474
0
        return 1;
475
476
0
    if (!EC_POINT_make_affine(group, point, ctx))
477
0
        return 0;
478
0
    return BN_GF2m_add(point->Y, point->X, point->Y);
479
0
}
480
481
/* Indicates whether the given point is the point at infinity. */
482
int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group,
483
                                  const EC_POINT *point)
484
22.7k
{
485
22.7k
    return BN_is_zero(point->Z);
486
22.7k
}
487
488
/*-
489
 * Determines whether the given EC_POINT is an actual point on the curve defined
490
 * in the EC_GROUP.  A point is valid if it satisfies the Weierstrass equation:
491
 *      y^2 + x*y = x^3 + a*x^2 + b.
492
 */
493
int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
494
                               BN_CTX *ctx)
495
22.7k
{
496
22.7k
    int ret = -1;
497
22.7k
    BN_CTX *new_ctx = NULL;
498
22.7k
    BIGNUM *lh, *y2;
499
22.7k
    int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,
500
22.7k
                      const BIGNUM *, BN_CTX *);
501
22.7k
    int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
502
503
22.7k
    if (EC_POINT_is_at_infinity(group, point))
504
0
        return 1;
505
506
22.7k
    field_mul = group->meth->field_mul;
507
22.7k
    field_sqr = group->meth->field_sqr;
508
509
    /* only support affine coordinates */
510
22.7k
    if (!point->Z_is_one)
511
0
        return -1;
512
513
22.7k
    if (ctx == NULL) {
514
0
        ctx = new_ctx = BN_CTX_new();
515
0
        if (ctx == NULL)
516
0
            return -1;
517
0
    }
518
519
22.7k
    BN_CTX_start(ctx);
520
22.7k
    y2 = BN_CTX_get(ctx);
521
22.7k
    lh = BN_CTX_get(ctx);
522
22.7k
    if (lh == NULL)
523
0
        goto err;
524
525
    /*-
526
     * We have a curve defined by a Weierstrass equation
527
     *      y^2 + x*y = x^3 + a*x^2 + b.
528
     *  <=> x^3 + a*x^2 + x*y + b + y^2 = 0
529
     *  <=> ((x + a) * x + y ) * x + b + y^2 = 0
530
     */
531
22.7k
    if (!BN_GF2m_add(lh, point->X, group->a))
532
0
        goto err;
533
22.7k
    if (!field_mul(group, lh, lh, point->X, ctx))
534
0
        goto err;
535
22.7k
    if (!BN_GF2m_add(lh, lh, point->Y))
536
0
        goto err;
537
22.7k
    if (!field_mul(group, lh, lh, point->X, ctx))
538
0
        goto err;
539
22.7k
    if (!BN_GF2m_add(lh, lh, group->b))
540
0
        goto err;
541
22.7k
    if (!field_sqr(group, y2, point->Y, ctx))
542
0
        goto err;
543
22.7k
    if (!BN_GF2m_add(lh, lh, y2))
544
0
        goto err;
545
22.7k
    ret = BN_is_zero(lh);
546
547
22.7k
 err:
548
22.7k
    BN_CTX_end(ctx);
549
22.7k
    BN_CTX_free(new_ctx);
550
22.7k
    return ret;
551
22.7k
}
552
553
/*-
554
 * Indicates whether two points are equal.
555
 * Return values:
556
 *  -1   error
557
 *   0   equal (in affine coordinates)
558
 *   1   not equal
559
 */
560
int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
561
                       const EC_POINT *b, BN_CTX *ctx)
562
0
{
563
0
    BIGNUM *aX, *aY, *bX, *bY;
564
0
    BN_CTX *new_ctx = NULL;
565
0
    int ret = -1;
566
567
0
    if (EC_POINT_is_at_infinity(group, a)) {
568
0
        return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
569
0
    }
570
571
0
    if (EC_POINT_is_at_infinity(group, b))
572
0
        return 1;
573
574
0
    if (a->Z_is_one && b->Z_is_one) {
575
0
        return ((BN_cmp(a->X, b->X) == 0) && BN_cmp(a->Y, b->Y) == 0) ? 0 : 1;
576
0
    }
577
578
0
    if (ctx == NULL) {
579
0
        ctx = new_ctx = BN_CTX_new();
580
0
        if (ctx == NULL)
581
0
            return -1;
582
0
    }
583
584
0
    BN_CTX_start(ctx);
585
0
    aX = BN_CTX_get(ctx);
586
0
    aY = BN_CTX_get(ctx);
587
0
    bX = BN_CTX_get(ctx);
588
0
    bY = BN_CTX_get(ctx);
589
0
    if (bY == NULL)
590
0
        goto err;
591
592
0
    if (!EC_POINT_get_affine_coordinates(group, a, aX, aY, ctx))
593
0
        goto err;
594
0
    if (!EC_POINT_get_affine_coordinates(group, b, bX, bY, ctx))
595
0
        goto err;
596
0
    ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1;
597
598
0
 err:
599
0
    BN_CTX_end(ctx);
600
0
    BN_CTX_free(new_ctx);
601
0
    return ret;
602
0
}
603
604
/* Forces the given EC_POINT to internally use affine coordinates. */
605
int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
606
                               BN_CTX *ctx)
607
0
{
608
0
    BN_CTX *new_ctx = NULL;
609
0
    BIGNUM *x, *y;
610
0
    int ret = 0;
611
612
0
    if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
613
0
        return 1;
614
615
0
    if (ctx == NULL) {
616
0
        ctx = new_ctx = BN_CTX_new();
617
0
        if (ctx == NULL)
618
0
            return 0;
619
0
    }
620
621
0
    BN_CTX_start(ctx);
622
0
    x = BN_CTX_get(ctx);
623
0
    y = BN_CTX_get(ctx);
624
0
    if (y == NULL)
625
0
        goto err;
626
627
0
    if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx))
628
0
        goto err;
629
0
    if (!BN_copy(point->X, x))
630
0
        goto err;
631
0
    if (!BN_copy(point->Y, y))
632
0
        goto err;
633
0
    if (!BN_one(point->Z))
634
0
        goto err;
635
0
    point->Z_is_one = 1;
636
637
0
    ret = 1;
638
639
0
 err:
640
0
    BN_CTX_end(ctx);
641
0
    BN_CTX_free(new_ctx);
642
0
    return ret;
643
0
}
644
645
/*
646
 * Forces each of the EC_POINTs in the given array to use affine coordinates.
647
 */
648
int ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num,
649
                                      EC_POINT *points[], BN_CTX *ctx)
650
0
{
651
0
    size_t i;
652
653
0
    for (i = 0; i < num; i++) {
654
0
        if (!group->meth->make_affine(group, points[i], ctx))
655
0
            return 0;
656
0
    }
657
658
0
    return 1;
659
0
}
660
661
/* Wrapper to simple binary polynomial field multiplication implementation. */
662
int ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r,
663
                             const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
664
50.3k
{
665
50.3k
    return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx);
666
50.3k
}
667
668
/* Wrapper to simple binary polynomial field squaring implementation. */
669
int ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r,
670
                             const BIGNUM *a, BN_CTX *ctx)
671
30.3k
{
672
30.3k
    return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx);
673
30.3k
}
674
675
/* Wrapper to simple binary polynomial field division implementation. */
676
int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r,
677
                             const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
678
11.3k
{
679
11.3k
    return BN_GF2m_mod_div(r, a, b, group->field, ctx);
680
11.3k
}
681
682
/*-
683
 * Lopez-Dahab ladder, pre step.
684
 * See e.g. "Guide to ECC" Alg 3.40.
685
 * Modified to blind s and r independently.
686
 * s:= p, r := 2p
687
 */
688
static
689
int ec_GF2m_simple_ladder_pre(const EC_GROUP *group,
690
                              EC_POINT *r, EC_POINT *s,
691
                              EC_POINT *p, BN_CTX *ctx)
692
0
{
693
    /* if p is not affine, something is wrong */
694
0
    if (p->Z_is_one == 0)
695
0
        return 0;
696
697
    /* s blinding: make sure lambda (s->Z here) is not zero */
698
0
    do {
699
0
        if (!BN_priv_rand(s->Z, BN_num_bits(group->field) - 1,
700
0
                          BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) {
701
0
            ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_PRE, ERR_R_BN_LIB);
702
0
            return 0;
703
0
        }
704
0
    } while (BN_is_zero(s->Z));
705
706
    /* if field_encode defined convert between representations */
707
0
    if ((group->meth->field_encode != NULL
708
0
         && !group->meth->field_encode(group, s->Z, s->Z, ctx))
709
0
        || !group->meth->field_mul(group, s->X, p->X, s->Z, ctx))
710
0
        return 0;
711
712
    /* r blinding: make sure lambda (r->Y here for storage) is not zero */
713
0
    do {
714
0
        if (!BN_priv_rand(r->Y, BN_num_bits(group->field) - 1,
715
0
                          BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) {
716
0
            ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_PRE, ERR_R_BN_LIB);
717
0
            return 0;
718
0
        }
719
0
    } while (BN_is_zero(r->Y));
720
721
0
    if ((group->meth->field_encode != NULL
722
0
         && !group->meth->field_encode(group, r->Y, r->Y, ctx))
723
0
        || !group->meth->field_sqr(group, r->Z, p->X, ctx)
724
0
        || !group->meth->field_sqr(group, r->X, r->Z, ctx)
725
0
        || !BN_GF2m_add(r->X, r->X, group->b)
726
0
        || !group->meth->field_mul(group, r->Z, r->Z, r->Y, ctx)
727
0
        || !group->meth->field_mul(group, r->X, r->X, r->Y, ctx))
728
0
        return 0;
729
730
0
    s->Z_is_one = 0;
731
0
    r->Z_is_one = 0;
732
733
0
    return 1;
734
0
}
735
736
/*-
737
 * Ladder step: differential addition-and-doubling, mixed Lopez-Dahab coords.
738
 * http://www.hyperelliptic.org/EFD/g12o/auto-code/shortw/xz/ladder/mladd-2003-s.op3
739
 * s := r + s, r := 2r
740
 */
741
static
742
int ec_GF2m_simple_ladder_step(const EC_GROUP *group,
743
                               EC_POINT *r, EC_POINT *s,
744
                               EC_POINT *p, BN_CTX *ctx)
745
0
{
746
0
    if (!group->meth->field_mul(group, r->Y, r->Z, s->X, ctx)
747
0
        || !group->meth->field_mul(group, s->X, r->X, s->Z, ctx)
748
0
        || !group->meth->field_sqr(group, s->Y, r->Z, ctx)
749
0
        || !group->meth->field_sqr(group, r->Z, r->X, ctx)
750
0
        || !BN_GF2m_add(s->Z, r->Y, s->X)
751
0
        || !group->meth->field_sqr(group, s->Z, s->Z, ctx)
752
0
        || !group->meth->field_mul(group, s->X, r->Y, s->X, ctx)
753
0
        || !group->meth->field_mul(group, r->Y, s->Z, p->X, ctx)
754
0
        || !BN_GF2m_add(s->X, s->X, r->Y)
755
0
        || !group->meth->field_sqr(group, r->Y, r->Z, ctx)
756
0
        || !group->meth->field_mul(group, r->Z, r->Z, s->Y, ctx)
757
0
        || !group->meth->field_sqr(group, s->Y, s->Y, ctx)
758
0
        || !group->meth->field_mul(group, s->Y, s->Y, group->b, ctx)
759
0
        || !BN_GF2m_add(r->X, r->Y, s->Y))
760
0
        return 0;
761
762
0
    return 1;
763
0
}
764
765
/*-
766
 * Recover affine (x,y) result from Lopez-Dahab r and s, affine p.
767
 * See e.g. "Fast Multiplication on Elliptic Curves over GF(2**m)
768
 * without Precomputation" (Lopez and Dahab, CHES 1999),
769
 * Appendix Alg Mxy.
770
 */
771
static
772
int ec_GF2m_simple_ladder_post(const EC_GROUP *group,
773
                               EC_POINT *r, EC_POINT *s,
774
                               EC_POINT *p, BN_CTX *ctx)
775
0
{
776
0
    int ret = 0;
777
0
    BIGNUM *t0, *t1, *t2 = NULL;
778
779
0
    if (BN_is_zero(r->Z))
780
0
        return EC_POINT_set_to_infinity(group, r);
781
782
0
    if (BN_is_zero(s->Z)) {
783
0
        if (!EC_POINT_copy(r, p)
784
0
            || !EC_POINT_invert(group, r, ctx)) {
785
0
            ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_POST, ERR_R_EC_LIB);
786
0
            return 0;
787
0
        }
788
0
        return 1;
789
0
    }
790
791
0
    BN_CTX_start(ctx);
792
0
    t0 = BN_CTX_get(ctx);
793
0
    t1 = BN_CTX_get(ctx);
794
0
    t2 = BN_CTX_get(ctx);
795
0
    if (t2 == NULL) {
796
0
        ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_POST, ERR_R_MALLOC_FAILURE);
797
0
        goto err;
798
0
    }
799
800
0
    if (!group->meth->field_mul(group, t0, r->Z, s->Z, ctx)
801
0
        || !group->meth->field_mul(group, t1, p->X, r->Z, ctx)
802
0
        || !BN_GF2m_add(t1, r->X, t1)
803
0
        || !group->meth->field_mul(group, t2, p->X, s->Z, ctx)
804
0
        || !group->meth->field_mul(group, r->Z, r->X, t2, ctx)
805
0
        || !BN_GF2m_add(t2, t2, s->X)
806
0
        || !group->meth->field_mul(group, t1, t1, t2, ctx)
807
0
        || !group->meth->field_sqr(group, t2, p->X, ctx)
808
0
        || !BN_GF2m_add(t2, p->Y, t2)
809
0
        || !group->meth->field_mul(group, t2, t2, t0, ctx)
810
0
        || !BN_GF2m_add(t1, t2, t1)
811
0
        || !group->meth->field_mul(group, t2, p->X, t0, ctx)
812
0
        || !group->meth->field_inv(group, t2, t2, ctx)
813
0
        || !group->meth->field_mul(group, t1, t1, t2, ctx)
814
0
        || !group->meth->field_mul(group, r->X, r->Z, t2, ctx)
815
0
        || !BN_GF2m_add(t2, p->X, r->X)
816
0
        || !group->meth->field_mul(group, t2, t2, t1, ctx)
817
0
        || !BN_GF2m_add(r->Y, p->Y, t2)
818
0
        || !BN_one(r->Z))
819
0
        goto err;
820
821
0
    r->Z_is_one = 1;
822
823
    /* GF(2^m) field elements should always have BIGNUM::neg = 0 */
824
0
    BN_set_negative(r->X, 0);
825
0
    BN_set_negative(r->Y, 0);
826
827
0
    ret = 1;
828
829
0
 err:
830
0
    BN_CTX_end(ctx);
831
0
    return ret;
832
0
}
833
834
static
835
int ec_GF2m_simple_points_mul(const EC_GROUP *group, EC_POINT *r,
836
                              const BIGNUM *scalar, size_t num,
837
                              const EC_POINT *points[],
838
                              const BIGNUM *scalars[],
839
                              BN_CTX *ctx)
840
0
{
841
0
    int ret = 0;
842
0
    EC_POINT *t = NULL;
843
844
    /*-
845
     * We limit use of the ladder only to the following cases:
846
     * - r := scalar * G
847
     *   Fixed point mul: scalar != NULL && num == 0;
848
     * - r := scalars[0] * points[0]
849
     *   Variable point mul: scalar == NULL && num == 1;
850
     * - r := scalar * G + scalars[0] * points[0]
851
     *   used, e.g., in ECDSA verification: scalar != NULL && num == 1
852
     *
853
     * In any other case (num > 1) we use the default wNAF implementation.
854
     *
855
     * We also let the default implementation handle degenerate cases like group
856
     * order or cofactor set to 0.
857
     */
858
0
    if (num > 1 || BN_is_zero(group->order) || BN_is_zero(group->cofactor))
859
0
        return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
860
861
0
    if (scalar != NULL && num == 0)
862
        /* Fixed point multiplication */
863
0
        return ec_scalar_mul_ladder(group, r, scalar, NULL, ctx);
864
865
0
    if (scalar == NULL && num == 1)
866
        /* Variable point multiplication */
867
0
        return ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx);
868
869
    /*-
870
     * Double point multiplication:
871
     *  r := scalar * G + scalars[0] * points[0]
872
     */
873
874
0
    if ((t = EC_POINT_new(group)) == NULL) {
875
0
        ECerr(EC_F_EC_GF2M_SIMPLE_POINTS_MUL, ERR_R_MALLOC_FAILURE);
876
0
        return 0;
877
0
    }
878
879
0
    if (!ec_scalar_mul_ladder(group, t, scalar, NULL, ctx)
880
0
        || !ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx)
881
0
        || !EC_POINT_add(group, r, t, r, ctx))
882
0
        goto err;
883
884
0
    ret = 1;
885
886
0
 err:
887
0
    EC_POINT_free(t);
888
0
    return ret;
889
0
}
890
891
/*-
892
 * Computes the multiplicative inverse of a in GF(2^m), storing the result in r.
893
 * If a is zero (or equivalent), you'll get a EC_R_CANNOT_INVERT error.
894
 * SCA hardening is with blinding: BN_GF2m_mod_inv does that.
895
 */
896
static int ec_GF2m_simple_field_inv(const EC_GROUP *group, BIGNUM *r,
897
                                    const BIGNUM *a, BN_CTX *ctx)
898
0
{
899
0
    int ret;
900
901
0
    if (!(ret = BN_GF2m_mod_inv(r, a, group->field, ctx)))
902
0
        ECerr(EC_F_EC_GF2M_SIMPLE_FIELD_INV, EC_R_CANNOT_INVERT);
903
0
    return ret;
904
0
}
905
906
const EC_METHOD *EC_GF2m_simple_method(void)
907
15.1k
{
908
15.1k
    static const EC_METHOD ret = {
909
15.1k
        EC_FLAGS_DEFAULT_OCT,
910
15.1k
        NID_X9_62_characteristic_two_field,
911
15.1k
        ec_GF2m_simple_group_init,
912
15.1k
        ec_GF2m_simple_group_finish,
913
15.1k
        ec_GF2m_simple_group_clear_finish,
914
15.1k
        ec_GF2m_simple_group_copy,
915
15.1k
        ec_GF2m_simple_group_set_curve,
916
15.1k
        ec_GF2m_simple_group_get_curve,
917
15.1k
        ec_GF2m_simple_group_get_degree,
918
15.1k
        ec_group_simple_order_bits,
919
15.1k
        ec_GF2m_simple_group_check_discriminant,
920
15.1k
        ec_GF2m_simple_point_init,
921
15.1k
        ec_GF2m_simple_point_finish,
922
15.1k
        ec_GF2m_simple_point_clear_finish,
923
15.1k
        ec_GF2m_simple_point_copy,
924
15.1k
        ec_GF2m_simple_point_set_to_infinity,
925
15.1k
        0, /* set_Jprojective_coordinates_GFp */
926
15.1k
        0, /* get_Jprojective_coordinates_GFp */
927
15.1k
        ec_GF2m_simple_point_set_affine_coordinates,
928
15.1k
        ec_GF2m_simple_point_get_affine_coordinates,
929
15.1k
        0, /* point_set_compressed_coordinates */
930
15.1k
        0, /* point2oct */
931
15.1k
        0, /* oct2point */
932
15.1k
        ec_GF2m_simple_add,
933
15.1k
        ec_GF2m_simple_dbl,
934
15.1k
        ec_GF2m_simple_invert,
935
15.1k
        ec_GF2m_simple_is_at_infinity,
936
15.1k
        ec_GF2m_simple_is_on_curve,
937
15.1k
        ec_GF2m_simple_cmp,
938
15.1k
        ec_GF2m_simple_make_affine,
939
15.1k
        ec_GF2m_simple_points_make_affine,
940
15.1k
        ec_GF2m_simple_points_mul,
941
15.1k
        0, /* precompute_mult */
942
15.1k
        0, /* have_precompute_mult */
943
15.1k
        ec_GF2m_simple_field_mul,
944
15.1k
        ec_GF2m_simple_field_sqr,
945
15.1k
        ec_GF2m_simple_field_div,
946
15.1k
        ec_GF2m_simple_field_inv,
947
15.1k
        0, /* field_encode */
948
15.1k
        0, /* field_decode */
949
15.1k
        0, /* field_set_to_one */
950
15.1k
        ec_key_simple_priv2oct,
951
15.1k
        ec_key_simple_oct2priv,
952
15.1k
        0, /* set private */
953
15.1k
        ec_key_simple_generate_key,
954
15.1k
        ec_key_simple_check_key,
955
15.1k
        ec_key_simple_generate_public_key,
956
15.1k
        0, /* keycopy */
957
15.1k
        0, /* keyfinish */
958
15.1k
        ecdh_simple_compute_key,
959
15.1k
        0, /* field_inverse_mod_ord */
960
15.1k
        0, /* blind_coordinates */
961
15.1k
        ec_GF2m_simple_ladder_pre,
962
15.1k
        ec_GF2m_simple_ladder_step,
963
15.1k
        ec_GF2m_simple_ladder_post
964
15.1k
    };
965
966
15.1k
    return &ret;
967
15.1k
}
968
969
#endif