|
1 | 1 | /*
|
2 | 2 | * Copyright 2014-2017 The OpenSSL Project Authors. All Rights Reserved.
|
3 | 3 | * Copyright (c) 2014, Intel Corporation. All Rights Reserved.
|
| 4 | + * Copyright (c) 2015, CloudFlare, Inc. |
4 | 5 | *
|
5 | 6 | * Licensed under the OpenSSL license (the "License"). You may not use
|
6 | 7 | * this file except in compliance with the License. You can obtain a copy
|
7 | 8 | * in the file LICENSE in the source distribution or at
|
8 | 9 | * https://www.openssl.org/source/license.html
|
9 | 10 | *
|
10 |
| - * Originally written by Shay Gueron (1, 2), and Vlad Krasnov (1) |
| 11 | + * Originally written by Shay Gueron (1, 2), and Vlad Krasnov (1, 3) |
11 | 12 | * (1) Intel Corporation, Israel Development Center, Haifa, Israel
|
12 | 13 | * (2) University of Haifa, Israel
|
| 14 | + * (3) CloudFlare, Inc. |
13 | 15 | *
|
14 | 16 | * Reference:
|
15 | 17 | * S.Gueron and V.Krasnov, "Fast Prime Field Elliptic Curve Cryptography with
|
@@ -908,7 +910,7 @@ __owur static int ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx)
|
908 | 910 | */
|
909 | 911 | #if defined(ECP_NISTZ256_AVX2)
|
910 | 912 | # if !(defined(__x86_64) || defined(__x86_64__) || \
|
911 |
| - defined(_M_AMD64) || defined(_MX64)) || \ |
| 913 | + defined(_M_AMD64) || defined(_M_X64)) || \ |
912 | 914 | !(defined(__GNUC__) || defined(_MSC_VER)) /* this is for ALIGN32 */
|
913 | 915 | # undef ECP_NISTZ256_AVX2
|
914 | 916 | # else
|
@@ -1495,6 +1497,117 @@ static int ecp_nistz256_window_have_precompute_mult(const EC_GROUP *group)
|
1495 | 1497 | return HAVEPRECOMP(group, nistz256);
|
1496 | 1498 | }
|
1497 | 1499 |
|
| 1500 | +#if defined(__x86_64) || defined(__x86_64__) || \ |
| 1501 | + defined(_M_AMD64) || defined(_M_X64) || \ |
| 1502 | + defined(__powerpc64__) || defined(_ARCH_PP64) |
| 1503 | +/* |
| 1504 | + * Montgomery mul modulo Order(P): res = a*b*2^-256 mod Order(P) |
| 1505 | + */ |
| 1506 | +void ecp_nistz256_ord_mul_mont(BN_ULONG res[P256_LIMBS], |
| 1507 | + const BN_ULONG a[P256_LIMBS], |
| 1508 | + const BN_ULONG b[P256_LIMBS]); |
| 1509 | +void ecp_nistz256_ord_sqr_mont(BN_ULONG res[P256_LIMBS], |
| 1510 | + const BN_ULONG a[P256_LIMBS], |
| 1511 | + int rep); |
| 1512 | + |
| 1513 | +static int ecp_nistz256_inv_mod_ord(const EC_GROUP *group, BIGNUM *r, |
| 1514 | + BIGNUM *x, BN_CTX *ctx) |
| 1515 | +{ |
| 1516 | + /* RR = 2^512 mod ord(p256) */ |
| 1517 | + static const BN_ULONG RR[P256_LIMBS] = { TOBN(0x83244c95,0xbe79eea2), |
| 1518 | + TOBN(0x4699799c,0x49bd6fa6), |
| 1519 | + TOBN(0x2845b239,0x2b6bec59), |
| 1520 | + TOBN(0x66e12d94,0xf3d95620) }; |
| 1521 | + /* The constant 1 (unlike ONE that is one in Montgomery representation) */ |
| 1522 | + static const BN_ULONG one[P256_LIMBS] = { TOBN(0,1),TOBN(0,0), |
| 1523 | + TOBN(0,0),TOBN(0,0) }; |
| 1524 | + /* expLo - the low 128bit of the exponent we use (ord(p256) - 2), |
| 1525 | + * split into 4bit windows */ |
| 1526 | + static const unsigned char expLo[32] = { 0xb,0xc,0xe,0x6,0xf,0xa,0xa,0xd, |
| 1527 | + 0xa,0x7,0x1,0x7,0x9,0xe,0x8,0x4, |
| 1528 | + 0xf,0x3,0xb,0x9,0xc,0xa,0xc,0x2, |
| 1529 | + 0xf,0xc,0x6,0x3,0x2,0x5,0x4,0xf }; |
| 1530 | + /* |
| 1531 | + * We don't use entry 0 in the table, so we omit it and address |
| 1532 | + * with -1 offset. |
| 1533 | + */ |
| 1534 | + BN_ULONG table[15][P256_LIMBS]; |
| 1535 | + BN_ULONG out[P256_LIMBS], t[P256_LIMBS]; |
| 1536 | + int i, ret = 0; |
| 1537 | + |
| 1538 | + /* |
| 1539 | + * Catch allocation failure early. |
| 1540 | + */ |
| 1541 | + if (bn_wexpand(r, P256_LIMBS) == NULL) { |
| 1542 | + ECerr(EC_F_ECP_NISTZ256_INV_MOD_ORD, ERR_R_BN_LIB); |
| 1543 | + goto err; |
| 1544 | + } |
| 1545 | + |
| 1546 | + if ((BN_num_bits(x) > 256) || BN_is_negative(x)) { |
| 1547 | + BIGNUM *tmp; |
| 1548 | + |
| 1549 | + if ((tmp = BN_CTX_get(ctx)) == NULL |
| 1550 | + || !BN_nnmod(tmp, x, group->order, ctx)) { |
| 1551 | + ECerr(EC_F_ECP_NISTZ256_INV_MOD_ORD, ERR_R_BN_LIB); |
| 1552 | + goto err; |
| 1553 | + } |
| 1554 | + x = tmp; |
| 1555 | + } |
| 1556 | + |
| 1557 | + if (!ecp_nistz256_bignum_to_field_elem(t, x)) { |
| 1558 | + ECerr(EC_F_ECP_NISTZ256_INV_MOD_ORD, EC_R_COORDINATES_OUT_OF_RANGE); |
| 1559 | + goto err; |
| 1560 | + } |
| 1561 | + |
| 1562 | + ecp_nistz256_ord_mul_mont(table[0], t, RR); |
| 1563 | + for (i = 2; i < 16; i += 2) { |
| 1564 | + ecp_nistz256_ord_sqr_mont(table[i-1], table[i/2-1], 1); |
| 1565 | + ecp_nistz256_ord_mul_mont(table[i], table[i-1], table[0]); |
| 1566 | + } |
| 1567 | + |
| 1568 | + /* |
| 1569 | + * The top 128bit of the exponent are highly redudndant, so we |
| 1570 | + * perform an optimized flow |
| 1571 | + */ |
| 1572 | + ecp_nistz256_ord_sqr_mont(t, table[15-1], 4); /* f0 */ |
| 1573 | + ecp_nistz256_ord_mul_mont(t, t, table[15-1]); /* ff */ |
| 1574 | + |
| 1575 | + ecp_nistz256_ord_sqr_mont(out, t, 8); /* ff00 */ |
| 1576 | + ecp_nistz256_ord_mul_mont(out, out, t); /* ffff */ |
| 1577 | + |
| 1578 | + ecp_nistz256_ord_sqr_mont(t, out, 16); /* ffff0000 */ |
| 1579 | + ecp_nistz256_ord_mul_mont(t, t, out); /* ffffffff */ |
| 1580 | + |
| 1581 | + ecp_nistz256_ord_sqr_mont(out, t, 64); /* ffffffff0000000000000000 */ |
| 1582 | + ecp_nistz256_ord_mul_mont(out, out, t); /* ffffffff00000000ffffffff */ |
| 1583 | + |
| 1584 | + ecp_nistz256_ord_sqr_mont(out, out, 32); /* ffffffff00000000ffffffff00000000 */ |
| 1585 | + ecp_nistz256_ord_mul_mont(out, out, t); /* ffffffff00000000ffffffffffffffff */ |
| 1586 | + |
| 1587 | + /* |
| 1588 | + * The bottom 128 bit of the exponent are easier done with a table |
| 1589 | + */ |
| 1590 | + for(i = 0; i < 32; i++) { |
| 1591 | + ecp_nistz256_ord_sqr_mont(out, out, 4); |
| 1592 | + /* The exponent is public, no need in constant-time access */ |
| 1593 | + ecp_nistz256_ord_mul_mont(out, out, table[expLo[i]-1]); |
| 1594 | + } |
| 1595 | + ecp_nistz256_ord_mul_mont(out, out, one); |
| 1596 | + |
| 1597 | + /* |
| 1598 | + * Can't fail, but check return code to be consistent anyway. |
| 1599 | + */ |
| 1600 | + if (!bn_set_words(r, out, P256_LIMBS)) |
| 1601 | + goto err; |
| 1602 | + |
| 1603 | + ret = 1; |
| 1604 | +err: |
| 1605 | + return ret; |
| 1606 | +} |
| 1607 | +#else |
| 1608 | +# define ecp_nistz256_inv_mod_ord NULL |
| 1609 | +#endif |
| 1610 | + |
1498 | 1611 | const EC_METHOD *EC_GFp_nistz256_method(void)
|
1499 | 1612 | {
|
1500 | 1613 | static const EC_METHOD ret = {
|
@@ -1544,7 +1657,8 @@ const EC_METHOD *EC_GFp_nistz256_method(void)
|
1544 | 1657 | ec_key_simple_generate_public_key,
|
1545 | 1658 | 0, /* keycopy */
|
1546 | 1659 | 0, /* keyfinish */
|
1547 |
| - ecdh_simple_compute_key |
| 1660 | + ecdh_simple_compute_key, |
| 1661 | + ecp_nistz256_inv_mod_ord /* can be #defined-ed NULL */ |
1548 | 1662 | };
|
1549 | 1663 |
|
1550 | 1664 | return &ret;
|
|
0 commit comments