Coverage Report

Created: 2018-08-29 13:53

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