diff options
Diffstat (limited to '')
-rw-r--r-- | security/nss/lib/freebl/ecl/ecp_secp521r1_wrap.c | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/security/nss/lib/freebl/ecl/ecp_secp521r1_wrap.c b/security/nss/lib/freebl/ecl/ecp_secp521r1_wrap.c new file mode 100644 index 0000000000..b767624966 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp_secp521r1_wrap.c @@ -0,0 +1,255 @@ +/*- + * MIT License + * - + * Copyright (c) 2020 Luis Rivera-Zamarripa, Jesús-Javier Chi-Domínguez, Billy Bob Brumley + * - + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * - + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * - + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#undef RADIX +#include "ecp.h" +#include "ecp_secp521r1.h" +#include "mpi-priv.h" +#include "mplogic.h" + +/*- + * reverse bytes -- total hack + */ +#define MP_BE2LE(a) \ + do { \ + unsigned char z_bswap; \ + z_bswap = a[0]; \ + a[0] = a[65]; \ + a[65] = z_bswap; \ + z_bswap = a[1]; \ + a[1] = a[64]; \ + a[64] = z_bswap; \ + z_bswap = a[2]; \ + a[2] = a[63]; \ + a[63] = z_bswap; \ + z_bswap = a[3]; \ + a[3] = a[62]; \ + a[62] = z_bswap; \ + z_bswap = a[4]; \ + a[4] = a[61]; \ + a[61] = z_bswap; \ + z_bswap = a[5]; \ + a[5] = a[60]; \ + a[60] = z_bswap; \ + z_bswap = a[6]; \ + a[6] = a[59]; \ + a[59] = z_bswap; \ + z_bswap = a[7]; \ + a[7] = a[58]; \ + a[58] = z_bswap; \ + z_bswap = a[8]; \ + a[8] = a[57]; \ + a[57] = z_bswap; \ + z_bswap = a[9]; \ + a[9] = a[56]; \ + a[56] = z_bswap; \ + z_bswap = a[10]; \ + a[10] = a[55]; \ + a[55] = z_bswap; \ + z_bswap = a[11]; \ + a[11] = a[54]; \ + a[54] = z_bswap; \ + z_bswap = a[12]; \ + a[12] = a[53]; \ + a[53] = z_bswap; \ + z_bswap = a[13]; \ + a[13] = a[52]; \ + a[52] = z_bswap; \ + z_bswap = a[14]; \ + a[14] = a[51]; \ + a[51] = z_bswap; \ + z_bswap = a[15]; \ + a[15] = a[50]; \ + a[50] = z_bswap; \ + z_bswap = a[16]; \ + a[16] = a[49]; \ + a[49] = z_bswap; \ + z_bswap = a[17]; \ + a[17] = a[48]; \ + a[48] = z_bswap; \ + z_bswap = a[18]; \ + a[18] = a[47]; \ + a[47] = z_bswap; \ + z_bswap = a[19]; \ + a[19] = a[46]; \ + a[46] = z_bswap; \ + z_bswap = a[20]; \ + a[20] = a[45]; \ + a[45] = z_bswap; \ + z_bswap = a[21]; \ + a[21] = a[44]; \ + a[44] = z_bswap; \ + z_bswap = a[22]; \ + a[22] = a[43]; \ + a[43] = z_bswap; \ + z_bswap = a[23]; \ + a[23] = a[42]; \ + a[42] = z_bswap; \ + z_bswap = a[24]; \ + a[24] = a[41]; \ + a[41] = z_bswap; \ + z_bswap = a[25]; \ + a[25] = a[40]; \ + a[40] = z_bswap; \ + z_bswap = a[26]; \ + a[26] = a[39]; \ + a[39] = z_bswap; \ + z_bswap = a[27]; \ + a[27] = a[38]; \ + a[38] = z_bswap; \ + z_bswap = a[28]; \ + a[28] = a[37]; \ + a[37] = z_bswap; \ + z_bswap = a[29]; \ + a[29] = a[36]; \ + a[36] = z_bswap; \ + z_bswap = a[30]; \ + a[30] = a[35]; \ + a[35] = z_bswap; \ + z_bswap = a[31]; \ + a[31] = a[34]; \ + a[34] = z_bswap; \ + z_bswap = a[32]; \ + a[32] = a[33]; \ + a[33] = z_bswap; \ + } while (0) + +static mp_err +point_mul_g_secp521r1_wrap(const mp_int *n, mp_int *out_x, + mp_int *out_y, const ECGroup *group) +{ + unsigned char b_x[66]; + unsigned char b_y[66]; + unsigned char b_n[66]; + mp_err res; + + ARGCHK(n != NULL && out_x != NULL && out_y != NULL, MP_BADARG); + + /* fail on out of range scalars */ + if (mpl_significant_bits(n) > 521 || mp_cmp_z(n) != MP_GT) + return MP_RANGE; + + MP_CHECKOK(mp_to_fixlen_octets(n, b_n, 66)); + MP_BE2LE(b_n); + point_mul_g_secp521r1(b_x, b_y, b_n); + MP_BE2LE(b_x); + MP_BE2LE(b_y); + MP_CHECKOK(mp_read_unsigned_octets(out_x, b_x, 66)); + MP_CHECKOK(mp_read_unsigned_octets(out_y, b_y, 66)); + +CLEANUP: + return res; +} + +static mp_err +point_mul_secp521r1_wrap(const mp_int *n, const mp_int *in_x, + const mp_int *in_y, mp_int *out_x, + mp_int *out_y, const ECGroup *group) +{ + unsigned char b_x[66]; + unsigned char b_y[66]; + unsigned char b_n[66]; + mp_err res; + + ARGCHK(n != NULL && in_x != NULL && in_y != NULL && out_x != NULL && + out_y != NULL, + MP_BADARG); + + /* fail on out of range scalars */ + if (mpl_significant_bits(n) > 521 || mp_cmp_z(n) != MP_GT) + return MP_RANGE; + + MP_CHECKOK(mp_to_fixlen_octets(n, b_n, 66)); + MP_CHECKOK(mp_to_fixlen_octets(in_x, b_x, 66)); + MP_CHECKOK(mp_to_fixlen_octets(in_y, b_y, 66)); + MP_BE2LE(b_x); + MP_BE2LE(b_y); + MP_BE2LE(b_n); + point_mul_secp521r1(b_x, b_y, b_n, b_x, b_y); + MP_BE2LE(b_x); + MP_BE2LE(b_y); + MP_CHECKOK(mp_read_unsigned_octets(out_x, b_x, 66)); + MP_CHECKOK(mp_read_unsigned_octets(out_y, b_y, 66)); + +CLEANUP: + return res; +} + +static mp_err +point_mul_two_secp521r1_wrap(const mp_int *n1, const mp_int *n2, + const mp_int *in_x, + const mp_int *in_y, mp_int *out_x, + mp_int *out_y, + const ECGroup *group) +{ + unsigned char b_x[66]; + unsigned char b_y[66]; + unsigned char b_n1[66]; + unsigned char b_n2[66]; + mp_err res; + + /* If n2 == NULL or 0, this is just a base-point multiplication. */ + if (n2 == NULL || mp_cmp_z(n2) == MP_EQ) + return point_mul_g_secp521r1_wrap(n1, out_x, out_y, group); + + /* If n1 == NULL or 0, this is just an arbitary-point multiplication. */ + if (n1 == NULL || mp_cmp_z(n1) == MP_EQ) + return point_mul_secp521r1_wrap(n2, in_x, in_y, out_x, out_y, group); + + ARGCHK(in_x != NULL && in_y != NULL && out_x != NULL && out_y != NULL, + MP_BADARG); + + /* fail on out of range scalars */ + if (mpl_significant_bits(n1) > 521 || mp_cmp_z(n1) != MP_GT || + mpl_significant_bits(n2) > 521 || mp_cmp_z(n2) != MP_GT) + return MP_RANGE; + + MP_CHECKOK(mp_to_fixlen_octets(n1, b_n1, 66)); + MP_CHECKOK(mp_to_fixlen_octets(n2, b_n2, 66)); + MP_CHECKOK(mp_to_fixlen_octets(in_x, b_x, 66)); + MP_CHECKOK(mp_to_fixlen_octets(in_y, b_y, 66)); + MP_BE2LE(b_x); + MP_BE2LE(b_y); + MP_BE2LE(b_n1); + MP_BE2LE(b_n2); + point_mul_two_secp521r1(b_x, b_y, b_n1, b_n2, b_x, b_y); + MP_BE2LE(b_x); + MP_BE2LE(b_y); + MP_CHECKOK(mp_read_unsigned_octets(out_x, b_x, 66)); + MP_CHECKOK(mp_read_unsigned_octets(out_y, b_y, 66)); + +CLEANUP: + return res; +} + +mp_err +ec_group_set_secp521r1(ECGroup *group, ECCurveName name) +{ + if (name == ECCurve_NIST_P521) { + group->base_point_mul = &point_mul_g_secp521r1_wrap; + group->point_mul = &point_mul_secp521r1_wrap; + group->points_mul = &point_mul_two_secp521r1_wrap; + } + return MP_OKAY; +} |