| OLD | NEW |
| (Empty) |
| 1 /* This Source Code Form is subject to the terms of the Mozilla Public | |
| 2 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
| 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
| 4 | |
| 5 #include "mpi.h" | |
| 6 #include "mplogic.h" | |
| 7 #include "ecl.h" | |
| 8 #include "ecl-priv.h" | |
| 9 #include <stdlib.h> | |
| 10 | |
| 11 /* Elliptic curve scalar-point multiplication. Computes R(x, y) = k * P(x, | |
| 12 * y). If x, y = NULL, then P is assumed to be the generator (base point) | |
| 13 * of the group of points on the elliptic curve. Input and output values | |
| 14 * are assumed to be NOT field-encoded. */ | |
| 15 mp_err | |
| 16 ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px, | |
| 17 const mp_int *py, mp_int *rx, mp_int *ry) | |
| 18 { | |
| 19 mp_err res = MP_OKAY; | |
| 20 mp_int kt; | |
| 21 | |
| 22 ARGCHK((k != NULL) && (group != NULL), MP_BADARG); | |
| 23 MP_DIGITS(&kt) = 0; | |
| 24 | |
| 25 /* want scalar to be less than or equal to group order */ | |
| 26 if (mp_cmp(k, &group->order) > 0) { | |
| 27 MP_CHECKOK(mp_init(&kt)); | |
| 28 MP_CHECKOK(mp_mod(k, &group->order, &kt)); | |
| 29 } else { | |
| 30 MP_SIGN(&kt) = MP_ZPOS; | |
| 31 MP_USED(&kt) = MP_USED(k); | |
| 32 MP_ALLOC(&kt) = MP_ALLOC(k); | |
| 33 MP_DIGITS(&kt) = MP_DIGITS(k); | |
| 34 } | |
| 35 | |
| 36 if ((px == NULL) || (py == NULL)) { | |
| 37 if (group->base_point_mul) { | |
| 38 MP_CHECKOK(group->base_point_mul(&kt, rx, ry, group)); | |
| 39 } else { | |
| 40 MP_CHECKOK(group-> | |
| 41 point_mul(&kt, &group->genx, &group->
geny, rx, ry, | |
| 42 group)); | |
| 43 } | |
| 44 } else { | |
| 45 if (group->meth->field_enc) { | |
| 46 MP_CHECKOK(group->meth->field_enc(px, rx, group->meth)); | |
| 47 MP_CHECKOK(group->meth->field_enc(py, ry, group->meth)); | |
| 48 MP_CHECKOK(group->point_mul(&kt, rx, ry, rx, ry, group))
; | |
| 49 } else { | |
| 50 MP_CHECKOK(group->point_mul(&kt, px, py, rx, ry, group))
; | |
| 51 } | |
| 52 } | |
| 53 if (group->meth->field_dec) { | |
| 54 MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth)); | |
| 55 MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth)); | |
| 56 } | |
| 57 | |
| 58 CLEANUP: | |
| 59 if (MP_DIGITS(&kt) != MP_DIGITS(k)) { | |
| 60 mp_clear(&kt); | |
| 61 } | |
| 62 return res; | |
| 63 } | |
| 64 | |
| 65 /* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G + | |
| 66 * k2 * P(x, y), where G is the generator (base point) of the group of | |
| 67 * points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL. | |
| 68 * Input and output values are assumed to be NOT field-encoded. */ | |
| 69 mp_err | |
| 70 ec_pts_mul_basic(const mp_int *k1, const mp_int *k2, const mp_int *px, | |
| 71 const mp_int *py, mp_int *rx, mp_int *ry, | |
| 72 const ECGroup *group) | |
| 73 { | |
| 74 mp_err res = MP_OKAY; | |
| 75 mp_int sx, sy; | |
| 76 | |
| 77 ARGCHK(group != NULL, MP_BADARG); | |
| 78 ARGCHK(!((k1 == NULL) | |
| 79 && ((k2 == NULL) || (px == NULL) | |
| 80 || (py == NULL))), MP_BADARG); | |
| 81 | |
| 82 /* if some arguments are not defined used ECPoint_mul */ | |
| 83 if (k1 == NULL) { | |
| 84 return ECPoint_mul(group, k2, px, py, rx, ry); | |
| 85 } else if ((k2 == NULL) || (px == NULL) || (py == NULL)) { | |
| 86 return ECPoint_mul(group, k1, NULL, NULL, rx, ry); | |
| 87 } | |
| 88 | |
| 89 MP_DIGITS(&sx) = 0; | |
| 90 MP_DIGITS(&sy) = 0; | |
| 91 MP_CHECKOK(mp_init(&sx)); | |
| 92 MP_CHECKOK(mp_init(&sy)); | |
| 93 | |
| 94 MP_CHECKOK(ECPoint_mul(group, k1, NULL, NULL, &sx, &sy)); | |
| 95 MP_CHECKOK(ECPoint_mul(group, k2, px, py, rx, ry)); | |
| 96 | |
| 97 if (group->meth->field_enc) { | |
| 98 MP_CHECKOK(group->meth->field_enc(&sx, &sx, group->meth)); | |
| 99 MP_CHECKOK(group->meth->field_enc(&sy, &sy, group->meth)); | |
| 100 MP_CHECKOK(group->meth->field_enc(rx, rx, group->meth)); | |
| 101 MP_CHECKOK(group->meth->field_enc(ry, ry, group->meth)); | |
| 102 } | |
| 103 | |
| 104 MP_CHECKOK(group->point_add(&sx, &sy, rx, ry, rx, ry, group)); | |
| 105 | |
| 106 if (group->meth->field_dec) { | |
| 107 MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth)); | |
| 108 MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth)); | |
| 109 } | |
| 110 | |
| 111 CLEANUP: | |
| 112 mp_clear(&sx); | |
| 113 mp_clear(&sy); | |
| 114 return res; | |
| 115 } | |
| 116 | |
| 117 /* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G + | |
| 118 * k2 * P(x, y), where G is the generator (base point) of the group of | |
| 119 * points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL. | |
| 120 * Input and output values are assumed to be NOT field-encoded. Uses | |
| 121 * algorithm 15 (simultaneous multiple point multiplication) from Brown, | |
| 122 * Hankerson, Lopez, Menezes. Software Implementation of the NIST | |
| 123 * Elliptic Curves over Prime Fields. */ | |
| 124 mp_err | |
| 125 ec_pts_mul_simul_w2(const mp_int *k1, const mp_int *k2, const mp_int *px, | |
| 126 const mp_int *py, mp_int *rx, mp_int *ry
, | |
| 127 const ECGroup *group) | |
| 128 { | |
| 129 mp_err res = MP_OKAY; | |
| 130 mp_int precomp[4][4][2]; | |
| 131 const mp_int *a, *b; | |
| 132 unsigned int i, j; | |
| 133 int ai, bi, d; | |
| 134 | |
| 135 ARGCHK(group != NULL, MP_BADARG); | |
| 136 ARGCHK(!((k1 == NULL) | |
| 137 && ((k2 == NULL) || (px == NULL) | |
| 138 || (py == NULL))), MP_BADARG); | |
| 139 | |
| 140 /* if some arguments are not defined used ECPoint_mul */ | |
| 141 if (k1 == NULL) { | |
| 142 return ECPoint_mul(group, k2, px, py, rx, ry); | |
| 143 } else if ((k2 == NULL) || (px == NULL) || (py == NULL)) { | |
| 144 return ECPoint_mul(group, k1, NULL, NULL, rx, ry); | |
| 145 } | |
| 146 | |
| 147 /* initialize precomputation table */ | |
| 148 for (i = 0; i < 4; i++) { | |
| 149 for (j = 0; j < 4; j++) { | |
| 150 MP_DIGITS(&precomp[i][j][0]) = 0; | |
| 151 MP_DIGITS(&precomp[i][j][1]) = 0; | |
| 152 } | |
| 153 } | |
| 154 for (i = 0; i < 4; i++) { | |
| 155 for (j = 0; j < 4; j++) { | |
| 156 MP_CHECKOK( mp_init_size(&precomp[i][j][0], | |
| 157 ECL_MAX_FIELD_SIZE_DIGITS) ); | |
| 158 MP_CHECKOK( mp_init_size(&precomp[i][j][1], | |
| 159 ECL_MAX_FIELD_SIZE_DIGITS) ); | |
| 160 } | |
| 161 } | |
| 162 | |
| 163 /* fill precomputation table */ | |
| 164 /* assign {k1, k2} = {a, b} such that len(a) >= len(b) */ | |
| 165 if (mpl_significant_bits(k1) < mpl_significant_bits(k2)) { | |
| 166 a = k2; | |
| 167 b = k1; | |
| 168 if (group->meth->field_enc) { | |
| 169 MP_CHECKOK(group->meth-> | |
| 170 field_enc(px, &precomp[1][0][0], grou
p->meth)); | |
| 171 MP_CHECKOK(group->meth-> | |
| 172 field_enc(py, &precomp[1][0][1], grou
p->meth)); | |
| 173 } else { | |
| 174 MP_CHECKOK(mp_copy(px, &precomp[1][0][0])); | |
| 175 MP_CHECKOK(mp_copy(py, &precomp[1][0][1])); | |
| 176 } | |
| 177 MP_CHECKOK(mp_copy(&group->genx, &precomp[0][1][0])); | |
| 178 MP_CHECKOK(mp_copy(&group->geny, &precomp[0][1][1])); | |
| 179 } else { | |
| 180 a = k1; | |
| 181 b = k2; | |
| 182 MP_CHECKOK(mp_copy(&group->genx, &precomp[1][0][0])); | |
| 183 MP_CHECKOK(mp_copy(&group->geny, &precomp[1][0][1])); | |
| 184 if (group->meth->field_enc) { | |
| 185 MP_CHECKOK(group->meth-> | |
| 186 field_enc(px, &precomp[0][1][0], grou
p->meth)); | |
| 187 MP_CHECKOK(group->meth-> | |
| 188 field_enc(py, &precomp[0][1][1], grou
p->meth)); | |
| 189 } else { | |
| 190 MP_CHECKOK(mp_copy(px, &precomp[0][1][0])); | |
| 191 MP_CHECKOK(mp_copy(py, &precomp[0][1][1])); | |
| 192 } | |
| 193 } | |
| 194 /* precompute [*][0][*] */ | |
| 195 mp_zero(&precomp[0][0][0]); | |
| 196 mp_zero(&precomp[0][0][1]); | |
| 197 MP_CHECKOK(group-> | |
| 198 point_dbl(&precomp[1][0][0], &precomp[1][0][1], | |
| 199 &precomp[2][0][0], &precomp[2][
0][1], group)); | |
| 200 MP_CHECKOK(group-> | |
| 201 point_add(&precomp[1][0][0], &precomp[1][0][1], | |
| 202 &precomp[2][0][0], &precomp[2][
0][1], | |
| 203 &precomp[3][0][0], &precomp[3][
0][1], group)); | |
| 204 /* precompute [*][1][*] */ | |
| 205 for (i = 1; i < 4; i++) { | |
| 206 MP_CHECKOK(group-> | |
| 207 point_add(&precomp[0][1][0], &precomp[0][1][1
], | |
| 208 &precomp[i][0][0], &pre
comp[i][0][1], | |
| 209 &precomp[i][1][0], &pre
comp[i][1][1], group)); | |
| 210 } | |
| 211 /* precompute [*][2][*] */ | |
| 212 MP_CHECKOK(group-> | |
| 213 point_dbl(&precomp[0][1][0], &precomp[0][1][1], | |
| 214 &precomp[0][2][0], &precomp[0][
2][1], group)); | |
| 215 for (i = 1; i < 4; i++) { | |
| 216 MP_CHECKOK(group-> | |
| 217 point_add(&precomp[0][2][0], &precomp[0][2][1
], | |
| 218 &precomp[i][0][0], &pre
comp[i][0][1], | |
| 219 &precomp[i][2][0], &pre
comp[i][2][1], group)); | |
| 220 } | |
| 221 /* precompute [*][3][*] */ | |
| 222 MP_CHECKOK(group-> | |
| 223 point_add(&precomp[0][1][0], &precomp[0][1][1], | |
| 224 &precomp[0][2][0], &precomp[0][
2][1], | |
| 225 &precomp[0][3][0], &precomp[0][
3][1], group)); | |
| 226 for (i = 1; i < 4; i++) { | |
| 227 MP_CHECKOK(group-> | |
| 228 point_add(&precomp[0][3][0], &precomp[0][3][1
], | |
| 229 &precomp[i][0][0], &pre
comp[i][0][1], | |
| 230 &precomp[i][3][0], &pre
comp[i][3][1], group)); | |
| 231 } | |
| 232 | |
| 233 d = (mpl_significant_bits(a) + 1) / 2; | |
| 234 | |
| 235 /* R = inf */ | |
| 236 mp_zero(rx); | |
| 237 mp_zero(ry); | |
| 238 | |
| 239 for (i = d; i-- > 0;) { | |
| 240 ai = MP_GET_BIT(a, 2 * i + 1); | |
| 241 ai <<= 1; | |
| 242 ai |= MP_GET_BIT(a, 2 * i); | |
| 243 bi = MP_GET_BIT(b, 2 * i + 1); | |
| 244 bi <<= 1; | |
| 245 bi |= MP_GET_BIT(b, 2 * i); | |
| 246 /* R = 2^2 * R */ | |
| 247 MP_CHECKOK(group->point_dbl(rx, ry, rx, ry, group)); | |
| 248 MP_CHECKOK(group->point_dbl(rx, ry, rx, ry, group)); | |
| 249 /* R = R + (ai * A + bi * B) */ | |
| 250 MP_CHECKOK(group-> | |
| 251 point_add(rx, ry, &precomp[ai][bi][0], | |
| 252 &precomp[ai][bi][1], rx
, ry, group)); | |
| 253 } | |
| 254 | |
| 255 if (group->meth->field_dec) { | |
| 256 MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth)); | |
| 257 MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth)); | |
| 258 } | |
| 259 | |
| 260 CLEANUP: | |
| 261 for (i = 0; i < 4; i++) { | |
| 262 for (j = 0; j < 4; j++) { | |
| 263 mp_clear(&precomp[i][j][0]); | |
| 264 mp_clear(&precomp[i][j][1]); | |
| 265 } | |
| 266 } | |
| 267 return res; | |
| 268 } | |
| 269 | |
| 270 /* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G + | |
| 271 * k2 * P(x, y), where G is the generator (base point) of the group of | |
| 272 * points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL. | |
| 273 * Input and output values are assumed to be NOT field-encoded. */ | |
| 274 mp_err | |
| 275 ECPoints_mul(const ECGroup *group, const mp_int *k1, const mp_int *k2, | |
| 276 const mp_int *px, const mp_int *py, mp_int *rx, mp_int
*ry) | |
| 277 { | |
| 278 mp_err res = MP_OKAY; | |
| 279 mp_int k1t, k2t; | |
| 280 const mp_int *k1p, *k2p; | |
| 281 | |
| 282 MP_DIGITS(&k1t) = 0; | |
| 283 MP_DIGITS(&k2t) = 0; | |
| 284 | |
| 285 ARGCHK(group != NULL, MP_BADARG); | |
| 286 | |
| 287 /* want scalar to be less than or equal to group order */ | |
| 288 if (k1 != NULL) { | |
| 289 if (mp_cmp(k1, &group->order) >= 0) { | |
| 290 MP_CHECKOK(mp_init(&k1t)); | |
| 291 MP_CHECKOK(mp_mod(k1, &group->order, &k1t)); | |
| 292 k1p = &k1t; | |
| 293 } else { | |
| 294 k1p = k1; | |
| 295 } | |
| 296 } else { | |
| 297 k1p = k1; | |
| 298 } | |
| 299 if (k2 != NULL) { | |
| 300 if (mp_cmp(k2, &group->order) >= 0) { | |
| 301 MP_CHECKOK(mp_init(&k2t)); | |
| 302 MP_CHECKOK(mp_mod(k2, &group->order, &k2t)); | |
| 303 k2p = &k2t; | |
| 304 } else { | |
| 305 k2p = k2; | |
| 306 } | |
| 307 } else { | |
| 308 k2p = k2; | |
| 309 } | |
| 310 | |
| 311 /* if points_mul is defined, then use it */ | |
| 312 if (group->points_mul) { | |
| 313 res = group->points_mul(k1p, k2p, px, py, rx, ry, group); | |
| 314 } else { | |
| 315 res = ec_pts_mul_simul_w2(k1p, k2p, px, py, rx, ry, group); | |
| 316 } | |
| 317 | |
| 318 CLEANUP: | |
| 319 mp_clear(&k1t); | |
| 320 mp_clear(&k2t); | |
| 321 return res; | |
| 322 } | |
| OLD | NEW |