0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 #include "mpi-internal.h"
0022 #include "longlong.h"
0023
0024 #define point_init(a) mpi_point_init((a))
0025 #define point_free(a) mpi_point_free_parts((a))
0026
0027 #define log_error(fmt, ...) pr_err(fmt, ##__VA_ARGS__)
0028 #define log_fatal(fmt, ...) pr_err(fmt, ##__VA_ARGS__)
0029
0030 #define DIM(v) (sizeof(v)/sizeof((v)[0]))
0031
0032
0033
0034
0035
0036
0037 MPI_POINT mpi_point_new(unsigned int nbits)
0038 {
0039 MPI_POINT p;
0040
0041 (void)nbits;
0042
0043 p = kmalloc(sizeof(*p), GFP_KERNEL);
0044 if (p)
0045 mpi_point_init(p);
0046 return p;
0047 }
0048 EXPORT_SYMBOL_GPL(mpi_point_new);
0049
0050
0051 void mpi_point_release(MPI_POINT p)
0052 {
0053 if (p) {
0054 mpi_point_free_parts(p);
0055 kfree(p);
0056 }
0057 }
0058 EXPORT_SYMBOL_GPL(mpi_point_release);
0059
0060
0061
0062
0063 void mpi_point_init(MPI_POINT p)
0064 {
0065 p->x = mpi_new(0);
0066 p->y = mpi_new(0);
0067 p->z = mpi_new(0);
0068 }
0069 EXPORT_SYMBOL_GPL(mpi_point_init);
0070
0071
0072 void mpi_point_free_parts(MPI_POINT p)
0073 {
0074 mpi_free(p->x); p->x = NULL;
0075 mpi_free(p->y); p->y = NULL;
0076 mpi_free(p->z); p->z = NULL;
0077 }
0078 EXPORT_SYMBOL_GPL(mpi_point_free_parts);
0079
0080
0081 static void point_set(MPI_POINT d, MPI_POINT s)
0082 {
0083 mpi_set(d->x, s->x);
0084 mpi_set(d->y, s->y);
0085 mpi_set(d->z, s->z);
0086 }
0087
0088 static void point_resize(MPI_POINT p, struct mpi_ec_ctx *ctx)
0089 {
0090 size_t nlimbs = ctx->p->nlimbs;
0091
0092 mpi_resize(p->x, nlimbs);
0093 p->x->nlimbs = nlimbs;
0094 mpi_resize(p->z, nlimbs);
0095 p->z->nlimbs = nlimbs;
0096
0097 if (ctx->model != MPI_EC_MONTGOMERY) {
0098 mpi_resize(p->y, nlimbs);
0099 p->y->nlimbs = nlimbs;
0100 }
0101 }
0102
0103 static void point_swap_cond(MPI_POINT d, MPI_POINT s, unsigned long swap,
0104 struct mpi_ec_ctx *ctx)
0105 {
0106 mpi_swap_cond(d->x, s->x, swap);
0107 if (ctx->model != MPI_EC_MONTGOMERY)
0108 mpi_swap_cond(d->y, s->y, swap);
0109 mpi_swap_cond(d->z, s->z, swap);
0110 }
0111
0112
0113
0114 static void ec_mod(MPI w, struct mpi_ec_ctx *ec)
0115 {
0116 if (ec->t.p_barrett)
0117 mpi_mod_barrett(w, w, ec->t.p_barrett);
0118 else
0119 mpi_mod(w, w, ec->p);
0120 }
0121
0122 static void ec_addm(MPI w, MPI u, MPI v, struct mpi_ec_ctx *ctx)
0123 {
0124 mpi_add(w, u, v);
0125 ec_mod(w, ctx);
0126 }
0127
0128 static void ec_subm(MPI w, MPI u, MPI v, struct mpi_ec_ctx *ec)
0129 {
0130 mpi_sub(w, u, v);
0131 while (w->sign)
0132 mpi_add(w, w, ec->p);
0133
0134 }
0135
0136 static void ec_mulm(MPI w, MPI u, MPI v, struct mpi_ec_ctx *ctx)
0137 {
0138 mpi_mul(w, u, v);
0139 ec_mod(w, ctx);
0140 }
0141
0142
0143 static void ec_mul2(MPI w, MPI u, struct mpi_ec_ctx *ctx)
0144 {
0145 mpi_lshift(w, u, 1);
0146 ec_mod(w, ctx);
0147 }
0148
0149 static void ec_powm(MPI w, const MPI b, const MPI e,
0150 struct mpi_ec_ctx *ctx)
0151 {
0152 mpi_powm(w, b, e, ctx->p);
0153
0154 }
0155
0156
0157
0158
0159
0160 static void ec_pow2(MPI w, const MPI b, struct mpi_ec_ctx *ctx)
0161 {
0162
0163
0164 ec_mulm(w, b, b, ctx);
0165 }
0166
0167
0168
0169
0170
0171 static void ec_pow3(MPI w, const MPI b, struct mpi_ec_ctx *ctx)
0172 {
0173 mpi_powm(w, b, mpi_const(MPI_C_THREE), ctx->p);
0174 }
0175
0176 static void ec_invm(MPI x, MPI a, struct mpi_ec_ctx *ctx)
0177 {
0178 if (!mpi_invm(x, a, ctx->p))
0179 log_error("ec_invm: inverse does not exist:\n");
0180 }
0181
0182 static void mpih_set_cond(mpi_ptr_t wp, mpi_ptr_t up,
0183 mpi_size_t usize, unsigned long set)
0184 {
0185 mpi_size_t i;
0186 mpi_limb_t mask = ((mpi_limb_t)0) - set;
0187 mpi_limb_t x;
0188
0189 for (i = 0; i < usize; i++) {
0190 x = mask & (wp[i] ^ up[i]);
0191 wp[i] = wp[i] ^ x;
0192 }
0193 }
0194
0195
0196
0197 #define LIMB_SIZE_25519 ((256+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB)
0198
0199 static void ec_addm_25519(MPI w, MPI u, MPI v, struct mpi_ec_ctx *ctx)
0200 {
0201 mpi_ptr_t wp, up, vp;
0202 mpi_size_t wsize = LIMB_SIZE_25519;
0203 mpi_limb_t n[LIMB_SIZE_25519];
0204 mpi_limb_t borrow;
0205
0206 if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
0207 log_bug("addm_25519: different sizes\n");
0208
0209 memset(n, 0, sizeof(n));
0210 up = u->d;
0211 vp = v->d;
0212 wp = w->d;
0213
0214 mpihelp_add_n(wp, up, vp, wsize);
0215 borrow = mpihelp_sub_n(wp, wp, ctx->p->d, wsize);
0216 mpih_set_cond(n, ctx->p->d, wsize, (borrow != 0UL));
0217 mpihelp_add_n(wp, wp, n, wsize);
0218 wp[LIMB_SIZE_25519-1] &= ~((mpi_limb_t)1 << (255 % BITS_PER_MPI_LIMB));
0219 }
0220
0221 static void ec_subm_25519(MPI w, MPI u, MPI v, struct mpi_ec_ctx *ctx)
0222 {
0223 mpi_ptr_t wp, up, vp;
0224 mpi_size_t wsize = LIMB_SIZE_25519;
0225 mpi_limb_t n[LIMB_SIZE_25519];
0226 mpi_limb_t borrow;
0227
0228 if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
0229 log_bug("subm_25519: different sizes\n");
0230
0231 memset(n, 0, sizeof(n));
0232 up = u->d;
0233 vp = v->d;
0234 wp = w->d;
0235
0236 borrow = mpihelp_sub_n(wp, up, vp, wsize);
0237 mpih_set_cond(n, ctx->p->d, wsize, (borrow != 0UL));
0238 mpihelp_add_n(wp, wp, n, wsize);
0239 wp[LIMB_SIZE_25519-1] &= ~((mpi_limb_t)1 << (255 % BITS_PER_MPI_LIMB));
0240 }
0241
0242 static void ec_mulm_25519(MPI w, MPI u, MPI v, struct mpi_ec_ctx *ctx)
0243 {
0244 mpi_ptr_t wp, up, vp;
0245 mpi_size_t wsize = LIMB_SIZE_25519;
0246 mpi_limb_t n[LIMB_SIZE_25519*2];
0247 mpi_limb_t m[LIMB_SIZE_25519+1];
0248 mpi_limb_t cy;
0249 int msb;
0250
0251 (void)ctx;
0252 if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
0253 log_bug("mulm_25519: different sizes\n");
0254
0255 up = u->d;
0256 vp = v->d;
0257 wp = w->d;
0258
0259 mpihelp_mul_n(n, up, vp, wsize);
0260 memcpy(wp, n, wsize * BYTES_PER_MPI_LIMB);
0261 wp[LIMB_SIZE_25519-1] &= ~((mpi_limb_t)1 << (255 % BITS_PER_MPI_LIMB));
0262
0263 memcpy(m, n+LIMB_SIZE_25519-1, (wsize+1) * BYTES_PER_MPI_LIMB);
0264 mpihelp_rshift(m, m, LIMB_SIZE_25519+1, (255 % BITS_PER_MPI_LIMB));
0265
0266 memcpy(n, m, wsize * BYTES_PER_MPI_LIMB);
0267 cy = mpihelp_lshift(m, m, LIMB_SIZE_25519, 4);
0268 m[LIMB_SIZE_25519] = cy;
0269 cy = mpihelp_add_n(m, m, n, wsize);
0270 m[LIMB_SIZE_25519] += cy;
0271 cy = mpihelp_add_n(m, m, n, wsize);
0272 m[LIMB_SIZE_25519] += cy;
0273 cy = mpihelp_add_n(m, m, n, wsize);
0274 m[LIMB_SIZE_25519] += cy;
0275
0276 cy = mpihelp_add_n(wp, wp, m, wsize);
0277 m[LIMB_SIZE_25519] += cy;
0278
0279 memset(m, 0, wsize * BYTES_PER_MPI_LIMB);
0280 msb = (wp[LIMB_SIZE_25519-1] >> (255 % BITS_PER_MPI_LIMB));
0281 m[0] = (m[LIMB_SIZE_25519] * 2 + msb) * 19;
0282 wp[LIMB_SIZE_25519-1] &= ~((mpi_limb_t)1 << (255 % BITS_PER_MPI_LIMB));
0283 mpihelp_add_n(wp, wp, m, wsize);
0284
0285 m[0] = 0;
0286 cy = mpihelp_sub_n(wp, wp, ctx->p->d, wsize);
0287 mpih_set_cond(m, ctx->p->d, wsize, (cy != 0UL));
0288 mpihelp_add_n(wp, wp, m, wsize);
0289 }
0290
0291 static void ec_mul2_25519(MPI w, MPI u, struct mpi_ec_ctx *ctx)
0292 {
0293 ec_addm_25519(w, u, u, ctx);
0294 }
0295
0296 static void ec_pow2_25519(MPI w, const MPI b, struct mpi_ec_ctx *ctx)
0297 {
0298 ec_mulm_25519(w, b, b, ctx);
0299 }
0300
0301
0302
0303 #define LIMB_SIZE_448 ((448+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB)
0304 #define LIMB_SIZE_HALF_448 ((LIMB_SIZE_448+1)/2)
0305
0306 static void ec_addm_448(MPI w, MPI u, MPI v, struct mpi_ec_ctx *ctx)
0307 {
0308 mpi_ptr_t wp, up, vp;
0309 mpi_size_t wsize = LIMB_SIZE_448;
0310 mpi_limb_t n[LIMB_SIZE_448];
0311 mpi_limb_t cy;
0312
0313 if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
0314 log_bug("addm_448: different sizes\n");
0315
0316 memset(n, 0, sizeof(n));
0317 up = u->d;
0318 vp = v->d;
0319 wp = w->d;
0320
0321 cy = mpihelp_add_n(wp, up, vp, wsize);
0322 mpih_set_cond(n, ctx->p->d, wsize, (cy != 0UL));
0323 mpihelp_sub_n(wp, wp, n, wsize);
0324 }
0325
0326 static void ec_subm_448(MPI w, MPI u, MPI v, struct mpi_ec_ctx *ctx)
0327 {
0328 mpi_ptr_t wp, up, vp;
0329 mpi_size_t wsize = LIMB_SIZE_448;
0330 mpi_limb_t n[LIMB_SIZE_448];
0331 mpi_limb_t borrow;
0332
0333 if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
0334 log_bug("subm_448: different sizes\n");
0335
0336 memset(n, 0, sizeof(n));
0337 up = u->d;
0338 vp = v->d;
0339 wp = w->d;
0340
0341 borrow = mpihelp_sub_n(wp, up, vp, wsize);
0342 mpih_set_cond(n, ctx->p->d, wsize, (borrow != 0UL));
0343 mpihelp_add_n(wp, wp, n, wsize);
0344 }
0345
0346 static void ec_mulm_448(MPI w, MPI u, MPI v, struct mpi_ec_ctx *ctx)
0347 {
0348 mpi_ptr_t wp, up, vp;
0349 mpi_size_t wsize = LIMB_SIZE_448;
0350 mpi_limb_t n[LIMB_SIZE_448*2];
0351 mpi_limb_t a2[LIMB_SIZE_HALF_448];
0352 mpi_limb_t a3[LIMB_SIZE_HALF_448];
0353 mpi_limb_t b0[LIMB_SIZE_HALF_448];
0354 mpi_limb_t b1[LIMB_SIZE_HALF_448];
0355 mpi_limb_t cy;
0356 int i;
0357 #if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2)
0358 mpi_limb_t b1_rest, a3_rest;
0359 #endif
0360
0361 if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
0362 log_bug("mulm_448: different sizes\n");
0363
0364 up = u->d;
0365 vp = v->d;
0366 wp = w->d;
0367
0368 mpihelp_mul_n(n, up, vp, wsize);
0369
0370 for (i = 0; i < (wsize + 1) / 2; i++) {
0371 b0[i] = n[i];
0372 b1[i] = n[i+wsize/2];
0373 a2[i] = n[i+wsize];
0374 a3[i] = n[i+wsize+wsize/2];
0375 }
0376
0377 #if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2)
0378 b0[LIMB_SIZE_HALF_448-1] &= ((mpi_limb_t)1UL << 32)-1;
0379 a2[LIMB_SIZE_HALF_448-1] &= ((mpi_limb_t)1UL << 32)-1;
0380
0381 b1_rest = 0;
0382 a3_rest = 0;
0383
0384 for (i = (wsize + 1) / 2 - 1; i >= 0; i--) {
0385 mpi_limb_t b1v, a3v;
0386 b1v = b1[i];
0387 a3v = a3[i];
0388 b1[i] = (b1_rest << 32) | (b1v >> 32);
0389 a3[i] = (a3_rest << 32) | (a3v >> 32);
0390 b1_rest = b1v & (((mpi_limb_t)1UL << 32)-1);
0391 a3_rest = a3v & (((mpi_limb_t)1UL << 32)-1);
0392 }
0393 #endif
0394
0395 cy = mpihelp_add_n(b0, b0, a2, LIMB_SIZE_HALF_448);
0396 cy += mpihelp_add_n(b0, b0, a3, LIMB_SIZE_HALF_448);
0397 for (i = 0; i < (wsize + 1) / 2; i++)
0398 wp[i] = b0[i];
0399 #if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2)
0400 wp[LIMB_SIZE_HALF_448-1] &= (((mpi_limb_t)1UL << 32)-1);
0401 #endif
0402
0403 #if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2)
0404 cy = b0[LIMB_SIZE_HALF_448-1] >> 32;
0405 #endif
0406
0407 cy = mpihelp_add_1(b1, b1, LIMB_SIZE_HALF_448, cy);
0408 cy += mpihelp_add_n(b1, b1, a2, LIMB_SIZE_HALF_448);
0409 cy += mpihelp_add_n(b1, b1, a3, LIMB_SIZE_HALF_448);
0410 cy += mpihelp_add_n(b1, b1, a3, LIMB_SIZE_HALF_448);
0411 #if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2)
0412 b1_rest = 0;
0413 for (i = (wsize + 1) / 2 - 1; i >= 0; i--) {
0414 mpi_limb_t b1v = b1[i];
0415 b1[i] = (b1_rest << 32) | (b1v >> 32);
0416 b1_rest = b1v & (((mpi_limb_t)1UL << 32)-1);
0417 }
0418 wp[LIMB_SIZE_HALF_448-1] |= (b1_rest << 32);
0419 #endif
0420 for (i = 0; i < wsize / 2; i++)
0421 wp[i+(wsize + 1) / 2] = b1[i];
0422
0423 #if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2)
0424 cy = b1[LIMB_SIZE_HALF_448-1];
0425 #endif
0426
0427 memset(n, 0, wsize * BYTES_PER_MPI_LIMB);
0428
0429 #if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2)
0430 n[LIMB_SIZE_HALF_448-1] = cy << 32;
0431 #else
0432 n[LIMB_SIZE_HALF_448] = cy;
0433 #endif
0434 n[0] = cy;
0435 mpihelp_add_n(wp, wp, n, wsize);
0436
0437 memset(n, 0, wsize * BYTES_PER_MPI_LIMB);
0438 cy = mpihelp_sub_n(wp, wp, ctx->p->d, wsize);
0439 mpih_set_cond(n, ctx->p->d, wsize, (cy != 0UL));
0440 mpihelp_add_n(wp, wp, n, wsize);
0441 }
0442
0443 static void ec_mul2_448(MPI w, MPI u, struct mpi_ec_ctx *ctx)
0444 {
0445 ec_addm_448(w, u, u, ctx);
0446 }
0447
0448 static void ec_pow2_448(MPI w, const MPI b, struct mpi_ec_ctx *ctx)
0449 {
0450 ec_mulm_448(w, b, b, ctx);
0451 }
0452
0453 struct field_table {
0454 const char *p;
0455
0456
0457 void (*addm)(MPI w, MPI u, MPI v, struct mpi_ec_ctx *ctx);
0458 void (*subm)(MPI w, MPI u, MPI v, struct mpi_ec_ctx *ctx);
0459 void (*mulm)(MPI w, MPI u, MPI v, struct mpi_ec_ctx *ctx);
0460 void (*mul2)(MPI w, MPI u, struct mpi_ec_ctx *ctx);
0461 void (*pow2)(MPI w, const MPI b, struct mpi_ec_ctx *ctx);
0462 };
0463
0464 static const struct field_table field_table[] = {
0465 {
0466 "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED",
0467 ec_addm_25519,
0468 ec_subm_25519,
0469 ec_mulm_25519,
0470 ec_mul2_25519,
0471 ec_pow2_25519
0472 },
0473 {
0474 "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
0475 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
0476 ec_addm_448,
0477 ec_subm_448,
0478 ec_mulm_448,
0479 ec_mul2_448,
0480 ec_pow2_448
0481 },
0482 { NULL, NULL, NULL, NULL, NULL, NULL },
0483 };
0484
0485
0486 static void mpi_ec_get_reset(struct mpi_ec_ctx *ec)
0487 {
0488 ec->t.valid.a_is_pminus3 = 0;
0489 ec->t.valid.two_inv_p = 0;
0490 }
0491
0492
0493 static int ec_get_a_is_pminus3(struct mpi_ec_ctx *ec)
0494 {
0495 MPI tmp;
0496
0497 if (!ec->t.valid.a_is_pminus3) {
0498 ec->t.valid.a_is_pminus3 = 1;
0499 tmp = mpi_alloc_like(ec->p);
0500 mpi_sub_ui(tmp, ec->p, 3);
0501 ec->t.a_is_pminus3 = !mpi_cmp(ec->a, tmp);
0502 mpi_free(tmp);
0503 }
0504
0505 return ec->t.a_is_pminus3;
0506 }
0507
0508
0509 static MPI ec_get_two_inv_p(struct mpi_ec_ctx *ec)
0510 {
0511 if (!ec->t.valid.two_inv_p) {
0512 ec->t.valid.two_inv_p = 1;
0513 if (!ec->t.two_inv_p)
0514 ec->t.two_inv_p = mpi_alloc(0);
0515 ec_invm(ec->t.two_inv_p, mpi_const(MPI_C_TWO), ec);
0516 }
0517 return ec->t.two_inv_p;
0518 }
0519
0520 static const char *const curve25519_bad_points[] = {
0521 "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed",
0522 "0x0000000000000000000000000000000000000000000000000000000000000000",
0523 "0x0000000000000000000000000000000000000000000000000000000000000001",
0524 "0x00b8495f16056286fdb1329ceb8d09da6ac49ff1fae35616aeb8413b7c7aebe0",
0525 "0x57119fd0dd4e22d8868e1c58c45c44045bef839c55b1d0b1248c50a3bc959c5f",
0526 "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec",
0527 "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee",
0528 NULL
0529 };
0530
0531 static const char *const curve448_bad_points[] = {
0532 "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
0533 "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
0534 "0x00000000000000000000000000000000000000000000000000000000"
0535 "00000000000000000000000000000000000000000000000000000000",
0536 "0x00000000000000000000000000000000000000000000000000000000"
0537 "00000000000000000000000000000000000000000000000000000001",
0538 "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
0539 "fffffffffffffffffffffffffffffffffffffffffffffffffffffffe",
0540 "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
0541 "00000000000000000000000000000000000000000000000000000000",
0542 NULL
0543 };
0544
0545 static const char *const *bad_points_table[] = {
0546 curve25519_bad_points,
0547 curve448_bad_points,
0548 };
0549
0550 static void mpi_ec_coefficient_normalize(MPI a, MPI p)
0551 {
0552 if (a->sign) {
0553 mpi_resize(a, p->nlimbs);
0554 mpihelp_sub_n(a->d, p->d, a->d, p->nlimbs);
0555 a->nlimbs = p->nlimbs;
0556 a->sign = 0;
0557 }
0558 }
0559
0560
0561
0562
0563
0564 void mpi_ec_init(struct mpi_ec_ctx *ctx, enum gcry_mpi_ec_models model,
0565 enum ecc_dialects dialect,
0566 int flags, MPI p, MPI a, MPI b)
0567 {
0568 int i;
0569 static int use_barrett = -1 ;
0570
0571 mpi_ec_coefficient_normalize(a, p);
0572 mpi_ec_coefficient_normalize(b, p);
0573
0574
0575
0576 ctx->model = model;
0577 ctx->dialect = dialect;
0578 ctx->flags = flags;
0579 if (dialect == ECC_DIALECT_ED25519)
0580 ctx->nbits = 256;
0581 else
0582 ctx->nbits = mpi_get_nbits(p);
0583 ctx->p = mpi_copy(p);
0584 ctx->a = mpi_copy(a);
0585 ctx->b = mpi_copy(b);
0586
0587 ctx->t.p_barrett = use_barrett > 0 ? mpi_barrett_init(ctx->p, 0) : NULL;
0588
0589 mpi_ec_get_reset(ctx);
0590
0591 if (model == MPI_EC_MONTGOMERY) {
0592 for (i = 0; i < DIM(bad_points_table); i++) {
0593 MPI p_candidate = mpi_scanval(bad_points_table[i][0]);
0594 int match_p = !mpi_cmp(ctx->p, p_candidate);
0595 int j;
0596
0597 mpi_free(p_candidate);
0598 if (!match_p)
0599 continue;
0600
0601 for (j = 0; i < DIM(ctx->t.scratch) && bad_points_table[i][j]; j++)
0602 ctx->t.scratch[j] = mpi_scanval(bad_points_table[i][j]);
0603 }
0604 } else {
0605
0606 for (i = 0; i < DIM(ctx->t.scratch); i++)
0607 ctx->t.scratch[i] = mpi_alloc_like(ctx->p);
0608 }
0609
0610 ctx->addm = ec_addm;
0611 ctx->subm = ec_subm;
0612 ctx->mulm = ec_mulm;
0613 ctx->mul2 = ec_mul2;
0614 ctx->pow2 = ec_pow2;
0615
0616 for (i = 0; field_table[i].p; i++) {
0617 MPI f_p;
0618
0619 f_p = mpi_scanval(field_table[i].p);
0620 if (!f_p)
0621 break;
0622
0623 if (!mpi_cmp(p, f_p)) {
0624 ctx->addm = field_table[i].addm;
0625 ctx->subm = field_table[i].subm;
0626 ctx->mulm = field_table[i].mulm;
0627 ctx->mul2 = field_table[i].mul2;
0628 ctx->pow2 = field_table[i].pow2;
0629 mpi_free(f_p);
0630
0631 mpi_resize(ctx->a, ctx->p->nlimbs);
0632 ctx->a->nlimbs = ctx->p->nlimbs;
0633
0634 mpi_resize(ctx->b, ctx->p->nlimbs);
0635 ctx->b->nlimbs = ctx->p->nlimbs;
0636
0637 for (i = 0; i < DIM(ctx->t.scratch) && ctx->t.scratch[i]; i++)
0638 ctx->t.scratch[i]->nlimbs = ctx->p->nlimbs;
0639
0640 break;
0641 }
0642
0643 mpi_free(f_p);
0644 }
0645 }
0646 EXPORT_SYMBOL_GPL(mpi_ec_init);
0647
0648 void mpi_ec_deinit(struct mpi_ec_ctx *ctx)
0649 {
0650 int i;
0651
0652 mpi_barrett_free(ctx->t.p_barrett);
0653
0654
0655 mpi_free(ctx->p);
0656 mpi_free(ctx->a);
0657 mpi_free(ctx->b);
0658 mpi_point_release(ctx->G);
0659 mpi_free(ctx->n);
0660
0661
0662 mpi_point_release(ctx->Q);
0663 mpi_free(ctx->d);
0664
0665
0666 mpi_free(ctx->t.two_inv_p);
0667
0668 for (i = 0; i < DIM(ctx->t.scratch); i++)
0669 mpi_free(ctx->t.scratch[i]);
0670 }
0671 EXPORT_SYMBOL_GPL(mpi_ec_deinit);
0672
0673
0674
0675
0676
0677
0678 int mpi_ec_get_affine(MPI x, MPI y, MPI_POINT point, struct mpi_ec_ctx *ctx)
0679 {
0680 if (!mpi_cmp_ui(point->z, 0))
0681 return -1;
0682
0683 switch (ctx->model) {
0684 case MPI_EC_WEIERSTRASS:
0685 {
0686 MPI z1, z2, z3;
0687
0688 z1 = mpi_new(0);
0689 z2 = mpi_new(0);
0690 ec_invm(z1, point->z, ctx);
0691 ec_mulm(z2, z1, z1, ctx);
0692
0693 if (x)
0694 ec_mulm(x, point->x, z2, ctx);
0695
0696 if (y) {
0697 z3 = mpi_new(0);
0698 ec_mulm(z3, z2, z1, ctx);
0699 ec_mulm(y, point->y, z3, ctx);
0700 mpi_free(z3);
0701 }
0702
0703 mpi_free(z2);
0704 mpi_free(z1);
0705 }
0706 return 0;
0707
0708 case MPI_EC_MONTGOMERY:
0709 {
0710 if (x)
0711 mpi_set(x, point->x);
0712
0713 if (y) {
0714 log_fatal("%s: Getting Y-coordinate on %s is not supported\n",
0715 "mpi_ec_get_affine", "Montgomery");
0716 return -1;
0717 }
0718 }
0719 return 0;
0720
0721 case MPI_EC_EDWARDS:
0722 {
0723 MPI z;
0724
0725 z = mpi_new(0);
0726 ec_invm(z, point->z, ctx);
0727
0728 mpi_resize(z, ctx->p->nlimbs);
0729 z->nlimbs = ctx->p->nlimbs;
0730
0731 if (x) {
0732 mpi_resize(x, ctx->p->nlimbs);
0733 x->nlimbs = ctx->p->nlimbs;
0734 ctx->mulm(x, point->x, z, ctx);
0735 }
0736 if (y) {
0737 mpi_resize(y, ctx->p->nlimbs);
0738 y->nlimbs = ctx->p->nlimbs;
0739 ctx->mulm(y, point->y, z, ctx);
0740 }
0741
0742 mpi_free(z);
0743 }
0744 return 0;
0745
0746 default:
0747 return -1;
0748 }
0749 }
0750 EXPORT_SYMBOL_GPL(mpi_ec_get_affine);
0751
0752
0753 static void dup_point_weierstrass(MPI_POINT result,
0754 MPI_POINT point, struct mpi_ec_ctx *ctx)
0755 {
0756 #define x3 (result->x)
0757 #define y3 (result->y)
0758 #define z3 (result->z)
0759 #define t1 (ctx->t.scratch[0])
0760 #define t2 (ctx->t.scratch[1])
0761 #define t3 (ctx->t.scratch[2])
0762 #define l1 (ctx->t.scratch[3])
0763 #define l2 (ctx->t.scratch[4])
0764 #define l3 (ctx->t.scratch[5])
0765
0766 if (!mpi_cmp_ui(point->y, 0) || !mpi_cmp_ui(point->z, 0)) {
0767
0768 mpi_set_ui(x3, 1);
0769 mpi_set_ui(y3, 1);
0770 mpi_set_ui(z3, 0);
0771 } else {
0772 if (ec_get_a_is_pminus3(ctx)) {
0773
0774
0775
0776
0777 ec_pow2(t1, point->z, ctx);
0778 ec_subm(l1, point->x, t1, ctx);
0779 ec_mulm(l1, l1, mpi_const(MPI_C_THREE), ctx);
0780 ec_addm(t2, point->x, t1, ctx);
0781 ec_mulm(l1, l1, t2, ctx);
0782 } else {
0783
0784
0785
0786 ec_pow2(l1, point->x, ctx);
0787 ec_mulm(l1, l1, mpi_const(MPI_C_THREE), ctx);
0788 ec_powm(t1, point->z, mpi_const(MPI_C_FOUR), ctx);
0789 ec_mulm(t1, t1, ctx->a, ctx);
0790 ec_addm(l1, l1, t1, ctx);
0791 }
0792
0793 ec_mulm(z3, point->y, point->z, ctx);
0794 ec_mul2(z3, z3, ctx);
0795
0796
0797
0798 ec_pow2(t2, point->y, ctx);
0799 ec_mulm(l2, t2, point->x, ctx);
0800 ec_mulm(l2, l2, mpi_const(MPI_C_FOUR), ctx);
0801
0802
0803
0804 ec_pow2(x3, l1, ctx);
0805 ec_mul2(t1, l2, ctx);
0806 ec_subm(x3, x3, t1, ctx);
0807
0808
0809
0810 ec_pow2(t2, t2, ctx);
0811 ec_mulm(l3, t2, mpi_const(MPI_C_EIGHT), ctx);
0812
0813
0814 ec_subm(y3, l2, x3, ctx);
0815 ec_mulm(y3, y3, l1, ctx);
0816 ec_subm(y3, y3, l3, ctx);
0817 }
0818
0819 #undef x3
0820 #undef y3
0821 #undef z3
0822 #undef t1
0823 #undef t2
0824 #undef t3
0825 #undef l1
0826 #undef l2
0827 #undef l3
0828 }
0829
0830
0831 static void dup_point_montgomery(MPI_POINT result,
0832 MPI_POINT point, struct mpi_ec_ctx *ctx)
0833 {
0834 (void)result;
0835 (void)point;
0836 (void)ctx;
0837 log_fatal("%s: %s not yet supported\n",
0838 "mpi_ec_dup_point", "Montgomery");
0839 }
0840
0841
0842 static void dup_point_edwards(MPI_POINT result,
0843 MPI_POINT point, struct mpi_ec_ctx *ctx)
0844 {
0845 #define X1 (point->x)
0846 #define Y1 (point->y)
0847 #define Z1 (point->z)
0848 #define X3 (result->x)
0849 #define Y3 (result->y)
0850 #define Z3 (result->z)
0851 #define B (ctx->t.scratch[0])
0852 #define C (ctx->t.scratch[1])
0853 #define D (ctx->t.scratch[2])
0854 #define E (ctx->t.scratch[3])
0855 #define F (ctx->t.scratch[4])
0856 #define H (ctx->t.scratch[5])
0857 #define J (ctx->t.scratch[6])
0858
0859
0860
0861
0862 ctx->addm(B, X1, Y1, ctx);
0863 ctx->pow2(B, B, ctx);
0864
0865
0866
0867 ctx->pow2(C, X1, ctx);
0868 ctx->pow2(D, Y1, ctx);
0869
0870
0871 if (ctx->dialect == ECC_DIALECT_ED25519)
0872 ctx->subm(E, ctx->p, C, ctx);
0873 else
0874 ctx->mulm(E, ctx->a, C, ctx);
0875
0876
0877 ctx->addm(F, E, D, ctx);
0878
0879
0880 ctx->pow2(H, Z1, ctx);
0881
0882
0883 ctx->mul2(J, H, ctx);
0884 ctx->subm(J, F, J, ctx);
0885
0886
0887 ctx->subm(X3, B, C, ctx);
0888 ctx->subm(X3, X3, D, ctx);
0889 ctx->mulm(X3, X3, J, ctx);
0890
0891
0892 ctx->subm(Y3, E, D, ctx);
0893 ctx->mulm(Y3, Y3, F, ctx);
0894
0895
0896 ctx->mulm(Z3, F, J, ctx);
0897
0898 #undef X1
0899 #undef Y1
0900 #undef Z1
0901 #undef X3
0902 #undef Y3
0903 #undef Z3
0904 #undef B
0905 #undef C
0906 #undef D
0907 #undef E
0908 #undef F
0909 #undef H
0910 #undef J
0911 }
0912
0913
0914 static void
0915 mpi_ec_dup_point(MPI_POINT result, MPI_POINT point, struct mpi_ec_ctx *ctx)
0916 {
0917 switch (ctx->model) {
0918 case MPI_EC_WEIERSTRASS:
0919 dup_point_weierstrass(result, point, ctx);
0920 break;
0921 case MPI_EC_MONTGOMERY:
0922 dup_point_montgomery(result, point, ctx);
0923 break;
0924 case MPI_EC_EDWARDS:
0925 dup_point_edwards(result, point, ctx);
0926 break;
0927 }
0928 }
0929
0930
0931 static void add_points_weierstrass(MPI_POINT result,
0932 MPI_POINT p1, MPI_POINT p2,
0933 struct mpi_ec_ctx *ctx)
0934 {
0935 #define x1 (p1->x)
0936 #define y1 (p1->y)
0937 #define z1 (p1->z)
0938 #define x2 (p2->x)
0939 #define y2 (p2->y)
0940 #define z2 (p2->z)
0941 #define x3 (result->x)
0942 #define y3 (result->y)
0943 #define z3 (result->z)
0944 #define l1 (ctx->t.scratch[0])
0945 #define l2 (ctx->t.scratch[1])
0946 #define l3 (ctx->t.scratch[2])
0947 #define l4 (ctx->t.scratch[3])
0948 #define l5 (ctx->t.scratch[4])
0949 #define l6 (ctx->t.scratch[5])
0950 #define l7 (ctx->t.scratch[6])
0951 #define l8 (ctx->t.scratch[7])
0952 #define l9 (ctx->t.scratch[8])
0953 #define t1 (ctx->t.scratch[9])
0954 #define t2 (ctx->t.scratch[10])
0955
0956 if ((!mpi_cmp(x1, x2)) && (!mpi_cmp(y1, y2)) && (!mpi_cmp(z1, z2))) {
0957
0958 mpi_ec_dup_point(result, p1, ctx);
0959 } else if (!mpi_cmp_ui(z1, 0)) {
0960
0961 mpi_set(x3, p2->x);
0962 mpi_set(y3, p2->y);
0963 mpi_set(z3, p2->z);
0964 } else if (!mpi_cmp_ui(z2, 0)) {
0965
0966 mpi_set(x3, p1->x);
0967 mpi_set(y3, p1->y);
0968 mpi_set(z3, p1->z);
0969 } else {
0970 int z1_is_one = !mpi_cmp_ui(z1, 1);
0971 int z2_is_one = !mpi_cmp_ui(z2, 1);
0972
0973
0974
0975 if (z2_is_one)
0976 mpi_set(l1, x1);
0977 else {
0978 ec_pow2(l1, z2, ctx);
0979 ec_mulm(l1, l1, x1, ctx);
0980 }
0981 if (z1_is_one)
0982 mpi_set(l2, x2);
0983 else {
0984 ec_pow2(l2, z1, ctx);
0985 ec_mulm(l2, l2, x2, ctx);
0986 }
0987
0988 ec_subm(l3, l1, l2, ctx);
0989
0990 ec_powm(l4, z2, mpi_const(MPI_C_THREE), ctx);
0991 ec_mulm(l4, l4, y1, ctx);
0992
0993 ec_powm(l5, z1, mpi_const(MPI_C_THREE), ctx);
0994 ec_mulm(l5, l5, y2, ctx);
0995
0996 ec_subm(l6, l4, l5, ctx);
0997
0998 if (!mpi_cmp_ui(l3, 0)) {
0999 if (!mpi_cmp_ui(l6, 0)) {
1000
1001 mpi_ec_dup_point(result, p1, ctx);
1002 } else {
1003
1004 mpi_set_ui(x3, 1);
1005 mpi_set_ui(y3, 1);
1006 mpi_set_ui(z3, 0);
1007 }
1008 } else {
1009
1010 ec_addm(l7, l1, l2, ctx);
1011
1012 ec_addm(l8, l4, l5, ctx);
1013
1014 ec_mulm(z3, z1, z2, ctx);
1015 ec_mulm(z3, z3, l3, ctx);
1016
1017 ec_pow2(t1, l6, ctx);
1018 ec_pow2(t2, l3, ctx);
1019 ec_mulm(t2, t2, l7, ctx);
1020 ec_subm(x3, t1, t2, ctx);
1021
1022 ec_mul2(t1, x3, ctx);
1023 ec_subm(l9, t2, t1, ctx);
1024
1025 ec_mulm(l9, l9, l6, ctx);
1026 ec_powm(t1, l3, mpi_const(MPI_C_THREE), ctx);
1027 ec_mulm(t1, t1, l8, ctx);
1028 ec_subm(y3, l9, t1, ctx);
1029 ec_mulm(y3, y3, ec_get_two_inv_p(ctx), ctx);
1030 }
1031 }
1032
1033 #undef x1
1034 #undef y1
1035 #undef z1
1036 #undef x2
1037 #undef y2
1038 #undef z2
1039 #undef x3
1040 #undef y3
1041 #undef z3
1042 #undef l1
1043 #undef l2
1044 #undef l3
1045 #undef l4
1046 #undef l5
1047 #undef l6
1048 #undef l7
1049 #undef l8
1050 #undef l9
1051 #undef t1
1052 #undef t2
1053 }
1054
1055
1056 static void add_points_montgomery(MPI_POINT result,
1057 MPI_POINT p1, MPI_POINT p2,
1058 struct mpi_ec_ctx *ctx)
1059 {
1060 (void)result;
1061 (void)p1;
1062 (void)p2;
1063 (void)ctx;
1064 log_fatal("%s: %s not yet supported\n",
1065 "mpi_ec_add_points", "Montgomery");
1066 }
1067
1068
1069 static void add_points_edwards(MPI_POINT result,
1070 MPI_POINT p1, MPI_POINT p2,
1071 struct mpi_ec_ctx *ctx)
1072 {
1073 #define X1 (p1->x)
1074 #define Y1 (p1->y)
1075 #define Z1 (p1->z)
1076 #define X2 (p2->x)
1077 #define Y2 (p2->y)
1078 #define Z2 (p2->z)
1079 #define X3 (result->x)
1080 #define Y3 (result->y)
1081 #define Z3 (result->z)
1082 #define A (ctx->t.scratch[0])
1083 #define B (ctx->t.scratch[1])
1084 #define C (ctx->t.scratch[2])
1085 #define D (ctx->t.scratch[3])
1086 #define E (ctx->t.scratch[4])
1087 #define F (ctx->t.scratch[5])
1088 #define G (ctx->t.scratch[6])
1089 #define tmp (ctx->t.scratch[7])
1090
1091 point_resize(result, ctx);
1092
1093
1094
1095
1096 ctx->mulm(A, Z1, Z2, ctx);
1097
1098
1099 ctx->pow2(B, A, ctx);
1100
1101
1102 ctx->mulm(C, X1, X2, ctx);
1103
1104
1105 ctx->mulm(D, Y1, Y2, ctx);
1106
1107
1108 ctx->mulm(E, ctx->b, C, ctx);
1109 ctx->mulm(E, E, D, ctx);
1110
1111
1112 ctx->subm(F, B, E, ctx);
1113
1114
1115 ctx->addm(G, B, E, ctx);
1116
1117
1118 ctx->addm(tmp, X1, Y1, ctx);
1119 ctx->addm(X3, X2, Y2, ctx);
1120 ctx->mulm(X3, X3, tmp, ctx);
1121 ctx->subm(X3, X3, C, ctx);
1122 ctx->subm(X3, X3, D, ctx);
1123 ctx->mulm(X3, X3, F, ctx);
1124 ctx->mulm(X3, X3, A, ctx);
1125
1126
1127 if (ctx->dialect == ECC_DIALECT_ED25519) {
1128 ctx->addm(Y3, D, C, ctx);
1129 } else {
1130 ctx->mulm(Y3, ctx->a, C, ctx);
1131 ctx->subm(Y3, D, Y3, ctx);
1132 }
1133 ctx->mulm(Y3, Y3, G, ctx);
1134 ctx->mulm(Y3, Y3, A, ctx);
1135
1136
1137 ctx->mulm(Z3, F, G, ctx);
1138
1139
1140 #undef X1
1141 #undef Y1
1142 #undef Z1
1143 #undef X2
1144 #undef Y2
1145 #undef Z2
1146 #undef X3
1147 #undef Y3
1148 #undef Z3
1149 #undef A
1150 #undef B
1151 #undef C
1152 #undef D
1153 #undef E
1154 #undef F
1155 #undef G
1156 #undef tmp
1157 }
1158
1159
1160
1161
1162
1163 static void montgomery_ladder(MPI_POINT prd, MPI_POINT sum,
1164 MPI_POINT p1, MPI_POINT p2, MPI dif_x,
1165 struct mpi_ec_ctx *ctx)
1166 {
1167 ctx->addm(sum->x, p2->x, p2->z, ctx);
1168 ctx->subm(p2->z, p2->x, p2->z, ctx);
1169 ctx->addm(prd->x, p1->x, p1->z, ctx);
1170 ctx->subm(p1->z, p1->x, p1->z, ctx);
1171 ctx->mulm(p2->x, p1->z, sum->x, ctx);
1172 ctx->mulm(p2->z, prd->x, p2->z, ctx);
1173 ctx->pow2(p1->x, prd->x, ctx);
1174 ctx->pow2(p1->z, p1->z, ctx);
1175 ctx->addm(sum->x, p2->x, p2->z, ctx);
1176 ctx->subm(p2->z, p2->x, p2->z, ctx);
1177 ctx->mulm(prd->x, p1->x, p1->z, ctx);
1178 ctx->subm(p1->z, p1->x, p1->z, ctx);
1179 ctx->pow2(sum->x, sum->x, ctx);
1180 ctx->pow2(sum->z, p2->z, ctx);
1181 ctx->mulm(prd->z, p1->z, ctx->a, ctx);
1182 ctx->mulm(sum->z, sum->z, dif_x, ctx);
1183 ctx->addm(prd->z, p1->x, prd->z, ctx);
1184 ctx->mulm(prd->z, prd->z, p1->z, ctx);
1185 }
1186
1187
1188 void mpi_ec_add_points(MPI_POINT result,
1189 MPI_POINT p1, MPI_POINT p2,
1190 struct mpi_ec_ctx *ctx)
1191 {
1192 switch (ctx->model) {
1193 case MPI_EC_WEIERSTRASS:
1194 add_points_weierstrass(result, p1, p2, ctx);
1195 break;
1196 case MPI_EC_MONTGOMERY:
1197 add_points_montgomery(result, p1, p2, ctx);
1198 break;
1199 case MPI_EC_EDWARDS:
1200 add_points_edwards(result, p1, p2, ctx);
1201 break;
1202 }
1203 }
1204 EXPORT_SYMBOL_GPL(mpi_ec_add_points);
1205
1206
1207
1208
1209
1210 void mpi_ec_mul_point(MPI_POINT result,
1211 MPI scalar, MPI_POINT point,
1212 struct mpi_ec_ctx *ctx)
1213 {
1214 MPI x1, y1, z1, k, h, yy;
1215 unsigned int i, loops;
1216 struct gcry_mpi_point p1, p2, p1inv;
1217
1218 if (ctx->model == MPI_EC_EDWARDS) {
1219
1220
1221
1222
1223
1224
1225
1226 unsigned int nbits;
1227 int j;
1228
1229 if (mpi_cmp(scalar, ctx->p) >= 0)
1230 nbits = mpi_get_nbits(scalar);
1231 else
1232 nbits = mpi_get_nbits(ctx->p);
1233
1234 mpi_set_ui(result->x, 0);
1235 mpi_set_ui(result->y, 1);
1236 mpi_set_ui(result->z, 1);
1237 point_resize(point, ctx);
1238
1239 point_resize(result, ctx);
1240 point_resize(point, ctx);
1241
1242 for (j = nbits-1; j >= 0; j--) {
1243 mpi_ec_dup_point(result, result, ctx);
1244 if (mpi_test_bit(scalar, j))
1245 mpi_ec_add_points(result, result, point, ctx);
1246 }
1247 return;
1248 } else if (ctx->model == MPI_EC_MONTGOMERY) {
1249 unsigned int nbits;
1250 int j;
1251 struct gcry_mpi_point p1_, p2_;
1252 MPI_POINT q1, q2, prd, sum;
1253 unsigned long sw;
1254 mpi_size_t rsize;
1255
1256
1257
1258
1259
1260
1261 nbits = mpi_get_nbits(scalar);
1262 point_init(&p1);
1263 point_init(&p2);
1264 point_init(&p1_);
1265 point_init(&p2_);
1266 mpi_set_ui(p1.x, 1);
1267 mpi_free(p2.x);
1268 p2.x = mpi_copy(point->x);
1269 mpi_set_ui(p2.z, 1);
1270
1271 point_resize(&p1, ctx);
1272 point_resize(&p2, ctx);
1273 point_resize(&p1_, ctx);
1274 point_resize(&p2_, ctx);
1275
1276 mpi_resize(point->x, ctx->p->nlimbs);
1277 point->x->nlimbs = ctx->p->nlimbs;
1278
1279 q1 = &p1;
1280 q2 = &p2;
1281 prd = &p1_;
1282 sum = &p2_;
1283
1284 for (j = nbits-1; j >= 0; j--) {
1285 MPI_POINT t;
1286
1287 sw = mpi_test_bit(scalar, j);
1288 point_swap_cond(q1, q2, sw, ctx);
1289 montgomery_ladder(prd, sum, q1, q2, point->x, ctx);
1290 point_swap_cond(prd, sum, sw, ctx);
1291 t = q1; q1 = prd; prd = t;
1292 t = q2; q2 = sum; sum = t;
1293 }
1294
1295 mpi_clear(result->y);
1296 sw = (nbits & 1);
1297 point_swap_cond(&p1, &p1_, sw, ctx);
1298
1299 rsize = p1.z->nlimbs;
1300 MPN_NORMALIZE(p1.z->d, rsize);
1301 if (rsize == 0) {
1302 mpi_set_ui(result->x, 1);
1303 mpi_set_ui(result->z, 0);
1304 } else {
1305 z1 = mpi_new(0);
1306 ec_invm(z1, p1.z, ctx);
1307 ec_mulm(result->x, p1.x, z1, ctx);
1308 mpi_set_ui(result->z, 1);
1309 mpi_free(z1);
1310 }
1311
1312 point_free(&p1);
1313 point_free(&p2);
1314 point_free(&p1_);
1315 point_free(&p2_);
1316 return;
1317 }
1318
1319 x1 = mpi_alloc_like(ctx->p);
1320 y1 = mpi_alloc_like(ctx->p);
1321 h = mpi_alloc_like(ctx->p);
1322 k = mpi_copy(scalar);
1323 yy = mpi_copy(point->y);
1324
1325 if (mpi_has_sign(k)) {
1326 k->sign = 0;
1327 ec_invm(yy, yy, ctx);
1328 }
1329
1330 if (!mpi_cmp_ui(point->z, 1)) {
1331 mpi_set(x1, point->x);
1332 mpi_set(y1, yy);
1333 } else {
1334 MPI z2, z3;
1335
1336 z2 = mpi_alloc_like(ctx->p);
1337 z3 = mpi_alloc_like(ctx->p);
1338 ec_mulm(z2, point->z, point->z, ctx);
1339 ec_mulm(z3, point->z, z2, ctx);
1340 ec_invm(z2, z2, ctx);
1341 ec_mulm(x1, point->x, z2, ctx);
1342 ec_invm(z3, z3, ctx);
1343 ec_mulm(y1, yy, z3, ctx);
1344 mpi_free(z2);
1345 mpi_free(z3);
1346 }
1347 z1 = mpi_copy(mpi_const(MPI_C_ONE));
1348
1349 mpi_mul(h, k, mpi_const(MPI_C_THREE));
1350 loops = mpi_get_nbits(h);
1351 if (loops < 2) {
1352
1353
1354
1355
1356 loops = 2;
1357 mpi_clear(result->x);
1358 mpi_clear(result->y);
1359 mpi_clear(result->z);
1360 } else {
1361 mpi_set(result->x, point->x);
1362 mpi_set(result->y, yy);
1363 mpi_set(result->z, point->z);
1364 }
1365 mpi_free(yy); yy = NULL;
1366
1367 p1.x = x1; x1 = NULL;
1368 p1.y = y1; y1 = NULL;
1369 p1.z = z1; z1 = NULL;
1370 point_init(&p2);
1371 point_init(&p1inv);
1372
1373
1374 point_set(&p1inv, &p1);
1375 ec_subm(p1inv.y, ctx->p, p1inv.y, ctx);
1376
1377 for (i = loops-2; i > 0; i--) {
1378 mpi_ec_dup_point(result, result, ctx);
1379 if (mpi_test_bit(h, i) == 1 && mpi_test_bit(k, i) == 0) {
1380 point_set(&p2, result);
1381 mpi_ec_add_points(result, &p2, &p1, ctx);
1382 }
1383 if (mpi_test_bit(h, i) == 0 && mpi_test_bit(k, i) == 1) {
1384 point_set(&p2, result);
1385 mpi_ec_add_points(result, &p2, &p1inv, ctx);
1386 }
1387 }
1388
1389 point_free(&p1);
1390 point_free(&p2);
1391 point_free(&p1inv);
1392 mpi_free(h);
1393 mpi_free(k);
1394 }
1395 EXPORT_SYMBOL_GPL(mpi_ec_mul_point);
1396
1397
1398 int mpi_ec_curve_point(MPI_POINT point, struct mpi_ec_ctx *ctx)
1399 {
1400 int res = 0;
1401 MPI x, y, w;
1402
1403 x = mpi_new(0);
1404 y = mpi_new(0);
1405 w = mpi_new(0);
1406
1407
1408
1409
1410 if (mpi_cmpabs(point->x, ctx->p) >= 0)
1411 goto leave;
1412 if (mpi_cmpabs(point->y, ctx->p) >= 0)
1413 goto leave;
1414 if (mpi_cmpabs(point->z, ctx->p) >= 0)
1415 goto leave;
1416
1417 switch (ctx->model) {
1418 case MPI_EC_WEIERSTRASS:
1419 {
1420 MPI xxx;
1421
1422 if (mpi_ec_get_affine(x, y, point, ctx))
1423 goto leave;
1424
1425 xxx = mpi_new(0);
1426
1427
1428 ec_pow2(y, y, ctx);
1429
1430 ec_pow3(xxx, x, ctx);
1431 ec_mulm(w, ctx->a, x, ctx);
1432 ec_addm(w, w, ctx->b, ctx);
1433 ec_addm(w, w, xxx, ctx);
1434
1435 if (!mpi_cmp(y, w))
1436 res = 1;
1437
1438 mpi_free(xxx);
1439 }
1440 break;
1441
1442 case MPI_EC_MONTGOMERY:
1443 {
1444 #define xx y
1445
1446 if (mpi_ec_get_affine(x, NULL, point, ctx))
1447 goto leave;
1448
1449
1450
1451
1452
1453
1454 ec_mulm(w, ctx->a, mpi_const(MPI_C_FOUR), ctx);
1455 ec_addm(w, w, mpi_const(MPI_C_TWO), ctx);
1456 ec_mulm(w, w, x, ctx);
1457 ec_pow2(xx, x, ctx);
1458 ec_addm(w, w, xx, ctx);
1459 ec_addm(w, w, mpi_const(MPI_C_ONE), ctx);
1460 ec_mulm(w, w, x, ctx);
1461 ec_mulm(w, w, ctx->b, ctx);
1462 #undef xx
1463
1464 #define p_minus1 y
1465 ec_subm(p_minus1, ctx->p, mpi_const(MPI_C_ONE), ctx);
1466 mpi_rshift(p_minus1, p_minus1, 1);
1467 ec_powm(w, w, p_minus1, ctx);
1468
1469 res = !mpi_cmp_ui(w, 1);
1470 #undef p_minus1
1471 }
1472 break;
1473
1474 case MPI_EC_EDWARDS:
1475 {
1476 if (mpi_ec_get_affine(x, y, point, ctx))
1477 goto leave;
1478
1479 mpi_resize(w, ctx->p->nlimbs);
1480 w->nlimbs = ctx->p->nlimbs;
1481
1482
1483 ctx->pow2(x, x, ctx);
1484 ctx->pow2(y, y, ctx);
1485 if (ctx->dialect == ECC_DIALECT_ED25519)
1486 ctx->subm(w, ctx->p, x, ctx);
1487 else
1488 ctx->mulm(w, ctx->a, x, ctx);
1489 ctx->addm(w, w, y, ctx);
1490 ctx->mulm(x, x, y, ctx);
1491 ctx->mulm(x, x, ctx->b, ctx);
1492 ctx->subm(w, w, x, ctx);
1493 if (!mpi_cmp_ui(w, 1))
1494 res = 1;
1495 }
1496 break;
1497 }
1498
1499 leave:
1500 mpi_free(w);
1501 mpi_free(x);
1502 mpi_free(y);
1503
1504 return res;
1505 }
1506 EXPORT_SYMBOL_GPL(mpi_ec_curve_point);