1 /* 2 * Copyright (C) 2017 - This file is part of libecc project 3 * 4 * Authors: 5 * Ryad BENADJILA <ryadbenadjila@gmail.com> 6 * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr> 7 * Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr> 8 * 9 * Contributors: 10 * Nicolas VIVET <nicolas.vivet@ssi.gouv.fr> 11 * Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr> 12 * 13 * This software is licensed under a dual BSD and GPL v2 license. 14 * See LICENSE file at the root folder of the project. 15 */ 16 #include <libecc/curves/ec_shortw.h> 17 #include <libecc/curves/prj_pt.h> 18 #include <libecc/nn/nn_logical.h> 19 #include <libecc/nn/nn_add.h> 20 #include <libecc/nn/nn_rand.h> 21 #include <libecc/fp/fp_add.h> 22 #include <libecc/fp/fp_mul.h> 23 #include <libecc/fp/fp_montgomery.h> 24 #include <libecc/fp/fp_rand.h> 25 26 #define PRJ_PT_MAGIC ((word_t)(0xe1cd70babb1d5afeULL)) 27 28 /* 29 * Check given projective point has been correctly initialized (using 30 * prj_pt_init()). Returns 0 on success, -1 on error. 31 */ 32 int prj_pt_check_initialized(prj_pt_src_t in) 33 { 34 int ret; 35 36 MUST_HAVE(((in != NULL) && (in->magic == PRJ_PT_MAGIC)), ret, err); 37 ret = ec_shortw_crv_check_initialized(in->crv); 38 39 err: 40 return ret; 41 } 42 43 /* 44 * Initialize the projective point structure on given curve as the point at 45 * infinity. The function returns 0 on success, -1 on error. 46 */ 47 int prj_pt_init(prj_pt_t in, ec_shortw_crv_src_t curve) 48 { 49 int ret; 50 51 ret = ec_shortw_crv_check_initialized(curve); EG(ret, err); 52 53 MUST_HAVE((in != NULL), ret, err); 54 55 ret = fp_init(&(in->X), curve->a.ctx); EG(ret, err); 56 ret = fp_init(&(in->Y), curve->a.ctx); EG(ret, err); 57 ret = fp_init(&(in->Z), curve->a.ctx); EG(ret, err); 58 in->crv = curve; 59 in->magic = PRJ_PT_MAGIC; 60 61 err: 62 return ret; 63 } 64 65 /* 66 * Initialize the projective point structure on given curve using given 67 * coordinates. The function returns 0 on success, -1 on error. 68 */ 69 int prj_pt_init_from_coords(prj_pt_t in, 70 ec_shortw_crv_src_t curve, 71 fp_src_t xcoord, fp_src_t ycoord, fp_src_t zcoord) 72 { 73 int ret; 74 75 ret = prj_pt_init(in, curve); EG(ret, err); 76 ret = fp_copy(&(in->X), xcoord); EG(ret, err); 77 ret = fp_copy(&(in->Y), ycoord); EG(ret, err); 78 ret = fp_copy(&(in->Z), zcoord); 79 80 err: 81 return ret; 82 } 83 84 /* 85 * Uninit given projective point structure. The function returns 0 on success, 86 * -1 on error. This is an error if passed point has not already been 87 * initialized first. 88 */ 89 void prj_pt_uninit(prj_pt_t in) 90 { 91 if((in != NULL) && (in->magic == PRJ_PT_MAGIC) && (in->crv != NULL)){ 92 in->crv = NULL; 93 in->magic = WORD(0); 94 95 fp_uninit(&(in->X)); 96 fp_uninit(&(in->Y)); 97 fp_uninit(&(in->Z)); 98 } 99 100 return; 101 } 102 103 /* 104 * Checks if projective point is the point at infinity (last coordinate is 0). 105 * In that case, 'iszero' out parameter is set to 1. It is set to 0 if the 106 * point is not the point at infinity. The function returns 0 on success, -1 on 107 * error. On error, 'iszero' is not meaningful. 108 */ 109 int prj_pt_iszero(prj_pt_src_t in, int *iszero) 110 { 111 int ret; 112 113 ret = prj_pt_check_initialized(in); EG(ret, err); 114 ret = fp_iszero(&(in->Z), iszero); 115 116 err: 117 return ret; 118 } 119 120 /* 121 * Set given projective point 'out' to the point at infinity. The functions 122 * returns 0 on success, -1 on error. 123 */ 124 int prj_pt_zero(prj_pt_t out) 125 { 126 int ret; 127 128 ret = prj_pt_check_initialized(out); EG(ret, err); 129 130 ret = fp_zero(&(out->X)); EG(ret, err); 131 ret = fp_one(&(out->Y)); EG(ret, err); 132 ret = fp_zero(&(out->Z)); 133 134 err: 135 return ret; 136 } 137 138 /* 139 * Check if a projective point is indeed on its curve. The function sets 140 * 'on_curve' out parameter to 1 if the point is on the curve, 0 if not. 141 * The function returns 0 on success, -1 on error. 'on_curve' is not 142 * meaningful on error. 143 */ 144 int prj_pt_is_on_curve(prj_pt_src_t in, int *on_curve) 145 { 146 int ret, cmp; 147 148 /* In order to check that we are on the curve, we 149 * use the projective formula of the curve: 150 * 151 * Y**2 * Z = X**3 + a * X * Z**2 + b * Z**3 152 * 153 */ 154 fp X, Y, Z; 155 X.magic = Y.magic = Z.magic = WORD(0); 156 157 ret = prj_pt_check_initialized(in); EG(ret, err); 158 ret = ec_shortw_crv_check_initialized(in->crv); EG(ret, err); 159 MUST_HAVE((on_curve != NULL), ret, err); 160 161 ret = fp_init(&X, in->X.ctx); EG(ret, err); 162 ret = fp_init(&Y, in->X.ctx); EG(ret, err); 163 ret = fp_init(&Z, in->X.ctx); EG(ret, err); 164 165 /* Compute X**3 + a * X * Z**2 + b * Z**3 on one side */ 166 ret = fp_sqr(&X, &(in->X)); EG(ret, err); 167 ret = fp_mul(&X, &X, &(in->X)); EG(ret, err); 168 ret = fp_mul(&Z, &(in->X), &(in->crv->a)); EG(ret, err); 169 ret = fp_mul(&Y, &(in->crv->b), &(in->Z)); EG(ret, err); 170 ret = fp_add(&Z, &Z, &Y); EG(ret, err); 171 ret = fp_mul(&Z, &Z, &(in->Z)); EG(ret, err); 172 ret = fp_mul(&Z, &Z, &(in->Z)); EG(ret, err); 173 ret = fp_add(&X, &X, &Z); EG(ret, err); 174 175 /* Compute Y**2 * Z on the other side */ 176 ret = fp_sqr(&Y, &(in->Y)); EG(ret, err); 177 ret = fp_mul(&Y, &Y, &(in->Z)); EG(ret, err); 178 179 /* Compare the two values */ 180 ret = fp_cmp(&X, &Y, &cmp); EG(ret, err); 181 182 (*on_curve) = (!cmp); 183 184 err: 185 fp_uninit(&X); 186 fp_uninit(&Y); 187 fp_uninit(&Z); 188 189 return ret; 190 } 191 192 /* 193 * The function copies 'in' projective point to 'out'. 'out' is initialized by 194 * the function. The function returns 0 on sucess, -1 on error. 195 */ 196 int prj_pt_copy(prj_pt_t out, prj_pt_src_t in) 197 { 198 int ret; 199 200 ret = prj_pt_check_initialized(in); EG(ret, err); 201 202 ret = prj_pt_init(out, in->crv); EG(ret, err); 203 204 ret = fp_copy(&(out->X), &(in->X)); EG(ret, err); 205 ret = fp_copy(&(out->Y), &(in->Y)); EG(ret, err); 206 ret = fp_copy(&(out->Z), &(in->Z)); 207 208 err: 209 return ret; 210 } 211 212 /* 213 * Convert given projective point 'in' to affine representation in 'out'. 'out' 214 * is initialized by the function. The function returns 0 on success, -1 on 215 * error. Passing the point at infinty to the function is considered as an 216 * error. 217 */ 218 int prj_pt_to_aff(aff_pt_t out, prj_pt_src_t in) 219 { 220 int ret, iszero; 221 222 ret = prj_pt_check_initialized(in); EG(ret, err); 223 224 ret = prj_pt_iszero(in, &iszero); EG(ret, err); 225 MUST_HAVE((!iszero), ret, err); 226 227 ret = aff_pt_init(out, in->crv); EG(ret, err); 228 229 ret = fp_inv(&(out->x), &(in->Z)); EG(ret, err); 230 ret = fp_mul(&(out->y), &(in->Y), &(out->x)); EG(ret, err); 231 ret = fp_mul(&(out->x), &(in->X), &(out->x)); 232 233 err: 234 return ret; 235 } 236 237 /* 238 * Get the unique Z = 1 projective point representation ("equivalent" to affine 239 * point). The function returns 0 on success, -1 on error. 240 */ 241 int prj_pt_unique(prj_pt_t out, prj_pt_src_t in) 242 { 243 int ret, iszero; 244 245 ret = prj_pt_check_initialized(in); EG(ret, err); 246 ret = prj_pt_iszero(in, &iszero); EG(ret, err); 247 MUST_HAVE((!iszero), ret, err); 248 249 if(out == in){ 250 /* Aliasing case */ 251 fp tmp; 252 tmp.magic = WORD(0); 253 254 ret = fp_init(&tmp, (in->Z).ctx); EG(ret, err); 255 ret = fp_inv(&tmp, &(in->Z)); EG(ret, err1); 256 ret = fp_mul(&(out->Y), &(in->Y), &tmp); EG(ret, err1); 257 ret = fp_mul(&(out->X), &(in->X), &tmp); EG(ret, err1); 258 ret = fp_one(&(out->Z)); EG(ret, err1); 259 err1: 260 fp_uninit(&tmp); EG(ret, err); 261 } 262 else{ 263 ret = prj_pt_init(out, in->crv); EG(ret, err); 264 ret = fp_inv(&(out->X), &(in->Z)); EG(ret, err); 265 ret = fp_mul(&(out->Y), &(in->Y), &(out->X)); EG(ret, err); 266 ret = fp_mul(&(out->X), &(in->X), &(out->X)); EG(ret, err); 267 ret = fp_one(&(out->Z)); EG(ret, err); 268 } 269 270 271 err: 272 return ret; 273 } 274 275 /* 276 * Converts affine point 'in' to projective representation in 'out'. 'out' is 277 * initialized by the function. The function returns 0 on success, -1 on error. 278 */ 279 int ec_shortw_aff_to_prj(prj_pt_t out, aff_pt_src_t in) 280 { 281 int ret, on_curve; 282 283 ret = aff_pt_check_initialized(in); EG(ret, err); 284 285 /* The input affine point must be on the curve */ 286 ret = aff_pt_is_on_curve(in, &on_curve); EG(ret, err); 287 MUST_HAVE(on_curve, ret, err); 288 289 ret = prj_pt_init(out, in->crv); EG(ret, err); 290 ret = fp_copy(&(out->X), &(in->x)); EG(ret, err); 291 ret = fp_copy(&(out->Y), &(in->y)); EG(ret, err); 292 ret = nn_one(&(out->Z).fp_val); /* Z = 1 */ 293 294 err: 295 return ret; 296 } 297 298 /* 299 * Compare projective points 'in1' and 'in2'. On success, 'cmp' is set to 300 * the result of the comparison (0 if in1 == in2, !0 if in1 != in2). The 301 * function returns 0 on success, -1 on error. 302 */ 303 int prj_pt_cmp(prj_pt_src_t in1, prj_pt_src_t in2, int *cmp) 304 { 305 fp X1, X2, Y1, Y2; 306 int ret, x_cmp, y_cmp; 307 X1.magic = X2.magic = Y1.magic = Y2.magic = WORD(0); 308 309 MUST_HAVE((cmp != NULL), ret, err); 310 ret = prj_pt_check_initialized(in1); EG(ret, err); 311 ret = prj_pt_check_initialized(in2); EG(ret, err); 312 313 MUST_HAVE((in1->crv == in2->crv), ret, err); 314 315 ret = fp_init(&X1, (in1->X).ctx); EG(ret, err); 316 ret = fp_init(&X2, (in2->X).ctx); EG(ret, err); 317 ret = fp_init(&Y1, (in1->Y).ctx); EG(ret, err); 318 ret = fp_init(&Y2, (in2->Y).ctx); EG(ret, err); 319 320 /* 321 * Montgomery multiplication is used as it is faster than 322 * usual multiplication and the spurious multiplicative 323 * factor does not matter. 324 */ 325 ret = fp_mul_monty(&X1, &(in1->X), &(in2->Z)); EG(ret, err); 326 ret = fp_mul_monty(&X2, &(in2->X), &(in1->Z)); EG(ret, err); 327 ret = fp_mul_monty(&Y1, &(in1->Y), &(in2->Z)); EG(ret, err); 328 ret = fp_mul_monty(&Y2, &(in2->Y), &(in1->Z)); EG(ret, err); 329 330 ret = fp_mul_monty(&X1, &(in1->X), &(in2->Z)); EG(ret, err); 331 ret = fp_mul_monty(&X2, &(in2->X), &(in1->Z)); EG(ret, err); 332 ret = fp_mul_monty(&Y1, &(in1->Y), &(in2->Z)); EG(ret, err); 333 ret = fp_mul_monty(&Y2, &(in2->Y), &(in1->Z)); EG(ret, err); 334 ret = fp_cmp(&X1, &X2, &x_cmp); EG(ret, err); 335 ret = fp_cmp(&Y1, &Y2, &y_cmp); 336 337 if (!ret) { 338 (*cmp) = (x_cmp | y_cmp); 339 } 340 341 err: 342 fp_uninit(&Y2); 343 fp_uninit(&Y1); 344 fp_uninit(&X2); 345 fp_uninit(&X1); 346 347 return ret; 348 } 349 350 /* 351 * NOTE: this internal functions assumes that upper layer have checked that in1 and in2 352 * are initialized, and that cmp is not NULL. 353 */ 354 ATTRIBUTE_WARN_UNUSED_RET static inline int _prj_pt_eq_or_opp_X(prj_pt_src_t in1, prj_pt_src_t in2, int *cmp) 355 { 356 int ret; 357 fp X1, X2; 358 X1.magic = X2.magic = WORD(0); 359 360 /* 361 * Montgomery multiplication is used as it is faster than 362 * usual multiplication and the spurious multiplicative 363 * factor does not matter. 364 */ 365 ret = fp_init(&X1, (in1->X).ctx); EG(ret, err); 366 ret = fp_init(&X2, (in2->X).ctx); EG(ret, err); 367 ret = fp_mul_monty(&X1, &(in1->X), &(in2->Z)); EG(ret, err); 368 ret = fp_mul_monty(&X2, &(in2->X), &(in1->Z)); EG(ret, err); 369 ret = fp_cmp(&X1, &X2, cmp); 370 371 err: 372 fp_uninit(&X1); 373 fp_uninit(&X2); 374 375 return ret; 376 } 377 378 /* 379 * NOTE: this internal functions assumes that upper layer have checked that in1 and in2 380 * are initialized, and that eq_or_opp is not NULL. 381 */ 382 ATTRIBUTE_WARN_UNUSED_RET static inline int _prj_pt_eq_or_opp_Y(prj_pt_src_t in1, prj_pt_src_t in2, int *eq_or_opp) 383 { 384 int ret; 385 fp Y1, Y2; 386 Y1.magic = Y2.magic = WORD(0); 387 388 /* 389 * Montgomery multiplication is used as it is faster than 390 * usual multiplication and the spurious multiplicative 391 * factor does not matter. 392 */ 393 ret = fp_init(&Y1, (in1->Y).ctx); EG(ret, err); 394 ret = fp_init(&Y2, (in2->Y).ctx); EG(ret, err); 395 ret = fp_mul_monty(&Y1, &(in1->Y), &(in2->Z)); EG(ret, err); 396 ret = fp_mul_monty(&Y2, &(in2->Y), &(in1->Z)); EG(ret, err); 397 ret = fp_eq_or_opp(&Y1, &Y2, eq_or_opp); 398 399 err: 400 fp_uninit(&Y1); 401 fp_uninit(&Y2); 402 403 return ret; 404 } 405 406 /* 407 * The functions tests if given projective points 'in1' and 'in2' are equal or 408 * opposite. On success, the result of the comparison is given via 'eq_or_opp' 409 * out parameter (1 if equal or opposite, 0 otherwise). The function returns 410 * 0 on succes, -1 on error. 411 */ 412 int prj_pt_eq_or_opp(prj_pt_src_t in1, prj_pt_src_t in2, int *eq_or_opp) 413 { 414 int ret, cmp, _eq_or_opp; 415 416 ret = prj_pt_check_initialized(in1); EG(ret, err); 417 ret = prj_pt_check_initialized(in2); EG(ret, err); 418 MUST_HAVE((in1->crv == in2->crv), ret, err); 419 MUST_HAVE((eq_or_opp != NULL), ret, err); 420 421 ret = _prj_pt_eq_or_opp_X(in1, in2, &cmp); EG(ret, err); 422 ret = _prj_pt_eq_or_opp_Y(in1, in2, &_eq_or_opp); 423 424 if (!ret) { 425 (*eq_or_opp) = ((cmp == 0) & _eq_or_opp); 426 } 427 428 err: 429 return ret; 430 } 431 432 /* Compute the opposite of a projective point. Supports aliasing. 433 * Returns 0 on success, -1 on failure. 434 */ 435 int prj_pt_neg(prj_pt_t out, prj_pt_src_t in) 436 { 437 int ret; 438 439 ret = prj_pt_check_initialized(in); EG(ret, err); 440 441 if (out != in) { /* Copy point if not aliased */ 442 ret = prj_pt_init(out, in->crv); EG(ret, err); 443 ret = prj_pt_copy(out, in); EG(ret, err); 444 } 445 446 /* Then, negate Y */ 447 ret = fp_neg(&(out->Y), &(out->Y)); 448 449 err: 450 return ret; 451 } 452 453 /* 454 * Import a projective point from a buffer with the following layout; the 3 455 * coordinates (elements of Fp) are each encoded on p_len bytes, where p_len 456 * is the size of p in bytes (e.g. 66 for a prime p of 521 bits). Each 457 * coordinate is encoded in big endian. Size of buffer must exactly match 458 * 3 * p_len. The projective point is initialized by the function. 459 * 460 * The function returns 0 on success, -1 on error. 461 */ 462 int prj_pt_import_from_buf(prj_pt_t pt, 463 const u8 *pt_buf, 464 u16 pt_buf_len, ec_shortw_crv_src_t crv) 465 { 466 int on_curve, ret; 467 fp_ctx_src_t ctx; 468 u16 coord_len; 469 470 ret = ec_shortw_crv_check_initialized(crv); EG(ret, err); 471 MUST_HAVE((pt_buf != NULL) && (pt != NULL), ret, err); 472 473 ctx = crv->a.ctx; 474 coord_len = (u16)BYTECEIL(ctx->p_bitlen); 475 MUST_HAVE((pt_buf_len == (3 * coord_len)), ret, err); 476 477 ret = fp_init_from_buf(&(pt->X), ctx, pt_buf, coord_len); EG(ret, err); 478 ret = fp_init_from_buf(&(pt->Y), ctx, pt_buf + coord_len, coord_len); EG(ret, err); 479 ret = fp_init_from_buf(&(pt->Z), ctx, pt_buf + (2 * coord_len), coord_len); EG(ret, err); 480 481 /* Set the curve */ 482 pt->crv = crv; 483 484 /* Mark the point as initialized */ 485 pt->magic = PRJ_PT_MAGIC; 486 487 /* Check that the point is indeed on the provided curve, uninitialize it 488 * if this is not the case. 489 */ 490 ret = prj_pt_is_on_curve(pt, &on_curve); EG(ret, err); 491 if (!on_curve){ 492 prj_pt_uninit(pt); 493 ret = -1; 494 } 495 496 err: 497 PTR_NULLIFY(ctx); 498 499 return ret; 500 } 501 502 /* 503 * Import a projective point from an affine point buffer with the following layout; the 2 504 * coordinates (elements of Fp) are each encoded on p_len bytes, where p_len 505 * is the size of p in bytes (e.g. 66 for a prime p of 521 bits). Each 506 * coordinate is encoded in big endian. Size of buffer must exactly match 507 * 2 * p_len. The projective point is initialized by the function. 508 * 509 * The function returns 0 on success, -1 on error. 510 */ 511 int prj_pt_import_from_aff_buf(prj_pt_t pt, 512 const u8 *pt_buf, 513 u16 pt_buf_len, ec_shortw_crv_src_t crv) 514 { 515 int ret, on_curve; 516 fp_ctx_src_t ctx; 517 u16 coord_len; 518 519 ret = ec_shortw_crv_check_initialized(crv); EG(ret, err); 520 MUST_HAVE((pt_buf != NULL) && (pt != NULL), ret, err); 521 522 ctx = crv->a.ctx; 523 coord_len = (u16)BYTECEIL(ctx->p_bitlen); 524 MUST_HAVE((pt_buf_len == (2 * coord_len)), ret, err); 525 526 ret = fp_init_from_buf(&(pt->X), ctx, pt_buf, coord_len); EG(ret, err); 527 ret = fp_init_from_buf(&(pt->Y), ctx, pt_buf + coord_len, coord_len); EG(ret, err); 528 /* Z coordinate is set to 1 */ 529 ret = fp_init(&(pt->Z), ctx); EG(ret, err); 530 ret = fp_one(&(pt->Z)); EG(ret, err); 531 532 /* Set the curve */ 533 pt->crv = crv; 534 535 /* Mark the point as initialized */ 536 pt->magic = PRJ_PT_MAGIC; 537 538 /* Check that the point is indeed on the provided curve, uninitialize it 539 * if this is not the case. 540 */ 541 ret = prj_pt_is_on_curve(pt, &on_curve); EG(ret, err); 542 if (!on_curve){ 543 prj_pt_uninit(pt); 544 ret = -1; 545 } 546 547 err: 548 PTR_NULLIFY(ctx); 549 550 return ret; 551 } 552 553 554 /* Export a projective point to a buffer with the following layout; the 3 555 * coordinates (elements of Fp) are each encoded on p_len bytes, where p_len 556 * is the size of p in bytes (e.g. 66 for a prime p of 521 bits). Each 557 * coordinate is encoded in big endian. Size of buffer must exactly match 558 * 3 * p_len. 559 * 560 * The function returns 0 on success, -1 on error. 561 */ 562 int prj_pt_export_to_buf(prj_pt_src_t pt, u8 *pt_buf, u32 pt_buf_len) 563 { 564 fp_ctx_src_t ctx; 565 u16 coord_len; 566 int ret, on_curve; 567 568 ret = prj_pt_check_initialized(pt); EG(ret, err); 569 570 MUST_HAVE((pt_buf != NULL), ret, err); 571 572 /* The point to be exported must be on the curve */ 573 ret = prj_pt_is_on_curve(pt, &on_curve); EG(ret, err); 574 MUST_HAVE((on_curve), ret, err); 575 576 ctx = pt->crv->a.ctx; 577 coord_len = (u16)BYTECEIL(ctx->p_bitlen); 578 MUST_HAVE((pt_buf_len == (3 * coord_len)), ret, err); 579 580 /* Export the three coordinates */ 581 ret = fp_export_to_buf(pt_buf, coord_len, &(pt->X)); EG(ret, err); 582 ret = fp_export_to_buf(pt_buf + coord_len, coord_len, &(pt->Y)); EG(ret, err); 583 ret = fp_export_to_buf(pt_buf + (2 * coord_len), coord_len, &(pt->Z)); 584 585 err: 586 PTR_NULLIFY(ctx); 587 588 return ret; 589 } 590 591 /* 592 * Export a projective point to an affine point buffer with the following 593 * layout; the 2 coordinates (elements of Fp) are each encoded on p_len bytes, 594 * where p_len is the size of p in bytes (e.g. 66 for a prime p of 521 bits). 595 * Each coordinate is encoded in big endian. Size of buffer must exactly match 596 * 2 * p_len. 597 * 598 * The function returns 0 on success, -1 on error. 599 */ 600 int prj_pt_export_to_aff_buf(prj_pt_src_t pt, u8 *pt_buf, u32 pt_buf_len) 601 { 602 int ret, on_curve; 603 aff_pt tmp_aff; 604 tmp_aff.magic = WORD(0); 605 606 ret = prj_pt_check_initialized(pt); EG(ret, err); 607 608 MUST_HAVE((pt_buf != NULL), ret, err); 609 610 /* The point to be exported must be on the curve */ 611 ret = prj_pt_is_on_curve(pt, &on_curve); EG(ret, err); 612 MUST_HAVE((on_curve), ret, err); 613 614 /* Move to the affine unique representation */ 615 ret = prj_pt_to_aff(&tmp_aff, pt); EG(ret, err); 616 617 /* Export the affine point to the buffer */ 618 ret = aff_pt_export_to_buf(&tmp_aff, pt_buf, pt_buf_len); 619 620 err: 621 aff_pt_uninit(&tmp_aff); 622 623 return ret; 624 } 625 626 627 #ifdef NO_USE_COMPLETE_FORMULAS 628 629 /* 630 * The function is an internal one: no check is performed on parameters, 631 * this MUST be done by the caller: 632 * 633 * - in is initialized 634 * - in and out must not be aliased 635 * 636 * The function will initialize 'out'. The function returns 0 on success, -1 637 * on error. 638 */ 639 ATTRIBUTE_WARN_UNUSED_RET static int __prj_pt_dbl_monty_no_cf(prj_pt_t out, prj_pt_src_t in) 640 { 641 fp XX, ZZ, w, s, ss, sss, R, RR, B, h; 642 int ret; 643 XX.magic = ZZ.magic = w.magic = s.magic = WORD(0); 644 ss.magic = sss.magic = R.magic = WORD(0); 645 RR.magic = B.magic = h.magic = WORD(0); 646 647 ret = prj_pt_init(out, in->crv); EG(ret, err); 648 649 ret = fp_init(&XX, out->crv->a.ctx); EG(ret, err); 650 ret = fp_init(&ZZ, out->crv->a.ctx); EG(ret, err); 651 ret = fp_init(&w, out->crv->a.ctx); EG(ret, err); 652 ret = fp_init(&s, out->crv->a.ctx); EG(ret, err); 653 ret = fp_init(&ss, out->crv->a.ctx); EG(ret, err); 654 ret = fp_init(&sss, out->crv->a.ctx); EG(ret, err); 655 ret = fp_init(&R, out->crv->a.ctx); EG(ret, err); 656 ret = fp_init(&RR, out->crv->a.ctx); EG(ret, err); 657 ret = fp_init(&B, out->crv->a.ctx); EG(ret, err); 658 ret = fp_init(&h, out->crv->a.ctx); EG(ret, err); 659 660 /* XX = X1² */ 661 ret = fp_sqr_monty(&XX, &(in->X)); EG(ret, err); 662 663 /* ZZ = Z1² */ 664 ret = fp_sqr_monty(&ZZ, &(in->Z)); EG(ret, err); 665 666 /* w = a*ZZ+3*XX */ 667 ret = fp_mul_monty(&w, &(in->crv->a_monty), &ZZ); EG(ret, err); 668 ret = fp_add_monty(&w, &w, &XX); EG(ret, err); 669 ret = fp_add_monty(&w, &w, &XX); EG(ret, err); 670 ret = fp_add_monty(&w, &w, &XX); EG(ret, err); 671 672 /* s = 2*Y1*Z1 */ 673 ret = fp_mul_monty(&s, &(in->Y), &(in->Z)); EG(ret, err); 674 ret = fp_add_monty(&s, &s, &s); EG(ret, err); 675 676 /* ss = s² */ 677 ret = fp_sqr_monty(&ss, &s); EG(ret, err); 678 679 /* sss = s*ss */ 680 ret = fp_mul_monty(&sss, &s, &ss); EG(ret, err); 681 682 /* R = Y1*s */ 683 ret = fp_mul_monty(&R, &(in->Y), &s); EG(ret, err); 684 685 /* RR = R² */ 686 ret = fp_sqr_monty(&RR, &R); EG(ret, err); 687 688 /* B = (X1+R)²-XX-RR */ 689 ret = fp_add_monty(&R, &R, &(in->X)); EG(ret, err); 690 ret = fp_sqr_monty(&B, &R); EG(ret, err); 691 ret = fp_sub_monty(&B, &B, &XX); EG(ret, err); 692 ret = fp_sub_monty(&B, &B, &RR); EG(ret, err); 693 694 /* h = w²-2*B */ 695 ret = fp_sqr_monty(&h, &w); EG(ret, err); 696 ret = fp_sub_monty(&h, &h, &B); EG(ret, err); 697 ret = fp_sub_monty(&h, &h, &B); EG(ret, err); 698 699 /* X3 = h*s */ 700 ret = fp_mul_monty(&(out->X), &h, &s); EG(ret, err); 701 702 /* Y3 = w*(B-h)-2*RR */ 703 ret = fp_sub_monty(&B, &B, &h); EG(ret, err); 704 ret = fp_mul_monty(&(out->Y), &w, &B); EG(ret, err); 705 ret = fp_sub_monty(&(out->Y), &(out->Y), &RR); EG(ret, err); 706 ret = fp_sub_monty(&(out->Y), &(out->Y), &RR); EG(ret, err); 707 708 /* Z3 = sss */ 709 ret = fp_copy(&(out->Z), &sss); 710 711 err: 712 fp_uninit(&XX); 713 fp_uninit(&ZZ); 714 fp_uninit(&w); 715 fp_uninit(&s); 716 fp_uninit(&ss); 717 fp_uninit(&sss); 718 fp_uninit(&R); 719 fp_uninit(&RR); 720 fp_uninit(&B); 721 fp_uninit(&h); 722 723 return ret; 724 } 725 726 /* 727 * The function is an internal one: no check is performed on parameters, 728 * this MUST be done by the caller: 729 * 730 * - in1 and in2 are initialized 731 * - in1 and in2 are on the same curve 732 * - in1/in2 and out must not be aliased 733 * - in1 and in2 must not be equal, opposite or have identical value 734 * 735 * The function will initialize 'out'. The function returns 0 on success, -1 736 * on error. 737 */ 738 ATTRIBUTE_WARN_UNUSED_RET static int ___prj_pt_add_monty_no_cf(prj_pt_t out, 739 prj_pt_src_t in1, 740 prj_pt_src_t in2) 741 { 742 fp Y1Z2, X1Z2, Z1Z2, u, uu, v, vv, vvv, R, A; 743 int ret; 744 Y1Z2.magic = X1Z2.magic = Z1Z2.magic = u.magic = uu.magic = v.magic = WORD(0); 745 vv.magic = vvv.magic = R.magic = A.magic = WORD(0); 746 747 ret = prj_pt_init(out, in1->crv); EG(ret, err); 748 749 ret = fp_init(&Y1Z2, out->crv->a.ctx); EG(ret, err); 750 ret = fp_init(&X1Z2, out->crv->a.ctx); EG(ret, err); 751 ret = fp_init(&Z1Z2, out->crv->a.ctx); EG(ret, err); 752 ret = fp_init(&u, out->crv->a.ctx); EG(ret, err); 753 ret = fp_init(&uu, out->crv->a.ctx); EG(ret, err); 754 ret = fp_init(&v, out->crv->a.ctx); EG(ret, err); 755 ret = fp_init(&vv, out->crv->a.ctx); EG(ret, err); 756 ret = fp_init(&vvv, out->crv->a.ctx); EG(ret, err); 757 ret = fp_init(&R, out->crv->a.ctx); EG(ret, err); 758 ret = fp_init(&A, out->crv->a.ctx); EG(ret, err); 759 760 /* Y1Z2 = Y1*Z2 */ 761 ret = fp_mul_monty(&Y1Z2, &(in1->Y), &(in2->Z)); EG(ret, err); 762 763 /* X1Z2 = X1*Z2 */ 764 ret = fp_mul_monty(&X1Z2, &(in1->X), &(in2->Z)); EG(ret, err); 765 766 /* Z1Z2 = Z1*Z2 */ 767 ret = fp_mul_monty(&Z1Z2, &(in1->Z), &(in2->Z)); EG(ret, err); 768 769 /* u = Y2*Z1-Y1Z2 */ 770 ret = fp_mul_monty(&u, &(in2->Y), &(in1->Z)); EG(ret, err); 771 ret = fp_sub_monty(&u, &u, &Y1Z2); EG(ret, err); 772 773 /* uu = u² */ 774 ret = fp_sqr_monty(&uu, &u); EG(ret, err); 775 776 /* v = X2*Z1-X1Z2 */ 777 ret = fp_mul_monty(&v, &(in2->X), &(in1->Z)); EG(ret, err); 778 ret = fp_sub_monty(&v, &v, &X1Z2); EG(ret, err); 779 780 /* vv = v² */ 781 ret = fp_sqr_monty(&vv, &v); EG(ret, err); 782 783 /* vvv = v*vv */ 784 ret = fp_mul_monty(&vvv, &v, &vv); EG(ret, err); 785 786 /* R = vv*X1Z2 */ 787 ret = fp_mul_monty(&R, &vv, &X1Z2); EG(ret, err); 788 789 /* A = uu*Z1Z2-vvv-2*R */ 790 ret = fp_mul_monty(&A, &uu, &Z1Z2); EG(ret, err); 791 ret = fp_sub_monty(&A, &A, &vvv); EG(ret, err); 792 ret = fp_sub_monty(&A, &A, &R); EG(ret, err); 793 ret = fp_sub_monty(&A, &A, &R); EG(ret, err); 794 795 /* X3 = v*A */ 796 ret = fp_mul_monty(&(out->X), &v, &A); EG(ret, err); 797 798 /* Y3 = u*(R-A)-vvv*Y1Z2 */ 799 ret = fp_sub_monty(&R, &R, &A); EG(ret, err); 800 ret = fp_mul_monty(&(out->Y), &u, &R); EG(ret, err); 801 ret = fp_mul_monty(&R, &vvv, &Y1Z2); EG(ret, err); 802 ret = fp_sub_monty(&(out->Y), &(out->Y), &R); EG(ret, err); 803 804 /* Z3 = vvv*Z1Z2 */ 805 ret = fp_mul_monty(&(out->Z), &vvv, &Z1Z2); 806 807 err: 808 fp_uninit(&Y1Z2); 809 fp_uninit(&X1Z2); 810 fp_uninit(&Z1Z2); 811 fp_uninit(&u); 812 fp_uninit(&uu); 813 fp_uninit(&v); 814 fp_uninit(&vv); 815 fp_uninit(&vvv); 816 fp_uninit(&R); 817 fp_uninit(&A); 818 819 return ret; 820 } 821 822 /* 823 * Public version of the addition w/o complete formulas to handle the case 824 * where the inputs are zero or opposite. Returns 0 on success, -1 on error. 825 */ 826 ATTRIBUTE_WARN_UNUSED_RET static int __prj_pt_add_monty_no_cf(prj_pt_t out, prj_pt_src_t in1, prj_pt_src_t in2) 827 { 828 int ret, iszero, eq_or_opp, cmp; 829 830 ret = prj_pt_check_initialized(in1); EG(ret, err); 831 ret = prj_pt_check_initialized(in2); EG(ret, err); 832 MUST_HAVE((in1->crv == in2->crv), ret, err); 833 834 ret = prj_pt_iszero(in1, &iszero); EG(ret, err); 835 if (iszero) { 836 /* in1 at infinity, output in2 in all cases */ 837 ret = prj_pt_init(out, in2->crv); EG(ret, err); 838 ret = prj_pt_copy(out, in2); EG(ret, err); 839 } else { 840 /* in1 not at infinity, output in2 */ 841 ret = prj_pt_iszero(in2, &iszero); EG(ret, err); 842 if (iszero) { 843 /* in2 at infinity, output in1 */ 844 ret = prj_pt_init(out, in1->crv); EG(ret, err); 845 ret = prj_pt_copy(out, in1); EG(ret, err); 846 } else { 847 /* enither in1, nor in2 at infinity */ 848 849 /* 850 * The following test which guarantees in1 and in2 are not 851 * equal or opposite needs to be rewritten because it 852 * has a *HUGE* impact on perf (ec_self_tests run on 853 * all test vectors takes 24 times as long with this 854 * enabled). The same exists in non monty version. 855 */ 856 ret = prj_pt_eq_or_opp(in1, in2, &eq_or_opp); EG(ret, err); 857 if (eq_or_opp) { 858 /* in1 and in2 are either equal or opposite */ 859 ret = prj_pt_cmp(in1, in2, &cmp); EG(ret, err); 860 if (cmp == 0) { 861 /* in1 == in2 => doubling w/o cf */ 862 ret = __prj_pt_dbl_monty_no_cf(out, in1); EG(ret, err); 863 } else { 864 /* in1 == -in2 => output zero (point at infinity) */ 865 ret = prj_pt_init(out, in1->crv); EG(ret, err); 866 ret = prj_pt_zero(out); EG(ret, err); 867 } 868 } else { 869 /* 870 * in1 and in2 are neither 0, nor equal or 871 * opposite. Use the basic monty addition 872 * implementation w/o complete formulas. 873 */ 874 ret = ___prj_pt_add_monty_no_cf(out, in1, in2); EG(ret, err); 875 } 876 } 877 } 878 879 err: 880 return ret; 881 } 882 883 884 #else /* NO_USE_COMPLETE_FORMULAS */ 885 886 887 /* 888 * If NO_USE_COMPLETE_FORMULAS flag is not defined addition formulas from Algorithm 3 889 * of https://joostrenes.nl/publications/complete.pdf are used, otherwise 890 * http://www.hyperelliptic.org/EFD/g1p/auto-shortw-projective.html#doubling-dbl-2007-bl 891 */ 892 ATTRIBUTE_WARN_UNUSED_RET static int __prj_pt_dbl_monty_cf(prj_pt_t out, prj_pt_src_t in) 893 { 894 fp t0, t1, t2, t3; 895 int ret; 896 t0.magic = t1.magic = t2.magic = t3.magic = WORD(0); 897 898 ret = prj_pt_init(out, in->crv); EG(ret, err); 899 900 ret = fp_init(&t0, out->crv->a.ctx); EG(ret, err); 901 ret = fp_init(&t1, out->crv->a.ctx); EG(ret, err); 902 ret = fp_init(&t2, out->crv->a.ctx); EG(ret, err); 903 ret = fp_init(&t3, out->crv->a.ctx); EG(ret, err); 904 905 ret = fp_mul_monty(&t0, &in->X, &in->X); EG(ret, err); 906 ret = fp_mul_monty(&t1, &in->Y, &in->Y); EG(ret, err); 907 ret = fp_mul_monty(&t2, &in->Z, &in->Z); EG(ret, err); 908 ret = fp_mul_monty(&t3, &in->X, &in->Y); EG(ret, err); 909 ret = fp_add_monty(&t3, &t3, &t3); EG(ret, err); 910 911 ret = fp_mul_monty(&out->Z, &in->X, &in->Z); EG(ret, err); 912 ret = fp_add_monty(&out->Z, &out->Z, &out->Z); EG(ret, err); 913 ret = fp_mul_monty(&out->X, &in->crv->a_monty, &out->Z); EG(ret, err); 914 ret = fp_mul_monty(&out->Y, &in->crv->b3_monty, &t2); EG(ret, err); 915 ret = fp_add_monty(&out->Y, &out->X, &out->Y); EG(ret, err); 916 917 ret = fp_sub_monty(&out->X, &t1, &out->Y); EG(ret, err); 918 ret = fp_add_monty(&out->Y, &t1, &out->Y); EG(ret, err); 919 ret = fp_mul_monty(&out->Y, &out->X, &out->Y); EG(ret, err); 920 ret = fp_mul_monty(&out->X, &t3, &out->X); EG(ret, err); 921 ret = fp_mul_monty(&out->Z, &in->crv->b3_monty, &out->Z); EG(ret, err); 922 923 ret = fp_mul_monty(&t2, &in->crv->a_monty, &t2); EG(ret, err); 924 ret = fp_sub_monty(&t3, &t0, &t2); EG(ret, err); 925 ret = fp_mul_monty(&t3, &in->crv->a_monty, &t3); EG(ret, err); 926 ret = fp_add_monty(&t3, &t3, &out->Z); EG(ret, err); 927 ret = fp_add_monty(&out->Z, &t0, &t0); EG(ret, err); 928 929 ret = fp_add_monty(&t0, &out->Z, &t0); EG(ret, err); 930 ret = fp_add_monty(&t0, &t0, &t2); EG(ret, err); 931 ret = fp_mul_monty(&t0, &t0, &t3); EG(ret, err); 932 ret = fp_add_monty(&out->Y, &out->Y, &t0); EG(ret, err); 933 ret = fp_mul_monty(&t2, &in->Y, &in->Z); EG(ret, err); 934 935 ret = fp_add_monty(&t2, &t2, &t2); EG(ret, err); 936 ret = fp_mul_monty(&t0, &t2, &t3); EG(ret, err); 937 ret = fp_sub_monty(&out->X, &out->X, &t0); EG(ret, err); 938 ret = fp_mul_monty(&out->Z, &t2, &t1); EG(ret, err); 939 ret = fp_add_monty(&out->Z, &out->Z, &out->Z); EG(ret, err); 940 941 ret = fp_add_monty(&out->Z, &out->Z, &out->Z); 942 943 err: 944 fp_uninit(&t0); 945 fp_uninit(&t1); 946 fp_uninit(&t2); 947 fp_uninit(&t3); 948 949 return ret; 950 } 951 952 /* 953 * If NO_USE_COMPLETE_FORMULAS flag is not defined addition formulas from Algorithm 1 954 * of https://joostrenes.nl/publications/complete.pdf are used, otherwise 955 * http://www.hyperelliptic.org/EFD/g1p/auto-shortw-projective.html#addition-add-1998-cmo-2 956 */ 957 958 /* 959 * The function is an internal one: no check is performed on parameters, 960 * this MUST be done by the caller: 961 * 962 * - in1 and in2 are initialized 963 * - in1 and in2 are on the same curve 964 * - in1/in2 and out must not be aliased 965 * - in1 and in2 must not be an "exceptional" pair, i.e. (in1-in2) is not a point 966 * of order exactly 2 967 * 968 * The function will initialize 'out'. The function returns 0 on success, -1 969 * on error. 970 */ 971 ATTRIBUTE_WARN_UNUSED_RET static int __prj_pt_add_monty_cf(prj_pt_t out, 972 prj_pt_src_t in1, 973 prj_pt_src_t in2) 974 { 975 int cmp1, cmp2; 976 fp t0, t1, t2, t3, t4, t5; 977 int ret; 978 t0.magic = t1.magic = t2.magic = WORD(0); 979 t3.magic = t4.magic = t5.magic = WORD(0); 980 981 ret = prj_pt_init(out, in1->crv); EG(ret, err); 982 983 ret = fp_init(&t0, out->crv->a.ctx); EG(ret, err); 984 ret = fp_init(&t1, out->crv->a.ctx); EG(ret, err); 985 ret = fp_init(&t2, out->crv->a.ctx); EG(ret, err); 986 ret = fp_init(&t3, out->crv->a.ctx); EG(ret, err); 987 ret = fp_init(&t4, out->crv->a.ctx); EG(ret, err); 988 ret = fp_init(&t5, out->crv->a.ctx); EG(ret, err); 989 990 ret = fp_mul_monty(&t0, &in1->X, &in2->X); EG(ret, err); 991 ret = fp_mul_monty(&t1, &in1->Y, &in2->Y); EG(ret, err); 992 ret = fp_mul_monty(&t2, &in1->Z, &in2->Z); EG(ret, err); 993 ret = fp_add_monty(&t3, &in1->X, &in1->Y); EG(ret, err); 994 ret = fp_add_monty(&t4, &in2->X, &in2->Y); EG(ret, err); 995 996 ret = fp_mul_monty(&t3, &t3, &t4); EG(ret, err); 997 ret = fp_add_monty(&t4, &t0, &t1); EG(ret, err); 998 ret = fp_sub_monty(&t3, &t3, &t4); EG(ret, err); 999 ret = fp_add_monty(&t4, &in1->X, &in1->Z); EG(ret, err); 1000 ret = fp_add_monty(&t5, &in2->X, &in2->Z); EG(ret, err); 1001 1002 ret = fp_mul_monty(&t4, &t4, &t5); EG(ret, err); 1003 ret = fp_add_monty(&t5, &t0, &t2); EG(ret, err); 1004 ret = fp_sub_monty(&t4, &t4, &t5); EG(ret, err); 1005 ret = fp_add_monty(&t5, &in1->Y, &in1->Z); EG(ret, err); 1006 ret = fp_add_monty(&out->X, &in2->Y, &in2->Z); EG(ret, err); 1007 1008 ret = fp_mul_monty(&t5, &t5, &out->X); EG(ret, err); 1009 ret = fp_add_monty(&out->X, &t1, &t2); EG(ret, err); 1010 ret = fp_sub_monty(&t5, &t5, &out->X); EG(ret, err); 1011 ret = fp_mul_monty(&out->Z, &in1->crv->a_monty, &t4); EG(ret, err); 1012 ret = fp_mul_monty(&out->X, &in1->crv->b3_monty, &t2); EG(ret, err); 1013 1014 ret = fp_add_monty(&out->Z, &out->X, &out->Z); EG(ret, err); 1015 ret = fp_sub_monty(&out->X, &t1, &out->Z); EG(ret, err); 1016 ret = fp_add_monty(&out->Z, &t1, &out->Z); EG(ret, err); 1017 ret = fp_mul_monty(&out->Y, &out->X, &out->Z); EG(ret, err); 1018 ret = fp_add_monty(&t1, &t0, &t0); EG(ret, err); 1019 1020 ret = fp_add_monty(&t1, &t1, &t0); EG(ret, err); 1021 ret = fp_mul_monty(&t2, &in1->crv->a_monty, &t2); EG(ret, err); 1022 ret = fp_mul_monty(&t4, &in1->crv->b3_monty, &t4); EG(ret, err); 1023 ret = fp_add_monty(&t1, &t1, &t2); EG(ret, err); 1024 ret = fp_sub_monty(&t2, &t0, &t2); EG(ret, err); 1025 1026 ret = fp_mul_monty(&t2, &in1->crv->a_monty, &t2); EG(ret, err); 1027 ret = fp_add_monty(&t4, &t4, &t2); EG(ret, err); 1028 ret = fp_mul_monty(&t0, &t1, &t4); EG(ret, err); 1029 ret = fp_add_monty(&out->Y, &out->Y, &t0); EG(ret, err); 1030 ret = fp_mul_monty(&t0, &t5, &t4); EG(ret, err); 1031 1032 ret = fp_mul_monty(&out->X, &t3, &out->X); EG(ret, err); 1033 ret = fp_sub_monty(&out->X, &out->X, &t0); EG(ret, err); 1034 ret = fp_mul_monty(&t0, &t3, &t1); EG(ret, err); 1035 ret = fp_mul_monty(&out->Z, &t5, &out->Z); EG(ret, err); 1036 ret = fp_add_monty(&out->Z, &out->Z, &t0); 1037 1038 /* Check for "exceptional" pairs of input points with 1039 * checking if Y = Z = 0 as output (see the Bosma-Lenstra 1040 * article "Complete Systems of Two Addition Laws for 1041 * Elliptic Curves"). This should only happen on composite 1042 * order curves (i.e. not on prime order curves). 1043 * 1044 * In this case, we raise an error as the result is 1045 * not sound. This should not happen in our nominal 1046 * cases with regular signature and protocols, and if 1047 * it happens this usually means that bad points have 1048 * been injected. 1049 * 1050 * NOTE: if for some reasons you need to deal with 1051 * all the possible pairs of points including these 1052 * exceptional pairs of inputs with an order 2 difference, 1053 * you should fallback to the incomplete formulas using the 1054 * COMPLETE=0 compilation toggle. Beware that in this 1055 * case, the library will be more sensitive to 1056 * side-channel attacks. 1057 */ 1058 ret = fp_iszero(&(out->Z), &cmp1); EG(ret, err); 1059 ret = fp_iszero(&(out->Y), &cmp2); EG(ret, err); 1060 MUST_HAVE(!((cmp1) && (cmp2)), ret, err); 1061 1062 err: 1063 fp_uninit(&t0); 1064 fp_uninit(&t1); 1065 fp_uninit(&t2); 1066 fp_uninit(&t3); 1067 fp_uninit(&t4); 1068 fp_uninit(&t5); 1069 1070 return ret; 1071 } 1072 #endif /* NO_USE_COMPLETE_FORMULAS */ 1073 1074 /* 1075 * Internal function: 1076 * 1077 * - not supporting aliasing, 1078 * - requiring caller to check in parameter is initialized 1079 * 1080 * Based on library configuration, the function either use complete formulas 1081 * or not. 1082 */ 1083 static int _prj_pt_dbl_monty(prj_pt_t out, prj_pt_src_t in) 1084 { 1085 int ret; 1086 1087 #ifdef NO_USE_COMPLETE_FORMULAS 1088 int iszero; 1089 ret = prj_pt_iszero(in, &iszero); EG(ret, err); 1090 if (iszero) { 1091 ret = prj_pt_init(out, in->crv); EG(ret, err); 1092 ret = prj_pt_zero(out); 1093 } else { 1094 ret = __prj_pt_dbl_monty_no_cf(out, in); 1095 } 1096 #else 1097 ret = __prj_pt_dbl_monty_cf(out, in); EG(ret, err); 1098 #endif 1099 1100 err: 1101 return ret; 1102 } 1103 1104 /* 1105 * Internal version that peform in place doubling of given val, 1106 * by using a temporary copy. Sanity checks on parameters must 1107 * be done by caller. 1108 */ 1109 ATTRIBUTE_WARN_UNUSED_RET static int _prj_pt_dbl_monty_aliased(prj_pt_t val) 1110 { 1111 prj_pt out_cpy; 1112 int ret; 1113 out_cpy.magic = WORD(0); 1114 1115 ret = _prj_pt_dbl_monty(&out_cpy, val); EG(ret, err); 1116 ret = prj_pt_copy(val, &out_cpy); 1117 1118 err: 1119 prj_pt_uninit(&out_cpy); 1120 1121 return ret; 1122 } 1123 1124 /* 1125 * Public function for projective point doubling. The function handles the init 1126 * check of 'in' parameter which must be guaranteed for internal functions. 1127 * 'out' parameter need not be initialized and can be aliased with 'in' 1128 * parameter. 1129 * 1130 * The function returns 0 on success, -1 on error. 1131 */ 1132 ATTRIBUTE_WARN_UNUSED_RET int prj_pt_dbl(prj_pt_t out, prj_pt_src_t in) 1133 { 1134 int ret; 1135 1136 ret = prj_pt_check_initialized(in); EG(ret, err); 1137 1138 if (out == in) { 1139 ret = _prj_pt_dbl_monty_aliased(out); 1140 } else { 1141 ret = _prj_pt_dbl_monty(out, in); 1142 } 1143 1144 err: 1145 return ret; 1146 } 1147 1148 /* 1149 * Internal function: 1150 * 1151 * - not supporting aliasing, 1152 * - requiring caller to check in1 and in2 parameter 1153 * 1154 * Based on library configuration, the function either use complete formulas 1155 * or not. 1156 */ 1157 ATTRIBUTE_WARN_UNUSED_RET static inline int _prj_pt_add_monty(prj_pt_t out, 1158 prj_pt_src_t in1, 1159 prj_pt_src_t in2) 1160 { 1161 #ifndef NO_USE_COMPLETE_FORMULAS 1162 return __prj_pt_add_monty_cf(out, in1, in2); 1163 #else 1164 return __prj_pt_add_monty_no_cf(out, in1, in2); 1165 #endif 1166 } 1167 1168 /* 1169 * The function is an internal one that specifically handles aliasing. No check 1170 * is performed on parameters, this MUST be done by the caller: 1171 * 1172 * - in1 and in2 are initialized 1173 * - in1 and in2 are on the same curve 1174 * 1175 * The function will initialize 'out'. The function returns 0 on success, -1 1176 * on error. 1177 */ 1178 ATTRIBUTE_WARN_UNUSED_RET static int _prj_pt_add_monty_aliased(prj_pt_t out, 1179 prj_pt_src_t in1, 1180 prj_pt_src_t in2) 1181 { 1182 int ret; 1183 prj_pt out_cpy; 1184 out_cpy.magic = WORD(0); 1185 1186 ret = _prj_pt_add_monty(&out_cpy, in1, in2); EG(ret, err); 1187 ret = prj_pt_copy(out, &out_cpy); EG(ret, err); 1188 1189 err: 1190 prj_pt_uninit(&out_cpy); 1191 1192 return ret; 1193 } 1194 1195 /* 1196 * Public function for projective point addition. The function handles the 1197 * init checks of 'in1' and 'in2' parameters, along with the check they 1198 * use the same curve. This must be guaranteed for internal functions. 1199 * 'out' parameter need not be initialized and can be aliased with either 1200 * 'in1' or 'in2' parameter. 1201 * 1202 * The function returns 0 on success, -1 on error. 1203 */ 1204 int prj_pt_add(prj_pt_t out, prj_pt_src_t in1, prj_pt_src_t in2) 1205 { 1206 int ret; 1207 1208 ret = prj_pt_check_initialized(in1); EG(ret, err); 1209 ret = prj_pt_check_initialized(in2); EG(ret, err); 1210 MUST_HAVE((in1->crv == in2->crv), ret, err); 1211 1212 if ((out == in1) || (out == in2)) { 1213 ret = _prj_pt_add_monty_aliased(out, in1, in2); 1214 } else { 1215 ret = _prj_pt_add_monty(out, in1, in2); 1216 } 1217 1218 err: 1219 return ret; 1220 } 1221 1222 /*******************************************************************************/ 1223 /****** Scalar multiplication algorithms ***************************************/ 1224 /***********/ 1225 /* 1226 * The description below summarizes the following algorithms. 1227 * 1228 * Double-and-Add-Always and Montgomery Ladder masked using Itoh et al. anti-ADPA 1229 * (Address-bit DPA) countermeasure. 1230 * See "A Practical Countermeasure against Address-Bit Differential Power Analysis" 1231 * by Itoh, Izu and Takenaka for more information. 1232 * 1233 * NOTE: these masked variants of the Double-and-Add-Always and Montgomery Ladder algorithms 1234 * are used by default as Itoh et al. countermeasure has a very small impact on performance 1235 * and is inherently more robust againt DPA. The only case where we use another variant is 1236 * for devices with low memory as Itoh requires many temporary variables that consume many 1237 * temporary stack space. 1238 * 1239 * NOTE: the algorithms inherently depend on the MSB of the 1240 * scalar. In order to avoid leaking this MSB and fall into HNP (Hidden Number 1241 * Problem) issues, we use the trick described in https://eprint.iacr.org/2011/232.pdf 1242 * to have the MSB always set. However, since the scalar m might be less or bigger than 1243 * the order q of the curve, we distinguish three situations: 1244 * - The scalar m is < q (the order), in this case we compute: 1245 * - 1246 * | m' = m + (2 * q) if [log(k + q)] == [log(q)], 1247 * | m' = m + q otherwise. 1248 * - 1249 * - The scalar m is >= q and < q**2, in this case we compute: 1250 * - 1251 * | m' = m + (2 * (q**2)) if [log(k + (q**2))] == [log(q**2)], 1252 * | m' = m + (q**2) otherwise. 1253 * - 1254 * - The scalar m is >= (q**2), in this case m == m' 1255 * 1256 * => We only deal with 0 <= m < (q**2) using the countermeasure. When m >= (q**2), 1257 * we stick with m' = m, accepting MSB issues (not much can be done in this case 1258 * anyways). In the two first cases, Double-and-Add-Always and Montgomery Ladder are 1259 * performed in constant time wrt the size of the scalar m. 1260 */ 1261 /***********/ 1262 /* 1263 * Internal point blinding function: as it is internal, in is supposed to be initialized and 1264 * aliasing is NOT supported. 1265 */ 1266 ATTRIBUTE_WARN_UNUSED_RET static int _blind_projective_point(prj_pt_t out, prj_pt_src_t in) 1267 { 1268 int ret; 1269 1270 /* Random for projective coordinates masking */ 1271 /* NOTE: to limit stack usage, we reuse out->Z as a temporary 1272 * variable. This does not work if in == out, hence the check. 1273 */ 1274 MUST_HAVE((in != out), ret, err); 1275 1276 ret = prj_pt_init(out, in->crv); EG(ret, err); 1277 1278 /* Get a random value l in Fp */ 1279 ret = fp_get_random(&(out->Z), in->X.ctx); EG(ret, err); 1280 1281 /* 1282 * Blind the point with projective coordinates 1283 * (X, Y, Z) => (l*X, l*Y, l*Z) 1284 */ 1285 ret = fp_mul_monty(&(out->X), &(in->X), &(out->Z)); EG(ret, err); 1286 ret = fp_mul_monty(&(out->Y), &(in->Y), &(out->Z)); EG(ret, err); 1287 ret = fp_mul_monty(&(out->Z), &(in->Z), &(out->Z)); 1288 1289 err: 1290 return ret; 1291 } 1292 1293 /* If nothing is specified regarding the scalar multiplication algorithm, we use 1294 * the Montgomery Ladder. For the specific case of small stack devices, we release 1295 * some pressure on the stack by explicitly using double and always WITHOUT the Itoh 1296 * et al. countermeasure against A-DPA as it is quite consuming. 1297 */ 1298 #if defined(USE_SMALL_STACK) && defined(USE_MONTY_LADDER) 1299 #error "Small stack is only compatible with USE_DOUBLE_ADD_ALWAYS while USE_MONTY_LADDER has been explicitly asked!" 1300 #endif 1301 1302 #if defined(USE_SMALL_STACK) 1303 #ifndef USE_DOUBLE_ADD_ALWAYS 1304 #define USE_DOUBLE_ADD_ALWAYS 1305 #endif 1306 #endif 1307 1308 #if !defined(USE_DOUBLE_ADD_ALWAYS) && !defined(USE_MONTY_LADDER) 1309 #define USE_MONTY_LADDER 1310 #endif 1311 1312 #if defined(USE_DOUBLE_ADD_ALWAYS) && defined(USE_MONTY_LADDER) 1313 #error "You can either choose USE_DOUBLE_ADD_ALWAYS or USE_MONTY_LADDER, not both!" 1314 #endif 1315 1316 #if defined(USE_DOUBLE_ADD_ALWAYS) && !defined(USE_SMALL_STACK) 1317 ATTRIBUTE_WARN_UNUSED_RET static int _prj_pt_mul_ltr_monty_dbl_add_always(prj_pt_t out, nn_src_t m, prj_pt_src_t in) 1318 { 1319 /* We use Itoh et al. notations here for T and the random r */ 1320 prj_pt T[3]; 1321 bitcnt_t mlen; 1322 u8 mbit, rbit; 1323 /* Random for masking the Double and Add Always algorithm */ 1324 nn r; 1325 /* The new scalar we will use with MSB fixed to 1 (noted m' above). 1326 * This helps dealing with constant time. 1327 */ 1328 nn m_msb_fixed; 1329 nn_src_t curve_order; 1330 nn curve_order_square; 1331 int ret, ret_ops, cmp; 1332 r.magic = m_msb_fixed.magic = curve_order_square.magic = WORD(0); 1333 T[0].magic = T[1].magic = T[2].magic = WORD(0); 1334 1335 /* Compute m' from m depending on the rule described above */ 1336 curve_order = &(in->crv->order); 1337 /* First compute q**2 */ 1338 ret = nn_sqr(&curve_order_square, curve_order); EG(ret, err); 1339 /* Then compute m' depending on m size */ 1340 ret = nn_cmp(m, curve_order, &cmp); EG(ret, err); 1341 if (cmp < 0){ 1342 bitcnt_t msb_bit_len, order_bitlen; 1343 1344 /* Case where m < q */ 1345 ret = nn_add(&m_msb_fixed, m, curve_order); EG(ret, err); 1346 ret = nn_bitlen(&m_msb_fixed, &msb_bit_len); EG(ret, err); 1347 ret = nn_bitlen(curve_order, &order_bitlen); EG(ret, err); 1348 ret = nn_cnd_add((msb_bit_len == order_bitlen), &m_msb_fixed, 1349 &m_msb_fixed, curve_order); EG(ret, err); 1350 } else { 1351 ret = nn_cmp(m, &curve_order_square, &cmp); EG(ret, err); 1352 if (cmp < 0) { 1353 bitcnt_t msb_bit_len, curve_order_square_bitlen; 1354 1355 /* Case where m >= q and m < (q**2) */ 1356 ret = nn_add(&m_msb_fixed, m, &curve_order_square); EG(ret, err); 1357 ret = nn_bitlen(&m_msb_fixed, &msb_bit_len); EG(ret, err); 1358 ret = nn_bitlen(&curve_order_square, &curve_order_square_bitlen); EG(ret, err); 1359 ret = nn_cnd_add((msb_bit_len == curve_order_square_bitlen), 1360 &m_msb_fixed, &m_msb_fixed, &curve_order_square); EG(ret, err); 1361 } else { 1362 /* Case where m >= (q**2) */ 1363 ret = nn_copy(&m_msb_fixed, m); EG(ret, err); 1364 } 1365 } 1366 ret = nn_bitlen(&m_msb_fixed, &mlen); EG(ret, err); 1367 MUST_HAVE(mlen != 0, ret, err); 1368 mlen--; 1369 1370 /* Hide possible internal failures for double and add 1371 * operations and perform the operation in constant time. 1372 */ 1373 ret_ops = 0; 1374 1375 /* Get a random r with the same size of m_msb_fixed */ 1376 ret = nn_get_random_len(&r, m_msb_fixed.wlen * WORD_BYTES); EG(ret, err); 1377 1378 ret = nn_getbit(&r, mlen, &rbit); EG(ret, err); 1379 1380 /* Initialize points */ 1381 ret = prj_pt_init(&T[0], in->crv); EG(ret, err); 1382 ret = prj_pt_init(&T[1], in->crv); EG(ret, err); 1383 1384 /* 1385 * T[2] = R(P) 1386 * Blind the point with projective coordinates 1387 * (X, Y, Z) => (l*X, l*Y, l*Z) 1388 */ 1389 ret = _blind_projective_point(&T[2], in); EG(ret, err); 1390 1391 /* T[r[n-1]] = T[2] */ 1392 ret = prj_pt_copy(&T[rbit], &T[2]); EG(ret, err); 1393 1394 /* Main loop of Double and Add Always */ 1395 while (mlen > 0) { 1396 u8 rbit_next; 1397 --mlen; 1398 /* rbit is r[i+1], and rbit_next is r[i] */ 1399 ret = nn_getbit(&r, mlen, &rbit_next); EG(ret, err); 1400 1401 /* mbit is m[i] */ 1402 ret = nn_getbit(&m_msb_fixed, mlen, &mbit); EG(ret, err); 1403 1404 /* Double: T[r[i+1]] = ECDBL(T[r[i+1]]) */ 1405 #ifndef NO_USE_COMPLETE_FORMULAS 1406 /* 1407 * NOTE: in case of complete formulas, we use the 1408 * addition for doubling, incurring a small performance hit 1409 * for better SCA resistance. 1410 */ 1411 ret_ops |= prj_pt_add(&T[rbit], &T[rbit], &T[rbit]); 1412 #else 1413 ret_ops |= prj_pt_dbl(&T[rbit], &T[rbit]); 1414 #endif 1415 /* Add: T[1-r[i+1]] = ECADD(T[r[i+1]],T[2]) */ 1416 ret_ops |= prj_pt_add(&T[1-rbit], &T[rbit], &T[2]); 1417 1418 /* 1419 * T[r[i]] = T[d[i] ^ r[i+1]] 1420 * NOTE: we use the low level nn_copy function here to avoid 1421 * any possible leakage on operands with prj_pt_copy 1422 */ 1423 ret = nn_copy(&(T[rbit_next].X.fp_val), &(T[mbit ^ rbit].X.fp_val)); EG(ret, err); 1424 ret = nn_copy(&(T[rbit_next].Y.fp_val), &(T[mbit ^ rbit].Y.fp_val)); EG(ret, err); 1425 ret = nn_copy(&(T[rbit_next].Z.fp_val), &(T[mbit ^ rbit].Z.fp_val)); EG(ret, err); 1426 1427 /* Update rbit */ 1428 rbit = rbit_next; 1429 } 1430 /* Output: T[r[0]] */ 1431 ret = prj_pt_copy(out, &T[rbit]); EG(ret, err); 1432 1433 /* Take into consideration our double and add errors */ 1434 ret |= ret_ops; 1435 1436 err: 1437 prj_pt_uninit(&T[0]); 1438 prj_pt_uninit(&T[1]); 1439 prj_pt_uninit(&T[2]); 1440 nn_uninit(&r); 1441 nn_uninit(&m_msb_fixed); 1442 nn_uninit(&curve_order_square); 1443 1444 PTR_NULLIFY(curve_order); 1445 1446 return ret; 1447 } 1448 #endif 1449 1450 #if defined(USE_DOUBLE_ADD_ALWAYS) && defined(USE_SMALL_STACK) 1451 /* NOTE: in small stack case where we compile for low memory devices, we do not use Itoh et al. countermeasure 1452 * as it requires too much temporary space on the stack. 1453 */ 1454 ATTRIBUTE_WARN_UNUSED_RET static int _prj_pt_mul_ltr_monty_dbl_add_always(prj_pt_t out, nn_src_t m, prj_pt_src_t in) 1455 { 1456 int ret, ret_ops; 1457 1458 /* Hide possible internal failures for double and add 1459 * operations and perform the operation in constant time. 1460 */ 1461 ret_ops = 0; 1462 1463 /* Blind the input point projective coordinates */ 1464 ret = _blind_projective_point(out, in); EG(ret, err); 1465 1466 /*******************/ 1467 { 1468 bitcnt_t mlen; 1469 u8 mbit; 1470 /* The new scalar we will use with MSB fixed to 1 (noted m' above). 1471 * This helps dealing with constant time. 1472 */ 1473 nn m_msb_fixed; 1474 nn_src_t curve_order; 1475 int cmp; 1476 m_msb_fixed.magic = WORD(0); 1477 1478 { 1479 nn curve_order_square; 1480 curve_order_square.magic = WORD(0); 1481 1482 /* Compute m' from m depending on the rule described above */ 1483 curve_order = &(in->crv->order); 1484 /* First compute q**2 */ 1485 ret = nn_sqr(&curve_order_square, curve_order); EG(ret, err1); 1486 /* Then compute m' depending on m size */ 1487 ret = nn_cmp(m, curve_order, &cmp); EG(ret, err1); 1488 if (cmp < 0){ 1489 bitcnt_t msb_bit_len, order_bitlen; 1490 1491 /* Case where m < q */ 1492 ret = nn_add(&m_msb_fixed, m, curve_order); EG(ret, err1); 1493 ret = nn_bitlen(&m_msb_fixed, &msb_bit_len); EG(ret, err1); 1494 ret = nn_bitlen(curve_order, &order_bitlen); EG(ret, err1); 1495 ret = nn_cnd_add((msb_bit_len == order_bitlen), &m_msb_fixed, 1496 &m_msb_fixed, curve_order); EG(ret, err1); 1497 } else { 1498 ret = nn_cmp(m, &curve_order_square, &cmp); EG(ret, err1); 1499 if (cmp < 0) { 1500 bitcnt_t msb_bit_len, curve_order_square_bitlen; 1501 1502 /* Case where m >= q and m < (q**2) */ 1503 ret = nn_add(&m_msb_fixed, m, &curve_order_square); EG(ret, err1); 1504 ret = nn_bitlen(&m_msb_fixed, &msb_bit_len); EG(ret, err1); 1505 ret = nn_bitlen(&curve_order_square, &curve_order_square_bitlen); EG(ret, err1); 1506 ret = nn_cnd_add((msb_bit_len == curve_order_square_bitlen), 1507 &m_msb_fixed, &m_msb_fixed, &curve_order_square); EG(ret, err1); 1508 } else { 1509 /* Case where m >= (q**2) */ 1510 ret = nn_copy(&m_msb_fixed, m); EG(ret, err1); 1511 } 1512 } 1513 err1: 1514 nn_uninit(&curve_order_square); EG(ret, err); 1515 } 1516 1517 ret = nn_bitlen(&m_msb_fixed, &mlen); EG(ret, err); 1518 MUST_HAVE((mlen != 0), ret, err); 1519 mlen--; 1520 1521 { 1522 prj_pt dbl; 1523 dbl.magic = WORD(0); 1524 1525 /* Initialize temporary point */ 1526 ret = prj_pt_init(&dbl, in->crv); EG(ret, err2); 1527 1528 /* Main loop of Double and Add Always */ 1529 while (mlen > 0) { 1530 --mlen; 1531 /* mbit is m[i] */ 1532 ret = nn_getbit(&m_msb_fixed, mlen, &mbit); EG(ret, err2); 1533 1534 #ifndef NO_USE_COMPLETE_FORMULAS 1535 /* 1536 * NOTE: in case of complete formulas, we use the 1537 * addition for doubling, incurring a small performance hit 1538 * for better SCA resistance. 1539 */ 1540 ret_ops |= prj_pt_add(&dbl, out, out); 1541 #else 1542 ret_ops |= prj_pt_dbl(&dbl, out); 1543 #endif 1544 ret_ops |= prj_pt_add(out, &dbl, in); 1545 /* Swap */ 1546 ret = nn_cnd_swap(!mbit, &(out->X.fp_val), &(dbl.X.fp_val)); EG(ret, err2); 1547 ret = nn_cnd_swap(!mbit, &(out->Y.fp_val), &(dbl.Y.fp_val)); EG(ret, err2); 1548 ret = nn_cnd_swap(!mbit, &(out->Z.fp_val), &(dbl.Z.fp_val)); EG(ret, err2); 1549 } 1550 err2: 1551 prj_pt_uninit(&dbl); EG(ret, err); 1552 } 1553 1554 err: 1555 nn_uninit(&m_msb_fixed); 1556 1557 PTR_NULLIFY(curve_order); 1558 } 1559 1560 /* Take into consideration our double and add errors */ 1561 ret |= ret_ops; 1562 1563 return ret; 1564 } 1565 #endif 1566 1567 1568 #ifdef USE_MONTY_LADDER 1569 ATTRIBUTE_WARN_UNUSED_RET static int _prj_pt_mul_ltr_monty_ladder(prj_pt_t out, nn_src_t m, prj_pt_src_t in) 1570 { 1571 /* We use Itoh et al. notations here for T and the random r */ 1572 prj_pt T[3]; 1573 bitcnt_t mlen; 1574 u8 mbit, rbit; 1575 /* Random for masking the Montgomery Ladder algorithm */ 1576 nn r; 1577 /* The new scalar we will use with MSB fixed to 1 (noted m' above). 1578 * This helps dealing with constant time. 1579 */ 1580 nn m_msb_fixed; 1581 nn_src_t curve_order; 1582 nn curve_order_square; 1583 int ret, ret_ops, cmp; 1584 r.magic = m_msb_fixed.magic = curve_order_square.magic = WORD(0); 1585 T[0].magic = T[1].magic = T[2].magic = WORD(0); 1586 1587 /* Compute m' from m depending on the rule described above */ 1588 curve_order = &(in->crv->order); 1589 1590 /* First compute q**2 */ 1591 ret = nn_sqr(&curve_order_square, curve_order); EG(ret, err); 1592 1593 /* Then compute m' depending on m size */ 1594 ret = nn_cmp(m, curve_order, &cmp); EG(ret, err); 1595 if (cmp < 0) { 1596 bitcnt_t msb_bit_len, order_bitlen; 1597 1598 /* Case where m < q */ 1599 ret = nn_add(&m_msb_fixed, m, curve_order); EG(ret, err); 1600 ret = nn_bitlen(&m_msb_fixed, &msb_bit_len); EG(ret, err); 1601 ret = nn_bitlen(curve_order, &order_bitlen); EG(ret, err); 1602 ret = nn_cnd_add((msb_bit_len == order_bitlen), &m_msb_fixed, 1603 &m_msb_fixed, curve_order); EG(ret, err); 1604 } else { 1605 ret = nn_cmp(m, &curve_order_square, &cmp); EG(ret, err); 1606 if (cmp < 0) { 1607 bitcnt_t msb_bit_len, curve_order_square_bitlen; 1608 1609 /* Case where m >= q and m < (q**2) */ 1610 ret = nn_add(&m_msb_fixed, m, &curve_order_square); EG(ret, err); 1611 ret = nn_bitlen(&m_msb_fixed, &msb_bit_len); EG(ret, err); 1612 ret = nn_bitlen(&curve_order_square, &curve_order_square_bitlen); EG(ret, err); 1613 ret = nn_cnd_add((msb_bit_len == curve_order_square_bitlen), 1614 &m_msb_fixed, &m_msb_fixed, &curve_order_square); EG(ret, err); 1615 } else { 1616 /* Case where m >= (q**2) */ 1617 ret = nn_copy(&m_msb_fixed, m); EG(ret, err); 1618 } 1619 } 1620 1621 ret = nn_bitlen(&m_msb_fixed, &mlen); EG(ret, err); 1622 MUST_HAVE((mlen != 0), ret, err); 1623 mlen--; 1624 1625 /* Hide possible internal failures for double and add 1626 * operations and perform the operation in constant time. 1627 */ 1628 ret_ops = 0; 1629 1630 /* Get a random r with the same size of m_msb_fixed */ 1631 ret = nn_get_random_len(&r, (u16)(m_msb_fixed.wlen * WORD_BYTES)); EG(ret, err); 1632 1633 ret = nn_getbit(&r, mlen, &rbit); EG(ret, err); 1634 1635 /* Initialize points */ 1636 ret = prj_pt_init(&T[0], in->crv); EG(ret, err); 1637 ret = prj_pt_init(&T[1], in->crv); EG(ret, err); 1638 ret = prj_pt_init(&T[2], in->crv); EG(ret, err); 1639 1640 /* Initialize T[r[n-1]] to input point */ 1641 /* 1642 * Blind the point with projective coordinates 1643 * (X, Y, Z) => (l*X, l*Y, l*Z) 1644 */ 1645 ret = _blind_projective_point(&T[rbit], in); EG(ret, err); 1646 1647 /* Initialize T[1-r[n-1]] with ECDBL(T[r[n-1]])) */ 1648 #ifndef NO_USE_COMPLETE_FORMULAS 1649 /* 1650 * NOTE: in case of complete formulas, we use the 1651 * addition for doubling, incurring a small performance hit 1652 * for better SCA resistance. 1653 */ 1654 ret_ops |= prj_pt_add(&T[1-rbit], &T[rbit], &T[rbit]); 1655 #else 1656 ret_ops |= prj_pt_dbl(&T[1-rbit], &T[rbit]); 1657 #endif 1658 1659 /* Main loop of the Montgomery Ladder */ 1660 while (mlen > 0) { 1661 u8 rbit_next; 1662 --mlen; 1663 /* rbit is r[i+1], and rbit_next is r[i] */ 1664 ret = nn_getbit(&r, mlen, &rbit_next); EG(ret, err); 1665 1666 /* mbit is m[i] */ 1667 ret = nn_getbit(&m_msb_fixed, mlen, &mbit); EG(ret, err); 1668 /* Double: T[2] = ECDBL(T[d[i] ^ r[i+1]]) */ 1669 1670 #ifndef NO_USE_COMPLETE_FORMULAS 1671 /* NOTE: in case of complete formulas, we use the 1672 * addition for doubling, incurring a small performance hit 1673 * for better SCA resistance. 1674 */ 1675 ret_ops |= prj_pt_add(&T[2], &T[mbit ^ rbit], &T[mbit ^ rbit]); 1676 #else 1677 ret_ops |= prj_pt_dbl(&T[2], &T[mbit ^ rbit]); 1678 #endif 1679 1680 /* Add: T[1] = ECADD(T[0],T[1]) */ 1681 ret_ops |= prj_pt_add(&T[1], &T[0], &T[1]); 1682 1683 /* T[0] = T[2-(d[i] ^ r[i])] */ 1684 /* 1685 * NOTE: we use the low level nn_copy function here to avoid 1686 * any possible leakage on operands with prj_pt_copy 1687 */ 1688 ret = nn_copy(&(T[0].X.fp_val), &(T[2-(mbit ^ rbit_next)].X.fp_val)); EG(ret, err); 1689 ret = nn_copy(&(T[0].Y.fp_val), &(T[2-(mbit ^ rbit_next)].Y.fp_val)); EG(ret, err); 1690 ret = nn_copy(&(T[0].Z.fp_val), &(T[2-(mbit ^ rbit_next)].Z.fp_val)); EG(ret, err); 1691 1692 /* T[1] = T[1+(d[i] ^ r[i])] */ 1693 /* NOTE: we use the low level nn_copy function here to avoid 1694 * any possible leakage on operands with prj_pt_copy 1695 */ 1696 ret = nn_copy(&(T[1].X.fp_val), &(T[1+(mbit ^ rbit_next)].X.fp_val)); EG(ret, err); 1697 ret = nn_copy(&(T[1].Y.fp_val), &(T[1+(mbit ^ rbit_next)].Y.fp_val)); EG(ret, err); 1698 ret = nn_copy(&(T[1].Z.fp_val), &(T[1+(mbit ^ rbit_next)].Z.fp_val)); EG(ret, err); 1699 1700 /* Update rbit */ 1701 rbit = rbit_next; 1702 } 1703 /* Output: T[r[0]] */ 1704 ret = prj_pt_copy(out, &T[rbit]); EG(ret, err); 1705 1706 /* Take into consideration our double and add errors */ 1707 ret |= ret_ops; 1708 1709 err: 1710 prj_pt_uninit(&T[0]); 1711 prj_pt_uninit(&T[1]); 1712 prj_pt_uninit(&T[2]); 1713 nn_uninit(&r); 1714 nn_uninit(&m_msb_fixed); 1715 nn_uninit(&curve_order_square); 1716 1717 PTR_NULLIFY(curve_order); 1718 1719 return ret; 1720 } 1721 #endif 1722 1723 /* Main projective scalar multiplication function. 1724 * Depending on the preprocessing options, we use either the 1725 * Double and Add Always algorithm, or the Montgomery Ladder one. 1726 */ 1727 ATTRIBUTE_WARN_UNUSED_RET static int _prj_pt_mul_ltr_monty(prj_pt_t out, nn_src_t m, prj_pt_src_t in){ 1728 #if defined(USE_DOUBLE_ADD_ALWAYS) 1729 return _prj_pt_mul_ltr_monty_dbl_add_always(out, m, in); 1730 #elif defined(USE_MONTY_LADDER) 1731 return _prj_pt_mul_ltr_monty_ladder(out, m, in); 1732 #else 1733 #error "Error: neither Double and Add Always nor Montgomery Ladder has been selected!" 1734 #endif 1735 } 1736 1737 /* version with 'm' passed via 'out'. */ 1738 ATTRIBUTE_WARN_UNUSED_RET static int _prj_pt_mul_ltr_monty_aliased(prj_pt_t out, nn_src_t m, prj_pt_src_t in) 1739 { 1740 prj_pt out_cpy; 1741 int ret; 1742 out_cpy.magic = WORD(0); 1743 1744 ret = prj_pt_init(&out_cpy, in->crv); EG(ret, err); 1745 ret = _prj_pt_mul_ltr_monty(&out_cpy, m, in); EG(ret, err); 1746 ret = prj_pt_copy(out, &out_cpy); 1747 1748 err: 1749 prj_pt_uninit(&out_cpy); 1750 return ret; 1751 } 1752 1753 /* Aliased version. This is the public main interface of our 1754 * scalar multiplication algorithm. Checks that the input point 1755 * and that the output point are on the curve are performed here 1756 * (before and after calling the core algorithm, albeit Double and 1757 * Add Always or Montgomery Ladder). 1758 */ 1759 int prj_pt_mul(prj_pt_t out, nn_src_t m, prj_pt_src_t in) 1760 { 1761 int ret, on_curve; 1762 1763 ret = prj_pt_check_initialized(in); EG(ret, err); 1764 ret = nn_check_initialized(m); EG(ret, err); 1765 1766 /* Check that the input is on the curve */ 1767 MUST_HAVE((!prj_pt_is_on_curve(in, &on_curve)) && on_curve, ret, err); 1768 1769 if (out == in) { 1770 ret = _prj_pt_mul_ltr_monty_aliased(out, m, in); EG(ret, err); 1771 } else { 1772 ret = _prj_pt_mul_ltr_monty(out, m, in); EG(ret, err); 1773 } 1774 1775 /* Check that the output is on the curve */ 1776 MUST_HAVE((!prj_pt_is_on_curve(out, &on_curve)) && on_curve, ret, err); 1777 1778 err: 1779 return ret; 1780 } 1781 1782 int prj_pt_mul_blind(prj_pt_t out, nn_src_t m, prj_pt_src_t in) 1783 { 1784 /* Blind the scalar m with (b*q) where q is the curve order. 1785 * NOTE: the curve order and the "generator" order are 1786 * usually the same (i.e. cofactor = 1) for the classical 1787 * prime fields curves. However some exceptions exist 1788 * (e.g. Wei25519 and Wei448), and in this case it is 1789 * curcial to use the curve order for a generic blinding 1790 * working on any point on the curve. 1791 */ 1792 nn b; 1793 nn_src_t q; 1794 int ret; 1795 b.magic = WORD(0); 1796 1797 ret = prj_pt_check_initialized(in); EG(ret, err); 1798 1799 q = &(in->crv->order); 1800 1801 ret = nn_init(&b, 0); EG(ret, err); 1802 1803 ret = nn_get_random_mod(&b, q); EG(ret, err); 1804 1805 ret = nn_mul(&b, &b, q); EG(ret, err); 1806 ret = nn_add(&b, &b, m); EG(ret, err); 1807 1808 /* NOTE: point blinding is performed in the lower functions */ 1809 /* NOTE: check that input and output points are on the curve are 1810 * performed in the lower functions. 1811 */ 1812 1813 /* Perform the scalar multiplication */ 1814 ret = prj_pt_mul(out, &b, in); 1815 1816 err: 1817 nn_uninit(&b); 1818 1819 PTR_NULLIFY(q); 1820 1821 return ret; 1822 } 1823 1824 /* Naive double and add scalar multiplication. 1825 * 1826 * This scalar multiplication is used on public values and is optimized with no 1827 * countermeasures, and it is usually faster as scalar can be small with few bits 1828 * to process (e.g. cofactors, etc.). 1829 * 1830 * out is initialized by the function. 1831 * 1832 * XXX: WARNING: this function must only be used on public points! 1833 * 1834 */ 1835 static int __prj_pt_unprotected_mult(prj_pt_t out, nn_src_t scalar, prj_pt_src_t public_in) 1836 { 1837 u8 expbit; 1838 bitcnt_t explen; 1839 int ret, iszero, on_curve; 1840 1841 ret = prj_pt_check_initialized(public_in); EG(ret, err); 1842 ret = nn_check_initialized(scalar); EG(ret, err); 1843 1844 /* This function does not support aliasing */ 1845 MUST_HAVE((out != public_in), ret, err); 1846 1847 /* Check that the input is on the curve */ 1848 MUST_HAVE((!prj_pt_is_on_curve(public_in, &on_curve)) && on_curve, ret, err); 1849 1850 ret = nn_iszero(scalar, &iszero); EG(ret, err); 1851 /* Multiplication by zero is the point at infinity */ 1852 if(iszero){ 1853 ret = prj_pt_zero(out); EG(ret, err); 1854 goto err; 1855 } 1856 1857 ret = nn_bitlen(scalar, &explen); EG(ret, err); 1858 /* Sanity check */ 1859 MUST_HAVE((explen > 0), ret, err); 1860 explen = (bitcnt_t)(explen - 1); 1861 ret = prj_pt_copy(out, public_in); EG(ret, err); 1862 1863 while (explen > 0) { 1864 explen = (bitcnt_t)(explen - 1); 1865 ret = nn_getbit(scalar, explen, &expbit); EG(ret, err); 1866 ret = prj_pt_dbl(out, out); EG(ret, err); 1867 if(expbit){ 1868 ret = prj_pt_add(out, out, public_in); EG(ret, err); 1869 } 1870 } 1871 1872 /* Check that the output is on the curve */ 1873 MUST_HAVE((!prj_pt_is_on_curve(out, &on_curve)) && on_curve, ret, err); 1874 1875 err: 1876 VAR_ZEROIFY(expbit); 1877 VAR_ZEROIFY(explen); 1878 1879 return ret; 1880 } 1881 1882 /* Aliased version of __prj_pt_unprotected_mult */ 1883 int _prj_pt_unprotected_mult(prj_pt_t out, nn_src_t scalar, prj_pt_src_t public_in) 1884 { 1885 int ret; 1886 1887 if(out == public_in){ 1888 prj_pt A; 1889 A.magic = WORD(0); 1890 1891 ret = prj_pt_copy(&A, public_in); EG(ret, err1); 1892 ret = __prj_pt_unprotected_mult(out, scalar, &A); 1893 err1: 1894 prj_pt_uninit(&A); 1895 goto err; 1896 } 1897 else{ 1898 ret = __prj_pt_unprotected_mult(out, scalar, public_in); 1899 } 1900 err: 1901 return ret; 1902 } 1903 /* 1904 * Check if an integer is (a multiple of) a projective point order. 1905 * 1906 * The function returns 0 on success, -1 on error. The value check is set to 1 if the projective 1907 * point has order in_isorder, 0 otherwise. The value is meaningless on error. 1908 */ 1909 int check_prj_pt_order(prj_pt_src_t in_shortw, nn_src_t in_isorder, prj_pt_sensitivity s, int *check) 1910 { 1911 int ret, iszero; 1912 prj_pt res; 1913 res.magic = WORD(0); 1914 1915 /* First sanity checks */ 1916 ret = prj_pt_check_initialized(in_shortw); EG(ret, err); 1917 ret = nn_check_initialized(in_isorder); EG(ret, err); 1918 MUST_HAVE((check != NULL), ret, err); 1919 1920 /* Then, perform the scalar multiplication */ 1921 if(s == PUBLIC_PT){ 1922 /* If this is a public point, we can use the naive scalar multiplication */ 1923 ret = _prj_pt_unprotected_mult(&res, in_isorder, in_shortw); EG(ret, err); 1924 } 1925 else{ 1926 /* If the point is private, it is sensitive and we proceed with the secure 1927 * scalar blind multiplication. 1928 */ 1929 ret = prj_pt_mul_blind(&res, in_isorder, in_shortw); EG(ret, err); 1930 } 1931 1932 /* Check if we have the point at infinity */ 1933 ret = prj_pt_iszero(&res, &iszero); EG(ret, err); 1934 (*check) = iszero; 1935 1936 err: 1937 prj_pt_uninit(&res); 1938 1939 return ret; 1940 } 1941 1942 /*****************************************************************************/ 1943 1944 /* 1945 * Map points from Edwards to short Weierstrass projective points through Montgomery (composition mapping). 1946 * Point at infinity (0, 1) -> (0, 1, 0) is treated as an exception, which is trivially not constant time. 1947 * This is OK since our mapping functions should be used at the non sensitive input and output 1948 * interfaces. 1949 * 1950 * The function returns 0 on success, -1 on error. 1951 */ 1952 int aff_pt_edwards_to_prj_pt_shortw(aff_pt_edwards_src_t in_edwards, 1953 ec_shortw_crv_src_t shortw_crv, 1954 prj_pt_t out_shortw, 1955 fp_src_t alpha_edwards) 1956 { 1957 int ret, iszero, cmp; 1958 aff_pt out_shortw_aff; 1959 fp one; 1960 out_shortw_aff.magic = one.magic = WORD(0); 1961 1962 /* Check the curves compatibility */ 1963 ret = aff_pt_edwards_check_initialized(in_edwards); EG(ret, err); 1964 ret = curve_edwards_shortw_check(in_edwards->crv, shortw_crv, alpha_edwards); EG(ret, err); 1965 1966 /* Initialize output point with curve */ 1967 ret = prj_pt_init(out_shortw, shortw_crv); EG(ret, err); 1968 1969 ret = fp_init(&one, in_edwards->x.ctx); EG(ret, err); 1970 ret = fp_one(&one); EG(ret, err); 1971 1972 /* Check if we are the point at infinity 1973 * This check induces a non consant time exception, but the current function must be called on 1974 * public data anyways. 1975 */ 1976 ret = fp_iszero(&(in_edwards->x), &iszero); EG(ret, err); 1977 ret = fp_cmp(&(in_edwards->y), &one, &cmp); EG(ret, err); 1978 if(iszero && (cmp == 0)){ 1979 ret = prj_pt_zero(out_shortw); EG(ret, err); 1980 ret = 0; 1981 goto err; 1982 } 1983 1984 /* Use the affine mapping */ 1985 ret = aff_pt_edwards_to_shortw(in_edwards, shortw_crv, &out_shortw_aff, alpha_edwards); EG(ret, err); 1986 /* And then map the short Weierstrass affine to projective coordinates */ 1987 ret = ec_shortw_aff_to_prj(out_shortw, &out_shortw_aff); 1988 1989 err: 1990 fp_uninit(&one); 1991 aff_pt_uninit(&out_shortw_aff); 1992 1993 return ret; 1994 } 1995 1996 /* 1997 * Map points from short Weierstrass projective points to Edwards through Montgomery (composition mapping). 1998 * Point at infinity with Z=0 (in projective coordinates) -> (0, 1) is treated as an exception, which is trivially not constant time. 1999 * This is OK since our mapping functions should be used at the non sensitive input and output 2000 * interfaces. 2001 * 2002 * The function returns 0 on success, -1 on error. 2003 */ 2004 int prj_pt_shortw_to_aff_pt_edwards(prj_pt_src_t in_shortw, 2005 ec_edwards_crv_src_t edwards_crv, 2006 aff_pt_edwards_t out_edwards, 2007 fp_src_t alpha_edwards) 2008 { 2009 int ret, iszero; 2010 aff_pt in_shortw_aff; 2011 in_shortw_aff.magic = WORD(0); 2012 2013 /* Check the curves compatibility */ 2014 ret = prj_pt_check_initialized(in_shortw); EG(ret, err); 2015 ret = curve_edwards_shortw_check(edwards_crv, in_shortw->crv, alpha_edwards); EG(ret, err); 2016 2017 /* Initialize output point with curve */ 2018 ret = aff_pt_init(&in_shortw_aff, in_shortw->crv); EG(ret, err); 2019 2020 /* Check if we are the point at infinity 2021 * This check induces a non consant time exception, but the current function must be called on 2022 * public data anyways. 2023 */ 2024 ret = prj_pt_iszero(in_shortw, &iszero); EG(ret, err); 2025 if(iszero){ 2026 fp zero, one; 2027 zero.magic = one.magic = WORD(0); 2028 2029 ret = fp_init(&zero, in_shortw->X.ctx); EG(ret, err1); 2030 ret = fp_init(&one, in_shortw->X.ctx); EG(ret, err1); 2031 2032 ret = fp_zero(&zero); EG(ret, err1); 2033 ret = fp_one(&one); EG(ret, err1); 2034 2035 ret = aff_pt_edwards_init_from_coords(out_edwards, edwards_crv, &zero, &one); 2036 2037 err1: 2038 fp_uninit(&zero); 2039 fp_uninit(&one); 2040 2041 goto err; 2042 } 2043 2044 /* Map projective to affine on the short Weierstrass */ 2045 ret = prj_pt_to_aff(&in_shortw_aff, in_shortw); EG(ret, err); 2046 /* Use the affine mapping */ 2047 ret = aff_pt_shortw_to_edwards(&in_shortw_aff, edwards_crv, out_edwards, alpha_edwards); 2048 2049 err: 2050 aff_pt_uninit(&in_shortw_aff); 2051 2052 return ret; 2053 } 2054 2055 /* 2056 * Map points from Montgomery to short Weierstrass projective points. 2057 * 2058 * The function returns 0 on success, -1 on error. 2059 */ 2060 int aff_pt_montgomery_to_prj_pt_shortw(aff_pt_montgomery_src_t in_montgomery, 2061 ec_shortw_crv_src_t shortw_crv, 2062 prj_pt_t out_shortw) 2063 { 2064 int ret; 2065 aff_pt out_shortw_aff; 2066 out_shortw_aff.magic = WORD(0); 2067 2068 /* Check the curves compatibility */ 2069 ret = aff_pt_montgomery_check_initialized(in_montgomery); EG(ret, err); 2070 ret = curve_montgomery_shortw_check(in_montgomery->crv, shortw_crv); EG(ret, err); 2071 2072 /* Initialize output point with curve */ 2073 ret = prj_pt_init(out_shortw, shortw_crv); EG(ret, err); 2074 2075 /* Use the affine mapping */ 2076 ret = aff_pt_montgomery_to_shortw(in_montgomery, shortw_crv, &out_shortw_aff); EG(ret, err); 2077 /* And then map the short Weierstrass affine to projective coordinates */ 2078 ret = ec_shortw_aff_to_prj(out_shortw, &out_shortw_aff); 2079 2080 err: 2081 aff_pt_uninit(&out_shortw_aff); 2082 2083 return ret; 2084 } 2085 2086 /* 2087 * Map points from short Weierstrass projective points to Montgomery. 2088 * 2089 * The function returns 0 on success, -1 on error. 2090 */ 2091 int prj_pt_shortw_to_aff_pt_montgomery(prj_pt_src_t in_shortw, ec_montgomery_crv_src_t montgomery_crv, aff_pt_montgomery_t out_montgomery) 2092 { 2093 int ret; 2094 aff_pt in_shortw_aff; 2095 in_shortw_aff.magic = WORD(0); 2096 2097 /* Check the curves compatibility */ 2098 ret = prj_pt_check_initialized(in_shortw); EG(ret, err); 2099 ret = curve_montgomery_shortw_check(montgomery_crv, in_shortw->crv); EG(ret, err); 2100 2101 /* Initialize output point with curve */ 2102 ret = aff_pt_init(&in_shortw_aff, in_shortw->crv); EG(ret, err); 2103 2104 /* Map projective to affine on the short Weierstrass */ 2105 ret = prj_pt_to_aff(&in_shortw_aff, in_shortw); EG(ret, err); 2106 /* Use the affine mapping */ 2107 ret = aff_pt_shortw_to_montgomery(&in_shortw_aff, montgomery_crv, out_montgomery); 2108 2109 err: 2110 aff_pt_uninit(&in_shortw_aff); 2111 2112 return ret; 2113 } 2114