diff options
author | jsg <> | 2018-07-15 05:38:48 +0000 |
---|---|---|
committer | jsg <> | 2018-07-15 05:38:48 +0000 |
commit | 5a27d0fd33187fa17d3aa1b151b981a5434a200f (patch) | |
tree | 7b8b0c999036035f793976bbe0b018b39f74e217 /src/lib/libcrypto/ec/ecp_smpl.c | |
parent | 4ffff01bec4bc66afd2ef22fba624a0d3cffdc04 (diff) | |
download | openbsd-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.c | 274 |
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: | 223 | err: |
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: | 268 | err: |
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: | 349 | err: |
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: | 459 | err: |
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: | 507 | err: |
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: | 627 | err: |
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: | 814 | end: |
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: | 957 | err: |
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: | 1078 | err: |
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: | 1180 | end: |
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: | 1218 | err: |
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: | 1383 | err: |
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 | */ | ||
1453 | static int | ||
1454 | ec_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 | |||
1639 | int | ||
1640 | ec_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 | |||
1646 | int | ||
1647 | ec_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 | |||
1653 | int | ||
1654 | ec_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 | } | ||