summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/ec/ecp_smpl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/ec/ecp_smpl.c')
-rw-r--r--src/lib/libcrypto/ec/ecp_smpl.c274
1 files changed, 13 insertions, 261 deletions
diff --git a/src/lib/libcrypto/ec/ecp_smpl.c b/src/lib/libcrypto/ec/ecp_smpl.c
index 57e8345364..1fe55307b4 100644
--- a/src/lib/libcrypto/ec/ecp_smpl.c
+++ b/src/lib/libcrypto/ec/ecp_smpl.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ecp_smpl.c,v 1.19 2018/07/10 22:06:14 tb Exp $ */ 1/* $OpenBSD: ecp_smpl.c,v 1.20 2018/07/15 05:38:48 jsg Exp $ */
2/* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de> 2/* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de>
3 * for the OpenSSL project. 3 * for the OpenSSL project.
4 * Includes code written by Bodo Moeller for the OpenSSL project. 4 * Includes code written by Bodo Moeller for the OpenSSL project.
@@ -103,9 +103,6 @@ EC_GFp_simple_method(void)
103 .point_cmp = ec_GFp_simple_cmp, 103 .point_cmp = ec_GFp_simple_cmp,
104 .make_affine = ec_GFp_simple_make_affine, 104 .make_affine = ec_GFp_simple_make_affine,
105 .points_make_affine = ec_GFp_simple_points_make_affine, 105 .points_make_affine = ec_GFp_simple_points_make_affine,
106 .mul_generator_ct = ec_GFp_simple_mul_generator_ct,
107 .mul_single_ct = ec_GFp_simple_mul_single_ct,
108 .mul_double_nonct = ec_GFp_simple_mul_double_nonct,
109 .field_mul = ec_GFp_simple_field_mul, 106 .field_mul = ec_GFp_simple_field_mul,
110 .field_sqr = ec_GFp_simple_field_sqr 107 .field_sqr = ec_GFp_simple_field_sqr
111 }; 108 };
@@ -223,7 +220,7 @@ ec_GFp_simple_group_set_curve(EC_GROUP * group,
223 220
224 ret = 1; 221 ret = 1;
225 222
226 err: 223err:
227 BN_CTX_end(ctx); 224 BN_CTX_end(ctx);
228 BN_CTX_free(new_ctx); 225 BN_CTX_free(new_ctx);
229 return ret; 226 return ret;
@@ -268,7 +265,7 @@ ec_GFp_simple_group_get_curve(const EC_GROUP * group, BIGNUM * p, BIGNUM * a, BI
268 } 265 }
269 ret = 1; 266 ret = 1;
270 267
271 err: 268err:
272 BN_CTX_free(new_ctx); 269 BN_CTX_free(new_ctx);
273 return ret; 270 return ret;
274} 271}
@@ -349,7 +346,7 @@ ec_GFp_simple_group_check_discriminant(const EC_GROUP * group, BN_CTX * ctx)
349 } 346 }
350 ret = 1; 347 ret = 1;
351 348
352 err: 349err:
353 if (ctx != NULL) 350 if (ctx != NULL)
354 BN_CTX_end(ctx); 351 BN_CTX_end(ctx);
355 BN_CTX_free(new_ctx); 352 BN_CTX_free(new_ctx);
@@ -459,7 +456,7 @@ ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP * group, EC_POINT *
459 } 456 }
460 ret = 1; 457 ret = 1;
461 458
462 err: 459err:
463 BN_CTX_free(new_ctx); 460 BN_CTX_free(new_ctx);
464 return ret; 461 return ret;
465} 462}
@@ -507,7 +504,7 @@ ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP * group, const EC_P
507 504
508 ret = 1; 505 ret = 1;
509 506
510 err: 507err:
511 BN_CTX_free(new_ctx); 508 BN_CTX_free(new_ctx);
512 return ret; 509 return ret;
513} 510}
@@ -627,7 +624,7 @@ ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP * group, const EC_POIN
627 624
628 ret = 1; 625 ret = 1;
629 626
630 err: 627err:
631 BN_CTX_end(ctx); 628 BN_CTX_end(ctx);
632 BN_CTX_free(new_ctx); 629 BN_CTX_free(new_ctx);
633 return ret; 630 return ret;
@@ -814,7 +811,7 @@ ec_GFp_simple_add(const EC_GROUP * group, EC_POINT * r, const EC_POINT * a, cons
814 811
815 ret = 1; 812 ret = 1;
816 813
817 end: 814end:
818 if (ctx) /* otherwise we already called BN_CTX_end */ 815 if (ctx) /* otherwise we already called BN_CTX_end */
819 BN_CTX_end(ctx); 816 BN_CTX_end(ctx);
820 BN_CTX_free(new_ctx); 817 BN_CTX_free(new_ctx);
@@ -957,7 +954,7 @@ ec_GFp_simple_dbl(const EC_GROUP * group, EC_POINT * r, const EC_POINT * a, BN_C
957 954
958 ret = 1; 955 ret = 1;
959 956
960 err: 957err:
961 BN_CTX_end(ctx); 958 BN_CTX_end(ctx);
962 BN_CTX_free(new_ctx); 959 BN_CTX_free(new_ctx);
963 return ret; 960 return ret;
@@ -1078,7 +1075,7 @@ ec_GFp_simple_is_on_curve(const EC_GROUP * group, const EC_POINT * point, BN_CTX
1078 1075
1079 ret = (0 == BN_ucmp(tmp, rh)); 1076 ret = (0 == BN_ucmp(tmp, rh));
1080 1077
1081 err: 1078err:
1082 BN_CTX_end(ctx); 1079 BN_CTX_end(ctx);
1083 BN_CTX_free(new_ctx); 1080 BN_CTX_free(new_ctx);
1084 return ret; 1081 return ret;
@@ -1180,7 +1177,7 @@ ec_GFp_simple_cmp(const EC_GROUP * group, const EC_POINT * a, const EC_POINT * b
1180 /* points are equal */ 1177 /* points are equal */
1181 ret = 0; 1178 ret = 0;
1182 1179
1183 end: 1180end:
1184 BN_CTX_end(ctx); 1181 BN_CTX_end(ctx);
1185 BN_CTX_free(new_ctx); 1182 BN_CTX_free(new_ctx);
1186 return ret; 1183 return ret;
@@ -1218,7 +1215,7 @@ ec_GFp_simple_make_affine(const EC_GROUP * group, EC_POINT * point, BN_CTX * ctx
1218 } 1215 }
1219 ret = 1; 1216 ret = 1;
1220 1217
1221 err: 1218err:
1222 BN_CTX_end(ctx); 1219 BN_CTX_end(ctx);
1223 BN_CTX_free(new_ctx); 1220 BN_CTX_free(new_ctx);
1224 return ret; 1221 return ret;
@@ -1383,7 +1380,7 @@ ec_GFp_simple_points_make_affine(const EC_GROUP * group, size_t num, EC_POINT *
1383 1380
1384 ret = 1; 1381 ret = 1;
1385 1382
1386 err: 1383err:
1387 BN_CTX_end(ctx); 1384 BN_CTX_end(ctx);
1388 BN_CTX_free(new_ctx); 1385 BN_CTX_free(new_ctx);
1389 if (heap != NULL) { 1386 if (heap != NULL) {
@@ -1412,248 +1409,3 @@ ec_GFp_simple_field_sqr(const EC_GROUP * group, BIGNUM * r, const BIGNUM * a, BN
1412{ 1409{
1413 return BN_mod_sqr(r, a, &group->field, ctx); 1410 return BN_mod_sqr(r, a, &group->field, ctx);
1414} 1411}
1415
1416#define EC_POINT_BN_set_flags(P, flags) do { \
1417 BN_set_flags(&(P)->X, (flags)); \
1418 BN_set_flags(&(P)->Y, (flags)); \
1419 BN_set_flags(&(P)->Z, (flags)); \
1420} while(0)
1421
1422#define EC_POINT_CSWAP(c, a, b, w, t) do { \
1423 if (!BN_swap_ct(c, &(a)->X, &(b)->X, w) || \
1424 !BN_swap_ct(c, &(a)->Y, &(b)->Y, w) || \
1425 !BN_swap_ct(c, &(a)->Z, &(b)->Z, w)) \
1426 goto err; \
1427 t = ((a)->Z_is_one ^ (b)->Z_is_one) & (c); \
1428 (a)->Z_is_one ^= (t); \
1429 (b)->Z_is_one ^= (t); \
1430} while(0)
1431
1432/*
1433 * This function computes (in constant time) a point multiplication over the
1434 * EC group.
1435 *
1436 * At a high level, it is Montgomery ladder with conditional swaps.
1437 *
1438 * It performs either a fixed point multiplication
1439 * (scalar * generator)
1440 * when point is NULL, or a variable point multiplication
1441 * (scalar * point)
1442 * when point is not NULL.
1443 *
1444 * scalar should be in the range [0,n) otherwise all constant time bets are off.
1445 *
1446 * NB: This says nothing about EC_POINT_add and EC_POINT_dbl,
1447 * which of course are not constant time themselves.
1448 *
1449 * The product is stored in r.
1450 *
1451 * Returns 1 on success, 0 otherwise.
1452 */
1453static int
1454ec_GFp_simple_mul_ct(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
1455 const EC_POINT *point, BN_CTX *ctx)
1456{
1457 int i, cardinality_bits, group_top, kbit, pbit, Z_is_one;
1458 EC_POINT *s = NULL;
1459 BIGNUM *k = NULL;
1460 BIGNUM *lambda = NULL;
1461 BIGNUM *cardinality = NULL;
1462 BN_CTX *new_ctx = NULL;
1463 int ret = 0;
1464
1465 if (ctx == NULL && (ctx = new_ctx = BN_CTX_new()) == NULL)
1466 return 0;
1467
1468 BN_CTX_start(ctx);
1469
1470 if ((s = EC_POINT_new(group)) == NULL)
1471 goto err;
1472
1473 if (point == NULL) {
1474 if (!EC_POINT_copy(s, group->generator))
1475 goto err;
1476 } else {
1477 if (!EC_POINT_copy(s, point))
1478 goto err;
1479 }
1480
1481 EC_POINT_BN_set_flags(s, BN_FLG_CONSTTIME);
1482
1483 if ((cardinality = BN_CTX_get(ctx)) == NULL)
1484 goto err;
1485 if ((lambda = BN_CTX_get(ctx)) == NULL)
1486 goto err;
1487 if ((k = BN_CTX_get(ctx)) == NULL)
1488 goto err;
1489 if (!BN_mul(cardinality, &group->order, &group->cofactor, ctx))
1490 goto err;
1491
1492 /*
1493 * Group cardinalities are often on a word boundary.
1494 * So when we pad the scalar, some timing diff might
1495 * pop if it needs to be expanded due to carries.
1496 * So expand ahead of time.
1497 */
1498 cardinality_bits = BN_num_bits(cardinality);
1499 group_top = cardinality->top;
1500 if ((bn_wexpand(k, group_top + 1) == NULL) ||
1501 (bn_wexpand(lambda, group_top + 1) == NULL))
1502 goto err;
1503
1504 if (!BN_copy(k, scalar))
1505 goto err;
1506
1507 BN_set_flags(k, BN_FLG_CONSTTIME);
1508
1509 if (BN_num_bits(k) > cardinality_bits || BN_is_negative(k)) {
1510 /*
1511 * This is an unusual input, and we don't guarantee
1512 * constant-timeness
1513 */
1514 if (!BN_nnmod(k, k, cardinality, ctx))
1515 goto err;
1516 }
1517
1518 if (!BN_add(lambda, k, cardinality))
1519 goto err;
1520 BN_set_flags(lambda, BN_FLG_CONSTTIME);
1521 if (!BN_add(k, lambda, cardinality))
1522 goto err;
1523 /*
1524 * lambda := scalar + cardinality
1525 * k := scalar + 2*cardinality
1526 */
1527 kbit = BN_is_bit_set(lambda, cardinality_bits);
1528 if (!BN_swap_ct(kbit, k, lambda, group_top + 1))
1529 goto err;
1530
1531 group_top = group->field.top;
1532 if ((bn_wexpand(&s->X, group_top) == NULL) ||
1533 (bn_wexpand(&s->Y, group_top) == NULL) ||
1534 (bn_wexpand(&s->Z, group_top) == NULL) ||
1535 (bn_wexpand(&r->X, group_top) == NULL) ||
1536 (bn_wexpand(&r->Y, group_top) == NULL) ||
1537 (bn_wexpand(&r->Z, group_top) == NULL))
1538 goto err;
1539
1540 /* top bit is a 1, in a fixed pos */
1541 if (!EC_POINT_copy(r, s))
1542 goto err;
1543
1544 EC_POINT_BN_set_flags(r, BN_FLG_CONSTTIME);
1545
1546 if (!EC_POINT_dbl(group, s, s, ctx))
1547 goto err;
1548
1549 pbit = 0;
1550
1551 /*
1552 * The ladder step, with branches, is
1553 *
1554 * k[i] == 0: S = add(R, S), R = dbl(R)
1555 * k[i] == 1: R = add(S, R), S = dbl(S)
1556 *
1557 * Swapping R, S conditionally on k[i] leaves you with state
1558 *
1559 * k[i] == 0: T, U = R, S
1560 * k[i] == 1: T, U = S, R
1561 *
1562 * Then perform the ECC ops.
1563 *
1564 * U = add(T, U)
1565 * T = dbl(T)
1566 *
1567 * Which leaves you with state
1568 *
1569 * k[i] == 0: U = add(R, S), T = dbl(R)
1570 * k[i] == 1: U = add(S, R), T = dbl(S)
1571 *
1572 * Swapping T, U conditionally on k[i] leaves you with state
1573 *
1574 * k[i] == 0: R, S = T, U
1575 * k[i] == 1: R, S = U, T
1576 *
1577 * Which leaves you with state
1578 *
1579 * k[i] == 0: S = add(R, S), R = dbl(R)
1580 * k[i] == 1: R = add(S, R), S = dbl(S)
1581 *
1582 * So we get the same logic, but instead of a branch it's a
1583 * conditional swap, followed by ECC ops, then another conditional swap.
1584 *
1585 * Optimization: The end of iteration i and start of i-1 looks like
1586 *
1587 * ...
1588 * CSWAP(k[i], R, S)
1589 * ECC
1590 * CSWAP(k[i], R, S)
1591 * (next iteration)
1592 * CSWAP(k[i-1], R, S)
1593 * ECC
1594 * CSWAP(k[i-1], R, S)
1595 * ...
1596 *
1597 * So instead of two contiguous swaps, you can merge the condition
1598 * bits and do a single swap.
1599 *
1600 * k[i] k[i-1] Outcome
1601 * 0 0 No Swap
1602 * 0 1 Swap
1603 * 1 0 Swap
1604 * 1 1 No Swap
1605 *
1606 * This is XOR. pbit tracks the previous bit of k.
1607 */
1608
1609 for (i = cardinality_bits - 1; i >= 0; i--) {
1610 kbit = BN_is_bit_set(k, i) ^ pbit;
1611 EC_POINT_CSWAP(kbit, r, s, group_top, Z_is_one);
1612 if (!EC_POINT_add(group, s, r, s, ctx))
1613 goto err;
1614 if (!EC_POINT_dbl(group, r, r, ctx))
1615 goto err;
1616 /*
1617 * pbit logic merges this cswap with that of the
1618 * next iteration
1619 */
1620 pbit ^= kbit;
1621 }
1622 /* one final cswap to move the right value into r */
1623 EC_POINT_CSWAP(pbit, r, s, group_top, Z_is_one);
1624
1625 ret = 1;
1626
1627 err:
1628 EC_POINT_free(s);
1629 if (ctx != NULL)
1630 BN_CTX_end(ctx);
1631 BN_CTX_free(new_ctx);
1632
1633 return ret;
1634}
1635
1636#undef EC_POINT_BN_set_flags
1637#undef EC_POINT_CSWAP
1638
1639int
1640ec_GFp_simple_mul_generator_ct(const EC_GROUP *group, EC_POINT *r,
1641 const BIGNUM *scalar, BN_CTX *ctx)
1642{
1643 return ec_GFp_simple_mul_ct(group, r, scalar, NULL, ctx);
1644}
1645
1646int
1647ec_GFp_simple_mul_single_ct(const EC_GROUP *group, EC_POINT *r,
1648 const BIGNUM *scalar, const EC_POINT *point, BN_CTX *ctx)
1649{
1650 return ec_GFp_simple_mul_ct(group, r, scalar, point, ctx);
1651}
1652
1653int
1654ec_GFp_simple_mul_double_nonct(const EC_GROUP *group, EC_POINT *r,
1655 const BIGNUM *g_scalar, const BIGNUM *p_scalar, const EC_POINT *point,
1656 BN_CTX *ctx)
1657{
1658 return ec_wNAF_mul(group, r, g_scalar, 1, &point, &p_scalar, ctx);
1659}