summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/ec/ecp_smpl.c
diff options
context:
space:
mode:
authorjsg <>2018-07-15 05:38:48 +0000
committerjsg <>2018-07-15 05:38:48 +0000
commit5a27d0fd33187fa17d3aa1b151b981a5434a200f (patch)
tree7b8b0c999036035f793976bbe0b018b39f74e217 /src/lib/libcrypto/ec/ecp_smpl.c
parent4ffff01bec4bc66afd2ef22fba624a0d3cffdc04 (diff)
downloadopenbsd-5a27d0fd33187fa17d3aa1b151b981a5434a200f.tar.gz
openbsd-5a27d0fd33187fa17d3aa1b151b981a5434a200f.tar.bz2
openbsd-5a27d0fd33187fa17d3aa1b151b981a5434a200f.zip
back out ecc constant time changes
after the constant time commits various regress tests started failing on sparc64 ssh t9, libcrypto ec ecdh ecdsa and trying to ssh out resulted in 'invalid elliptic curve value' ok tb@
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}