Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | |
michael@0 | 5 | #include "ecp_fp.h" |
michael@0 | 6 | #include "ecl-priv.h" |
michael@0 | 7 | #include <stdlib.h> |
michael@0 | 8 | |
michael@0 | 9 | /* Performs tidying on a short multi-precision floating point integer (the |
michael@0 | 10 | * lower group->numDoubles floats). */ |
michael@0 | 11 | void |
michael@0 | 12 | ecfp_tidyShort(double *t, const EC_group_fp * group) |
michael@0 | 13 | { |
michael@0 | 14 | group->ecfp_tidy(t, group->alpha, group); |
michael@0 | 15 | } |
michael@0 | 16 | |
michael@0 | 17 | /* Performs tidying on only the upper float digits of a multi-precision |
michael@0 | 18 | * floating point integer, i.e. the digits beyond the regular length which |
michael@0 | 19 | * are removed in the reduction step. */ |
michael@0 | 20 | void |
michael@0 | 21 | ecfp_tidyUpper(double *t, const EC_group_fp * group) |
michael@0 | 22 | { |
michael@0 | 23 | group->ecfp_tidy(t + group->numDoubles, |
michael@0 | 24 | group->alpha + group->numDoubles, group); |
michael@0 | 25 | } |
michael@0 | 26 | |
michael@0 | 27 | /* Performs a "tidy" operation, which performs carrying, moving excess |
michael@0 | 28 | * bits from one double to the next double, so that the precision of the |
michael@0 | 29 | * doubles is reduced to the regular precision group->doubleBitSize. This |
michael@0 | 30 | * might result in some float digits being negative. Alternative C version |
michael@0 | 31 | * for portability. */ |
michael@0 | 32 | void |
michael@0 | 33 | ecfp_tidy(double *t, const double *alpha, const EC_group_fp * group) |
michael@0 | 34 | { |
michael@0 | 35 | double q; |
michael@0 | 36 | int i; |
michael@0 | 37 | |
michael@0 | 38 | /* Do carrying */ |
michael@0 | 39 | for (i = 0; i < group->numDoubles - 1; i++) { |
michael@0 | 40 | q = t[i] + alpha[i + 1]; |
michael@0 | 41 | q -= alpha[i + 1]; |
michael@0 | 42 | t[i] -= q; |
michael@0 | 43 | t[i + 1] += q; |
michael@0 | 44 | |
michael@0 | 45 | /* If we don't assume that truncation rounding is used, then q |
michael@0 | 46 | * might be 2^n bigger than expected (if it rounds up), then t[0] |
michael@0 | 47 | * could be negative and t[1] 2^n larger than expected. */ |
michael@0 | 48 | } |
michael@0 | 49 | } |
michael@0 | 50 | |
michael@0 | 51 | /* Performs a more mathematically precise "tidying" so that each term is |
michael@0 | 52 | * positive. This is slower than the regular tidying, and is used for |
michael@0 | 53 | * conversion from floating point to integer. */ |
michael@0 | 54 | void |
michael@0 | 55 | ecfp_positiveTidy(double *t, const EC_group_fp * group) |
michael@0 | 56 | { |
michael@0 | 57 | double q; |
michael@0 | 58 | int i; |
michael@0 | 59 | |
michael@0 | 60 | /* Do carrying */ |
michael@0 | 61 | for (i = 0; i < group->numDoubles - 1; i++) { |
michael@0 | 62 | /* Subtract beta to force rounding down */ |
michael@0 | 63 | q = t[i] - ecfp_beta[i + 1]; |
michael@0 | 64 | q += group->alpha[i + 1]; |
michael@0 | 65 | q -= group->alpha[i + 1]; |
michael@0 | 66 | t[i] -= q; |
michael@0 | 67 | t[i + 1] += q; |
michael@0 | 68 | |
michael@0 | 69 | /* Due to subtracting ecfp_beta, we should have each term a |
michael@0 | 70 | * non-negative int */ |
michael@0 | 71 | ECFP_ASSERT(t[i] / ecfp_exp[i] == |
michael@0 | 72 | (unsigned long long) (t[i] / ecfp_exp[i])); |
michael@0 | 73 | ECFP_ASSERT(t[i] >= 0); |
michael@0 | 74 | } |
michael@0 | 75 | } |
michael@0 | 76 | |
michael@0 | 77 | /* Converts from a floating point representation into an mp_int. Expects |
michael@0 | 78 | * that d is already reduced. */ |
michael@0 | 79 | void |
michael@0 | 80 | ecfp_fp2i(mp_int *mpout, double *d, const ECGroup *ecgroup) |
michael@0 | 81 | { |
michael@0 | 82 | EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; |
michael@0 | 83 | unsigned short i16[(group->primeBitSize + 15) / 16]; |
michael@0 | 84 | double q = 1; |
michael@0 | 85 | |
michael@0 | 86 | #ifdef ECL_THIRTY_TWO_BIT |
michael@0 | 87 | /* TEST uint32_t z = 0; */ |
michael@0 | 88 | unsigned int z = 0; |
michael@0 | 89 | #else |
michael@0 | 90 | uint64_t z = 0; |
michael@0 | 91 | #endif |
michael@0 | 92 | int zBits = 0; |
michael@0 | 93 | int copiedBits = 0; |
michael@0 | 94 | int i = 0; |
michael@0 | 95 | int j = 0; |
michael@0 | 96 | |
michael@0 | 97 | mp_digit *out; |
michael@0 | 98 | |
michael@0 | 99 | /* Result should always be >= 0, so set sign accordingly */ |
michael@0 | 100 | MP_SIGN(mpout) = MP_ZPOS; |
michael@0 | 101 | |
michael@0 | 102 | /* Tidy up so we're just dealing with positive numbers */ |
michael@0 | 103 | ecfp_positiveTidy(d, group); |
michael@0 | 104 | |
michael@0 | 105 | /* We might need to do this reduction step more than once if the |
michael@0 | 106 | * reduction adds smaller terms which carry-over to cause another |
michael@0 | 107 | * reduction. However, this should happen very rarely, if ever, |
michael@0 | 108 | * depending on the elliptic curve. */ |
michael@0 | 109 | do { |
michael@0 | 110 | /* Init loop data */ |
michael@0 | 111 | z = 0; |
michael@0 | 112 | zBits = 0; |
michael@0 | 113 | q = 1; |
michael@0 | 114 | i = 0; |
michael@0 | 115 | j = 0; |
michael@0 | 116 | copiedBits = 0; |
michael@0 | 117 | |
michael@0 | 118 | /* Might have to do a bit more reduction */ |
michael@0 | 119 | group->ecfp_singleReduce(d, group); |
michael@0 | 120 | |
michael@0 | 121 | /* Grow the size of the mpint if it's too small */ |
michael@0 | 122 | s_mp_grow(mpout, group->numInts); |
michael@0 | 123 | MP_USED(mpout) = group->numInts; |
michael@0 | 124 | out = MP_DIGITS(mpout); |
michael@0 | 125 | |
michael@0 | 126 | /* Convert double to 16 bit integers */ |
michael@0 | 127 | while (copiedBits < group->primeBitSize) { |
michael@0 | 128 | if (zBits < 16) { |
michael@0 | 129 | z += d[i] * q; |
michael@0 | 130 | i++; |
michael@0 | 131 | ECFP_ASSERT(i < (group->primeBitSize + 15) / 16); |
michael@0 | 132 | zBits += group->doubleBitSize; |
michael@0 | 133 | } |
michael@0 | 134 | i16[j] = z; |
michael@0 | 135 | j++; |
michael@0 | 136 | z >>= 16; |
michael@0 | 137 | zBits -= 16; |
michael@0 | 138 | q *= ecfp_twom16; |
michael@0 | 139 | copiedBits += 16; |
michael@0 | 140 | } |
michael@0 | 141 | } while (z != 0); |
michael@0 | 142 | |
michael@0 | 143 | /* Convert 16 bit integers to mp_digit */ |
michael@0 | 144 | #ifdef ECL_THIRTY_TWO_BIT |
michael@0 | 145 | for (i = 0; i < (group->primeBitSize + 15) / 16; i += 2) { |
michael@0 | 146 | *out = 0; |
michael@0 | 147 | if (i + 1 < (group->primeBitSize + 15) / 16) { |
michael@0 | 148 | *out = i16[i + 1]; |
michael@0 | 149 | *out <<= 16; |
michael@0 | 150 | } |
michael@0 | 151 | *out++ += i16[i]; |
michael@0 | 152 | } |
michael@0 | 153 | #else /* 64 bit */ |
michael@0 | 154 | for (i = 0; i < (group->primeBitSize + 15) / 16; i += 4) { |
michael@0 | 155 | *out = 0; |
michael@0 | 156 | if (i + 3 < (group->primeBitSize + 15) / 16) { |
michael@0 | 157 | *out = i16[i + 3]; |
michael@0 | 158 | *out <<= 16; |
michael@0 | 159 | } |
michael@0 | 160 | if (i + 2 < (group->primeBitSize + 15) / 16) { |
michael@0 | 161 | *out += i16[i + 2]; |
michael@0 | 162 | *out <<= 16; |
michael@0 | 163 | } |
michael@0 | 164 | if (i + 1 < (group->primeBitSize + 15) / 16) { |
michael@0 | 165 | *out += i16[i + 1]; |
michael@0 | 166 | *out <<= 16; |
michael@0 | 167 | } |
michael@0 | 168 | *out++ += i16[i]; |
michael@0 | 169 | } |
michael@0 | 170 | #endif |
michael@0 | 171 | |
michael@0 | 172 | /* Perform final reduction. mpout should already be the same number |
michael@0 | 173 | * of bits as p, but might not be less than p. Make it so. Since |
michael@0 | 174 | * mpout has the same number of bits as p, and 2p has a larger bit |
michael@0 | 175 | * size, then mpout < 2p, so a single subtraction of p will suffice. */ |
michael@0 | 176 | if (mp_cmp(mpout, &ecgroup->meth->irr) >= 0) { |
michael@0 | 177 | mp_sub(mpout, &ecgroup->meth->irr, mpout); |
michael@0 | 178 | } |
michael@0 | 179 | |
michael@0 | 180 | /* Shrink the size of the mp_int to the actual used size (required for |
michael@0 | 181 | * mp_cmp_z == 0) */ |
michael@0 | 182 | out = MP_DIGITS(mpout); |
michael@0 | 183 | for (i = group->numInts - 1; i > 0; i--) { |
michael@0 | 184 | if (out[i] != 0) |
michael@0 | 185 | break; |
michael@0 | 186 | } |
michael@0 | 187 | MP_USED(mpout) = i + 1; |
michael@0 | 188 | |
michael@0 | 189 | /* Should be between 0 and p-1 */ |
michael@0 | 190 | ECFP_ASSERT(mp_cmp(mpout, &ecgroup->meth->irr) < 0); |
michael@0 | 191 | ECFP_ASSERT(mp_cmp_z(mpout) >= 0); |
michael@0 | 192 | } |
michael@0 | 193 | |
michael@0 | 194 | /* Converts from an mpint into a floating point representation. */ |
michael@0 | 195 | void |
michael@0 | 196 | ecfp_i2fp(double *out, const mp_int *x, const ECGroup *ecgroup) |
michael@0 | 197 | { |
michael@0 | 198 | int i; |
michael@0 | 199 | int j = 0; |
michael@0 | 200 | int size; |
michael@0 | 201 | double shift = 1; |
michael@0 | 202 | mp_digit *in; |
michael@0 | 203 | EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; |
michael@0 | 204 | |
michael@0 | 205 | #ifdef ECL_DEBUG |
michael@0 | 206 | /* if debug mode, convert result back using ecfp_fp2i into cmp, then |
michael@0 | 207 | * compare to x. */ |
michael@0 | 208 | mp_int cmp; |
michael@0 | 209 | |
michael@0 | 210 | MP_DIGITS(&cmp) = NULL; |
michael@0 | 211 | mp_init(&cmp); |
michael@0 | 212 | #endif |
michael@0 | 213 | |
michael@0 | 214 | ECFP_ASSERT(group != NULL); |
michael@0 | 215 | |
michael@0 | 216 | /* init output to 0 (since we skip over some terms) */ |
michael@0 | 217 | for (i = 0; i < group->numDoubles; i++) |
michael@0 | 218 | out[i] = 0; |
michael@0 | 219 | i = 0; |
michael@0 | 220 | |
michael@0 | 221 | size = MP_USED(x); |
michael@0 | 222 | in = MP_DIGITS(x); |
michael@0 | 223 | |
michael@0 | 224 | /* Copy from int into doubles */ |
michael@0 | 225 | #ifdef ECL_THIRTY_TWO_BIT |
michael@0 | 226 | while (j < size) { |
michael@0 | 227 | while (group->doubleBitSize * (i + 1) <= 32 * j) { |
michael@0 | 228 | i++; |
michael@0 | 229 | } |
michael@0 | 230 | ECFP_ASSERT(group->doubleBitSize * i <= 32 * j); |
michael@0 | 231 | out[i] = in[j]; |
michael@0 | 232 | out[i] *= shift; |
michael@0 | 233 | shift *= ecfp_two32; |
michael@0 | 234 | j++; |
michael@0 | 235 | } |
michael@0 | 236 | #else |
michael@0 | 237 | while (j < size) { |
michael@0 | 238 | while (group->doubleBitSize * (i + 1) <= 64 * j) { |
michael@0 | 239 | i++; |
michael@0 | 240 | } |
michael@0 | 241 | ECFP_ASSERT(group->doubleBitSize * i <= 64 * j); |
michael@0 | 242 | out[i] = (in[j] & 0x00000000FFFFFFFF) * shift; |
michael@0 | 243 | |
michael@0 | 244 | while (group->doubleBitSize * (i + 1) <= 64 * j + 32) { |
michael@0 | 245 | i++; |
michael@0 | 246 | } |
michael@0 | 247 | ECFP_ASSERT(24 * i <= 64 * j + 32); |
michael@0 | 248 | out[i] = (in[j] & 0xFFFFFFFF00000000) * shift; |
michael@0 | 249 | |
michael@0 | 250 | shift *= ecfp_two64; |
michael@0 | 251 | j++; |
michael@0 | 252 | } |
michael@0 | 253 | #endif |
michael@0 | 254 | /* Realign bits to match double boundaries */ |
michael@0 | 255 | ecfp_tidyShort(out, group); |
michael@0 | 256 | |
michael@0 | 257 | #ifdef ECL_DEBUG |
michael@0 | 258 | /* Convert result back to mp_int, compare to original */ |
michael@0 | 259 | ecfp_fp2i(&cmp, out, ecgroup); |
michael@0 | 260 | ECFP_ASSERT(mp_cmp(&cmp, x) == 0); |
michael@0 | 261 | mp_clear(&cmp); |
michael@0 | 262 | #endif |
michael@0 | 263 | } |
michael@0 | 264 | |
michael@0 | 265 | /* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters |
michael@0 | 266 | * a, b and p are the elliptic curve coefficients and the prime that |
michael@0 | 267 | * determines the field GFp. Elliptic curve points P and R can be |
michael@0 | 268 | * identical. Uses Jacobian coordinates. Uses 4-bit window method. */ |
michael@0 | 269 | mp_err |
michael@0 | 270 | ec_GFp_point_mul_jac_4w_fp(const mp_int *n, const mp_int *px, |
michael@0 | 271 | const mp_int *py, mp_int *rx, mp_int *ry, |
michael@0 | 272 | const ECGroup *ecgroup) |
michael@0 | 273 | { |
michael@0 | 274 | mp_err res = MP_OKAY; |
michael@0 | 275 | ecfp_jac_pt precomp[16], r; |
michael@0 | 276 | ecfp_aff_pt p; |
michael@0 | 277 | EC_group_fp *group; |
michael@0 | 278 | |
michael@0 | 279 | mp_int rz; |
michael@0 | 280 | int i, ni, d; |
michael@0 | 281 | |
michael@0 | 282 | ARGCHK(ecgroup != NULL, MP_BADARG); |
michael@0 | 283 | ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG); |
michael@0 | 284 | |
michael@0 | 285 | group = (EC_group_fp *) ecgroup->extra1; |
michael@0 | 286 | MP_DIGITS(&rz) = 0; |
michael@0 | 287 | MP_CHECKOK(mp_init(&rz)); |
michael@0 | 288 | |
michael@0 | 289 | /* init p, da */ |
michael@0 | 290 | ecfp_i2fp(p.x, px, ecgroup); |
michael@0 | 291 | ecfp_i2fp(p.y, py, ecgroup); |
michael@0 | 292 | ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup); |
michael@0 | 293 | |
michael@0 | 294 | /* Do precomputation */ |
michael@0 | 295 | group->precompute_jac(precomp, &p, group); |
michael@0 | 296 | |
michael@0 | 297 | /* Do main body of calculations */ |
michael@0 | 298 | d = (mpl_significant_bits(n) + 3) / 4; |
michael@0 | 299 | |
michael@0 | 300 | /* R = inf */ |
michael@0 | 301 | for (i = 0; i < group->numDoubles; i++) { |
michael@0 | 302 | r.z[i] = 0; |
michael@0 | 303 | } |
michael@0 | 304 | |
michael@0 | 305 | for (i = d - 1; i >= 0; i--) { |
michael@0 | 306 | /* compute window ni */ |
michael@0 | 307 | ni = MP_GET_BIT(n, 4 * i + 3); |
michael@0 | 308 | ni <<= 1; |
michael@0 | 309 | ni |= MP_GET_BIT(n, 4 * i + 2); |
michael@0 | 310 | ni <<= 1; |
michael@0 | 311 | ni |= MP_GET_BIT(n, 4 * i + 1); |
michael@0 | 312 | ni <<= 1; |
michael@0 | 313 | ni |= MP_GET_BIT(n, 4 * i); |
michael@0 | 314 | |
michael@0 | 315 | /* R = 2^4 * R */ |
michael@0 | 316 | group->pt_dbl_jac(&r, &r, group); |
michael@0 | 317 | group->pt_dbl_jac(&r, &r, group); |
michael@0 | 318 | group->pt_dbl_jac(&r, &r, group); |
michael@0 | 319 | group->pt_dbl_jac(&r, &r, group); |
michael@0 | 320 | |
michael@0 | 321 | /* R = R + (ni * P) */ |
michael@0 | 322 | group->pt_add_jac(&r, &precomp[ni], &r, group); |
michael@0 | 323 | } |
michael@0 | 324 | |
michael@0 | 325 | /* Convert back to integer */ |
michael@0 | 326 | ecfp_fp2i(rx, r.x, ecgroup); |
michael@0 | 327 | ecfp_fp2i(ry, r.y, ecgroup); |
michael@0 | 328 | ecfp_fp2i(&rz, r.z, ecgroup); |
michael@0 | 329 | |
michael@0 | 330 | /* convert result S to affine coordinates */ |
michael@0 | 331 | MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, ecgroup)); |
michael@0 | 332 | |
michael@0 | 333 | CLEANUP: |
michael@0 | 334 | mp_clear(&rz); |
michael@0 | 335 | return res; |
michael@0 | 336 | } |
michael@0 | 337 | |
michael@0 | 338 | /* Uses mixed Jacobian-affine coordinates to perform a point |
michael@0 | 339 | * multiplication: R = n * P, n scalar. Uses mixed Jacobian-affine |
michael@0 | 340 | * coordinates (Jacobian coordinates for doubles and affine coordinates |
michael@0 | 341 | * for additions; based on recommendation from Brown et al.). Not very |
michael@0 | 342 | * time efficient but quite space efficient, no precomputation needed. |
michael@0 | 343 | * group contains the elliptic curve coefficients and the prime that |
michael@0 | 344 | * determines the field GFp. Elliptic curve points P and R can be |
michael@0 | 345 | * identical. Performs calculations in floating point number format, since |
michael@0 | 346 | * this is faster than the integer operations on the ULTRASPARC III. |
michael@0 | 347 | * Uses left-to-right binary method (double & add) (algorithm 9) for |
michael@0 | 348 | * scalar-point multiplication from Brown, Hankerson, Lopez, Menezes. |
michael@0 | 349 | * Software Implementation of the NIST Elliptic Curves Over Prime Fields. */ |
michael@0 | 350 | mp_err |
michael@0 | 351 | ec_GFp_pt_mul_jac_fp(const mp_int *n, const mp_int *px, const mp_int *py, |
michael@0 | 352 | mp_int *rx, mp_int *ry, const ECGroup *ecgroup) |
michael@0 | 353 | { |
michael@0 | 354 | mp_err res; |
michael@0 | 355 | mp_int sx, sy, sz; |
michael@0 | 356 | |
michael@0 | 357 | ecfp_aff_pt p; |
michael@0 | 358 | ecfp_jac_pt r; |
michael@0 | 359 | EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; |
michael@0 | 360 | |
michael@0 | 361 | int i, l; |
michael@0 | 362 | |
michael@0 | 363 | MP_DIGITS(&sx) = 0; |
michael@0 | 364 | MP_DIGITS(&sy) = 0; |
michael@0 | 365 | MP_DIGITS(&sz) = 0; |
michael@0 | 366 | MP_CHECKOK(mp_init(&sx)); |
michael@0 | 367 | MP_CHECKOK(mp_init(&sy)); |
michael@0 | 368 | MP_CHECKOK(mp_init(&sz)); |
michael@0 | 369 | |
michael@0 | 370 | /* if n = 0 then r = inf */ |
michael@0 | 371 | if (mp_cmp_z(n) == 0) { |
michael@0 | 372 | mp_zero(rx); |
michael@0 | 373 | mp_zero(ry); |
michael@0 | 374 | res = MP_OKAY; |
michael@0 | 375 | goto CLEANUP; |
michael@0 | 376 | /* if n < 0 then out of range error */ |
michael@0 | 377 | } else if (mp_cmp_z(n) < 0) { |
michael@0 | 378 | res = MP_RANGE; |
michael@0 | 379 | goto CLEANUP; |
michael@0 | 380 | } |
michael@0 | 381 | |
michael@0 | 382 | /* Convert from integer to floating point */ |
michael@0 | 383 | ecfp_i2fp(p.x, px, ecgroup); |
michael@0 | 384 | ecfp_i2fp(p.y, py, ecgroup); |
michael@0 | 385 | ecfp_i2fp(group->curvea, &(ecgroup->curvea), ecgroup); |
michael@0 | 386 | |
michael@0 | 387 | /* Init r to point at infinity */ |
michael@0 | 388 | for (i = 0; i < group->numDoubles; i++) { |
michael@0 | 389 | r.z[i] = 0; |
michael@0 | 390 | } |
michael@0 | 391 | |
michael@0 | 392 | /* double and add method */ |
michael@0 | 393 | l = mpl_significant_bits(n) - 1; |
michael@0 | 394 | |
michael@0 | 395 | for (i = l; i >= 0; i--) { |
michael@0 | 396 | /* R = 2R */ |
michael@0 | 397 | group->pt_dbl_jac(&r, &r, group); |
michael@0 | 398 | |
michael@0 | 399 | /* if n_i = 1, then R = R + Q */ |
michael@0 | 400 | if (MP_GET_BIT(n, i) != 0) { |
michael@0 | 401 | group->pt_add_jac_aff(&r, &p, &r, group); |
michael@0 | 402 | } |
michael@0 | 403 | } |
michael@0 | 404 | |
michael@0 | 405 | /* Convert from floating point to integer */ |
michael@0 | 406 | ecfp_fp2i(&sx, r.x, ecgroup); |
michael@0 | 407 | ecfp_fp2i(&sy, r.y, ecgroup); |
michael@0 | 408 | ecfp_fp2i(&sz, r.z, ecgroup); |
michael@0 | 409 | |
michael@0 | 410 | /* convert result R to affine coordinates */ |
michael@0 | 411 | MP_CHECKOK(ec_GFp_pt_jac2aff(&sx, &sy, &sz, rx, ry, ecgroup)); |
michael@0 | 412 | |
michael@0 | 413 | CLEANUP: |
michael@0 | 414 | mp_clear(&sx); |
michael@0 | 415 | mp_clear(&sy); |
michael@0 | 416 | mp_clear(&sz); |
michael@0 | 417 | return res; |
michael@0 | 418 | } |
michael@0 | 419 | |
michael@0 | 420 | /* Computes R = nP where R is (rx, ry) and P is the base point. Elliptic |
michael@0 | 421 | * curve points P and R can be identical. Uses mixed Modified-Jacobian |
michael@0 | 422 | * co-ordinates for doubling and Chudnovsky Jacobian coordinates for |
michael@0 | 423 | * additions. Uses 5-bit window NAF method (algorithm 11) for scalar-point |
michael@0 | 424 | * multiplication from Brown, Hankerson, Lopez, Menezes. Software |
michael@0 | 425 | * Implementation of the NIST Elliptic Curves Over Prime Fields. */ |
michael@0 | 426 | mp_err |
michael@0 | 427 | ec_GFp_point_mul_wNAF_fp(const mp_int *n, const mp_int *px, |
michael@0 | 428 | const mp_int *py, mp_int *rx, mp_int *ry, |
michael@0 | 429 | const ECGroup *ecgroup) |
michael@0 | 430 | { |
michael@0 | 431 | mp_err res = MP_OKAY; |
michael@0 | 432 | mp_int sx, sy, sz; |
michael@0 | 433 | EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; |
michael@0 | 434 | ecfp_chud_pt precomp[16]; |
michael@0 | 435 | |
michael@0 | 436 | ecfp_aff_pt p; |
michael@0 | 437 | ecfp_jm_pt r; |
michael@0 | 438 | |
michael@0 | 439 | signed char naf[group->orderBitSize + 1]; |
michael@0 | 440 | int i; |
michael@0 | 441 | |
michael@0 | 442 | MP_DIGITS(&sx) = 0; |
michael@0 | 443 | MP_DIGITS(&sy) = 0; |
michael@0 | 444 | MP_DIGITS(&sz) = 0; |
michael@0 | 445 | MP_CHECKOK(mp_init(&sx)); |
michael@0 | 446 | MP_CHECKOK(mp_init(&sy)); |
michael@0 | 447 | MP_CHECKOK(mp_init(&sz)); |
michael@0 | 448 | |
michael@0 | 449 | /* if n = 0 then r = inf */ |
michael@0 | 450 | if (mp_cmp_z(n) == 0) { |
michael@0 | 451 | mp_zero(rx); |
michael@0 | 452 | mp_zero(ry); |
michael@0 | 453 | res = MP_OKAY; |
michael@0 | 454 | goto CLEANUP; |
michael@0 | 455 | /* if n < 0 then out of range error */ |
michael@0 | 456 | } else if (mp_cmp_z(n) < 0) { |
michael@0 | 457 | res = MP_RANGE; |
michael@0 | 458 | goto CLEANUP; |
michael@0 | 459 | } |
michael@0 | 460 | |
michael@0 | 461 | /* Convert from integer to floating point */ |
michael@0 | 462 | ecfp_i2fp(p.x, px, ecgroup); |
michael@0 | 463 | ecfp_i2fp(p.y, py, ecgroup); |
michael@0 | 464 | ecfp_i2fp(group->curvea, &(ecgroup->curvea), ecgroup); |
michael@0 | 465 | |
michael@0 | 466 | /* Perform precomputation */ |
michael@0 | 467 | group->precompute_chud(precomp, &p, group); |
michael@0 | 468 | |
michael@0 | 469 | /* Compute 5NAF */ |
michael@0 | 470 | ec_compute_wNAF(naf, group->orderBitSize, n, 5); |
michael@0 | 471 | |
michael@0 | 472 | /* Init R = pt at infinity */ |
michael@0 | 473 | for (i = 0; i < group->numDoubles; i++) { |
michael@0 | 474 | r.z[i] = 0; |
michael@0 | 475 | } |
michael@0 | 476 | |
michael@0 | 477 | /* wNAF method */ |
michael@0 | 478 | for (i = group->orderBitSize; i >= 0; i--) { |
michael@0 | 479 | /* R = 2R */ |
michael@0 | 480 | group->pt_dbl_jm(&r, &r, group); |
michael@0 | 481 | |
michael@0 | 482 | if (naf[i] != 0) { |
michael@0 | 483 | group->pt_add_jm_chud(&r, &precomp[(naf[i] + 15) / 2], &r, |
michael@0 | 484 | group); |
michael@0 | 485 | } |
michael@0 | 486 | } |
michael@0 | 487 | |
michael@0 | 488 | /* Convert from floating point to integer */ |
michael@0 | 489 | ecfp_fp2i(&sx, r.x, ecgroup); |
michael@0 | 490 | ecfp_fp2i(&sy, r.y, ecgroup); |
michael@0 | 491 | ecfp_fp2i(&sz, r.z, ecgroup); |
michael@0 | 492 | |
michael@0 | 493 | /* convert result R to affine coordinates */ |
michael@0 | 494 | MP_CHECKOK(ec_GFp_pt_jac2aff(&sx, &sy, &sz, rx, ry, ecgroup)); |
michael@0 | 495 | |
michael@0 | 496 | CLEANUP: |
michael@0 | 497 | mp_clear(&sx); |
michael@0 | 498 | mp_clear(&sy); |
michael@0 | 499 | mp_clear(&sz); |
michael@0 | 500 | return res; |
michael@0 | 501 | } |
michael@0 | 502 | |
michael@0 | 503 | /* Cleans up extra memory allocated in ECGroup for this implementation. */ |
michael@0 | 504 | void |
michael@0 | 505 | ec_GFp_extra_free_fp(ECGroup *group) |
michael@0 | 506 | { |
michael@0 | 507 | if (group->extra1 != NULL) { |
michael@0 | 508 | free(group->extra1); |
michael@0 | 509 | group->extra1 = NULL; |
michael@0 | 510 | } |
michael@0 | 511 | } |
michael@0 | 512 | |
michael@0 | 513 | /* Tests what precision floating point arithmetic is set to. This should |
michael@0 | 514 | * be either a 53-bit mantissa (IEEE standard) or a 64-bit mantissa |
michael@0 | 515 | * (extended precision on x86) and sets it into the EC_group_fp. Returns |
michael@0 | 516 | * either 53 or 64 accordingly. */ |
michael@0 | 517 | int |
michael@0 | 518 | ec_set_fp_precision(EC_group_fp * group) |
michael@0 | 519 | { |
michael@0 | 520 | double a = 9007199254740992.0; /* 2^53 */ |
michael@0 | 521 | double b = a + 1; |
michael@0 | 522 | |
michael@0 | 523 | if (a == b) { |
michael@0 | 524 | group->fpPrecision = 53; |
michael@0 | 525 | group->alpha = ecfp_alpha_53; |
michael@0 | 526 | return 53; |
michael@0 | 527 | } |
michael@0 | 528 | group->fpPrecision = 64; |
michael@0 | 529 | group->alpha = ecfp_alpha_64; |
michael@0 | 530 | return 64; |
michael@0 | 531 | } |