1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/freebl/ecl/ecl_mult.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,322 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "mpi.h" 1.9 +#include "mplogic.h" 1.10 +#include "ecl.h" 1.11 +#include "ecl-priv.h" 1.12 +#include <stdlib.h> 1.13 + 1.14 +/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k * P(x, 1.15 + * y). If x, y = NULL, then P is assumed to be the generator (base point) 1.16 + * of the group of points on the elliptic curve. Input and output values 1.17 + * are assumed to be NOT field-encoded. */ 1.18 +mp_err 1.19 +ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px, 1.20 + const mp_int *py, mp_int *rx, mp_int *ry) 1.21 +{ 1.22 + mp_err res = MP_OKAY; 1.23 + mp_int kt; 1.24 + 1.25 + ARGCHK((k != NULL) && (group != NULL), MP_BADARG); 1.26 + MP_DIGITS(&kt) = 0; 1.27 + 1.28 + /* want scalar to be less than or equal to group order */ 1.29 + if (mp_cmp(k, &group->order) > 0) { 1.30 + MP_CHECKOK(mp_init(&kt)); 1.31 + MP_CHECKOK(mp_mod(k, &group->order, &kt)); 1.32 + } else { 1.33 + MP_SIGN(&kt) = MP_ZPOS; 1.34 + MP_USED(&kt) = MP_USED(k); 1.35 + MP_ALLOC(&kt) = MP_ALLOC(k); 1.36 + MP_DIGITS(&kt) = MP_DIGITS(k); 1.37 + } 1.38 + 1.39 + if ((px == NULL) || (py == NULL)) { 1.40 + if (group->base_point_mul) { 1.41 + MP_CHECKOK(group->base_point_mul(&kt, rx, ry, group)); 1.42 + } else { 1.43 + MP_CHECKOK(group-> 1.44 + point_mul(&kt, &group->genx, &group->geny, rx, ry, 1.45 + group)); 1.46 + } 1.47 + } else { 1.48 + if (group->meth->field_enc) { 1.49 + MP_CHECKOK(group->meth->field_enc(px, rx, group->meth)); 1.50 + MP_CHECKOK(group->meth->field_enc(py, ry, group->meth)); 1.51 + MP_CHECKOK(group->point_mul(&kt, rx, ry, rx, ry, group)); 1.52 + } else { 1.53 + MP_CHECKOK(group->point_mul(&kt, px, py, rx, ry, group)); 1.54 + } 1.55 + } 1.56 + if (group->meth->field_dec) { 1.57 + MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth)); 1.58 + MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth)); 1.59 + } 1.60 + 1.61 + CLEANUP: 1.62 + if (MP_DIGITS(&kt) != MP_DIGITS(k)) { 1.63 + mp_clear(&kt); 1.64 + } 1.65 + return res; 1.66 +} 1.67 + 1.68 +/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G + 1.69 + * k2 * P(x, y), where G is the generator (base point) of the group of 1.70 + * points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL. 1.71 + * Input and output values are assumed to be NOT field-encoded. */ 1.72 +mp_err 1.73 +ec_pts_mul_basic(const mp_int *k1, const mp_int *k2, const mp_int *px, 1.74 + const mp_int *py, mp_int *rx, mp_int *ry, 1.75 + const ECGroup *group) 1.76 +{ 1.77 + mp_err res = MP_OKAY; 1.78 + mp_int sx, sy; 1.79 + 1.80 + ARGCHK(group != NULL, MP_BADARG); 1.81 + ARGCHK(!((k1 == NULL) 1.82 + && ((k2 == NULL) || (px == NULL) 1.83 + || (py == NULL))), MP_BADARG); 1.84 + 1.85 + /* if some arguments are not defined used ECPoint_mul */ 1.86 + if (k1 == NULL) { 1.87 + return ECPoint_mul(group, k2, px, py, rx, ry); 1.88 + } else if ((k2 == NULL) || (px == NULL) || (py == NULL)) { 1.89 + return ECPoint_mul(group, k1, NULL, NULL, rx, ry); 1.90 + } 1.91 + 1.92 + MP_DIGITS(&sx) = 0; 1.93 + MP_DIGITS(&sy) = 0; 1.94 + MP_CHECKOK(mp_init(&sx)); 1.95 + MP_CHECKOK(mp_init(&sy)); 1.96 + 1.97 + MP_CHECKOK(ECPoint_mul(group, k1, NULL, NULL, &sx, &sy)); 1.98 + MP_CHECKOK(ECPoint_mul(group, k2, px, py, rx, ry)); 1.99 + 1.100 + if (group->meth->field_enc) { 1.101 + MP_CHECKOK(group->meth->field_enc(&sx, &sx, group->meth)); 1.102 + MP_CHECKOK(group->meth->field_enc(&sy, &sy, group->meth)); 1.103 + MP_CHECKOK(group->meth->field_enc(rx, rx, group->meth)); 1.104 + MP_CHECKOK(group->meth->field_enc(ry, ry, group->meth)); 1.105 + } 1.106 + 1.107 + MP_CHECKOK(group->point_add(&sx, &sy, rx, ry, rx, ry, group)); 1.108 + 1.109 + if (group->meth->field_dec) { 1.110 + MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth)); 1.111 + MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth)); 1.112 + } 1.113 + 1.114 + CLEANUP: 1.115 + mp_clear(&sx); 1.116 + mp_clear(&sy); 1.117 + return res; 1.118 +} 1.119 + 1.120 +/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G + 1.121 + * k2 * P(x, y), where G is the generator (base point) of the group of 1.122 + * points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL. 1.123 + * Input and output values are assumed to be NOT field-encoded. Uses 1.124 + * algorithm 15 (simultaneous multiple point multiplication) from Brown, 1.125 + * Hankerson, Lopez, Menezes. Software Implementation of the NIST 1.126 + * Elliptic Curves over Prime Fields. */ 1.127 +mp_err 1.128 +ec_pts_mul_simul_w2(const mp_int *k1, const mp_int *k2, const mp_int *px, 1.129 + const mp_int *py, mp_int *rx, mp_int *ry, 1.130 + const ECGroup *group) 1.131 +{ 1.132 + mp_err res = MP_OKAY; 1.133 + mp_int precomp[4][4][2]; 1.134 + const mp_int *a, *b; 1.135 + int i, j; 1.136 + int ai, bi, d; 1.137 + 1.138 + ARGCHK(group != NULL, MP_BADARG); 1.139 + ARGCHK(!((k1 == NULL) 1.140 + && ((k2 == NULL) || (px == NULL) 1.141 + || (py == NULL))), MP_BADARG); 1.142 + 1.143 + /* if some arguments are not defined used ECPoint_mul */ 1.144 + if (k1 == NULL) { 1.145 + return ECPoint_mul(group, k2, px, py, rx, ry); 1.146 + } else if ((k2 == NULL) || (px == NULL) || (py == NULL)) { 1.147 + return ECPoint_mul(group, k1, NULL, NULL, rx, ry); 1.148 + } 1.149 + 1.150 + /* initialize precomputation table */ 1.151 + for (i = 0; i < 4; i++) { 1.152 + for (j = 0; j < 4; j++) { 1.153 + MP_DIGITS(&precomp[i][j][0]) = 0; 1.154 + MP_DIGITS(&precomp[i][j][1]) = 0; 1.155 + } 1.156 + } 1.157 + for (i = 0; i < 4; i++) { 1.158 + for (j = 0; j < 4; j++) { 1.159 + MP_CHECKOK( mp_init_size(&precomp[i][j][0], 1.160 + ECL_MAX_FIELD_SIZE_DIGITS) ); 1.161 + MP_CHECKOK( mp_init_size(&precomp[i][j][1], 1.162 + ECL_MAX_FIELD_SIZE_DIGITS) ); 1.163 + } 1.164 + } 1.165 + 1.166 + /* fill precomputation table */ 1.167 + /* assign {k1, k2} = {a, b} such that len(a) >= len(b) */ 1.168 + if (mpl_significant_bits(k1) < mpl_significant_bits(k2)) { 1.169 + a = k2; 1.170 + b = k1; 1.171 + if (group->meth->field_enc) { 1.172 + MP_CHECKOK(group->meth-> 1.173 + field_enc(px, &precomp[1][0][0], group->meth)); 1.174 + MP_CHECKOK(group->meth-> 1.175 + field_enc(py, &precomp[1][0][1], group->meth)); 1.176 + } else { 1.177 + MP_CHECKOK(mp_copy(px, &precomp[1][0][0])); 1.178 + MP_CHECKOK(mp_copy(py, &precomp[1][0][1])); 1.179 + } 1.180 + MP_CHECKOK(mp_copy(&group->genx, &precomp[0][1][0])); 1.181 + MP_CHECKOK(mp_copy(&group->geny, &precomp[0][1][1])); 1.182 + } else { 1.183 + a = k1; 1.184 + b = k2; 1.185 + MP_CHECKOK(mp_copy(&group->genx, &precomp[1][0][0])); 1.186 + MP_CHECKOK(mp_copy(&group->geny, &precomp[1][0][1])); 1.187 + if (group->meth->field_enc) { 1.188 + MP_CHECKOK(group->meth-> 1.189 + field_enc(px, &precomp[0][1][0], group->meth)); 1.190 + MP_CHECKOK(group->meth-> 1.191 + field_enc(py, &precomp[0][1][1], group->meth)); 1.192 + } else { 1.193 + MP_CHECKOK(mp_copy(px, &precomp[0][1][0])); 1.194 + MP_CHECKOK(mp_copy(py, &precomp[0][1][1])); 1.195 + } 1.196 + } 1.197 + /* precompute [*][0][*] */ 1.198 + mp_zero(&precomp[0][0][0]); 1.199 + mp_zero(&precomp[0][0][1]); 1.200 + MP_CHECKOK(group-> 1.201 + point_dbl(&precomp[1][0][0], &precomp[1][0][1], 1.202 + &precomp[2][0][0], &precomp[2][0][1], group)); 1.203 + MP_CHECKOK(group-> 1.204 + point_add(&precomp[1][0][0], &precomp[1][0][1], 1.205 + &precomp[2][0][0], &precomp[2][0][1], 1.206 + &precomp[3][0][0], &precomp[3][0][1], group)); 1.207 + /* precompute [*][1][*] */ 1.208 + for (i = 1; i < 4; i++) { 1.209 + MP_CHECKOK(group-> 1.210 + point_add(&precomp[0][1][0], &precomp[0][1][1], 1.211 + &precomp[i][0][0], &precomp[i][0][1], 1.212 + &precomp[i][1][0], &precomp[i][1][1], group)); 1.213 + } 1.214 + /* precompute [*][2][*] */ 1.215 + MP_CHECKOK(group-> 1.216 + point_dbl(&precomp[0][1][0], &precomp[0][1][1], 1.217 + &precomp[0][2][0], &precomp[0][2][1], group)); 1.218 + for (i = 1; i < 4; i++) { 1.219 + MP_CHECKOK(group-> 1.220 + point_add(&precomp[0][2][0], &precomp[0][2][1], 1.221 + &precomp[i][0][0], &precomp[i][0][1], 1.222 + &precomp[i][2][0], &precomp[i][2][1], group)); 1.223 + } 1.224 + /* precompute [*][3][*] */ 1.225 + MP_CHECKOK(group-> 1.226 + point_add(&precomp[0][1][0], &precomp[0][1][1], 1.227 + &precomp[0][2][0], &precomp[0][2][1], 1.228 + &precomp[0][3][0], &precomp[0][3][1], group)); 1.229 + for (i = 1; i < 4; i++) { 1.230 + MP_CHECKOK(group-> 1.231 + point_add(&precomp[0][3][0], &precomp[0][3][1], 1.232 + &precomp[i][0][0], &precomp[i][0][1], 1.233 + &precomp[i][3][0], &precomp[i][3][1], group)); 1.234 + } 1.235 + 1.236 + d = (mpl_significant_bits(a) + 1) / 2; 1.237 + 1.238 + /* R = inf */ 1.239 + mp_zero(rx); 1.240 + mp_zero(ry); 1.241 + 1.242 + for (i = d - 1; i >= 0; i--) { 1.243 + ai = MP_GET_BIT(a, 2 * i + 1); 1.244 + ai <<= 1; 1.245 + ai |= MP_GET_BIT(a, 2 * i); 1.246 + bi = MP_GET_BIT(b, 2 * i + 1); 1.247 + bi <<= 1; 1.248 + bi |= MP_GET_BIT(b, 2 * i); 1.249 + /* R = 2^2 * R */ 1.250 + MP_CHECKOK(group->point_dbl(rx, ry, rx, ry, group)); 1.251 + MP_CHECKOK(group->point_dbl(rx, ry, rx, ry, group)); 1.252 + /* R = R + (ai * A + bi * B) */ 1.253 + MP_CHECKOK(group-> 1.254 + point_add(rx, ry, &precomp[ai][bi][0], 1.255 + &precomp[ai][bi][1], rx, ry, group)); 1.256 + } 1.257 + 1.258 + if (group->meth->field_dec) { 1.259 + MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth)); 1.260 + MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth)); 1.261 + } 1.262 + 1.263 + CLEANUP: 1.264 + for (i = 0; i < 4; i++) { 1.265 + for (j = 0; j < 4; j++) { 1.266 + mp_clear(&precomp[i][j][0]); 1.267 + mp_clear(&precomp[i][j][1]); 1.268 + } 1.269 + } 1.270 + return res; 1.271 +} 1.272 + 1.273 +/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G + 1.274 + * k2 * P(x, y), where G is the generator (base point) of the group of 1.275 + * points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL. 1.276 + * Input and output values are assumed to be NOT field-encoded. */ 1.277 +mp_err 1.278 +ECPoints_mul(const ECGroup *group, const mp_int *k1, const mp_int *k2, 1.279 + const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry) 1.280 +{ 1.281 + mp_err res = MP_OKAY; 1.282 + mp_int k1t, k2t; 1.283 + const mp_int *k1p, *k2p; 1.284 + 1.285 + MP_DIGITS(&k1t) = 0; 1.286 + MP_DIGITS(&k2t) = 0; 1.287 + 1.288 + ARGCHK(group != NULL, MP_BADARG); 1.289 + 1.290 + /* want scalar to be less than or equal to group order */ 1.291 + if (k1 != NULL) { 1.292 + if (mp_cmp(k1, &group->order) >= 0) { 1.293 + MP_CHECKOK(mp_init(&k1t)); 1.294 + MP_CHECKOK(mp_mod(k1, &group->order, &k1t)); 1.295 + k1p = &k1t; 1.296 + } else { 1.297 + k1p = k1; 1.298 + } 1.299 + } else { 1.300 + k1p = k1; 1.301 + } 1.302 + if (k2 != NULL) { 1.303 + if (mp_cmp(k2, &group->order) >= 0) { 1.304 + MP_CHECKOK(mp_init(&k2t)); 1.305 + MP_CHECKOK(mp_mod(k2, &group->order, &k2t)); 1.306 + k2p = &k2t; 1.307 + } else { 1.308 + k2p = k2; 1.309 + } 1.310 + } else { 1.311 + k2p = k2; 1.312 + } 1.313 + 1.314 + /* if points_mul is defined, then use it */ 1.315 + if (group->points_mul) { 1.316 + res = group->points_mul(k1p, k2p, px, py, rx, ry, group); 1.317 + } else { 1.318 + res = ec_pts_mul_simul_w2(k1p, k2p, px, py, rx, ry, group); 1.319 + } 1.320 + 1.321 + CLEANUP: 1.322 + mp_clear(&k1t); 1.323 + mp_clear(&k2t); 1.324 + return res; 1.325 +}