security/nss/lib/freebl/ecl/ecl_gf.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

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 "mpi.h"
michael@0 6 #include "mp_gf2m.h"
michael@0 7 #include "ecl-priv.h"
michael@0 8 #include "mpi-priv.h"
michael@0 9 #include <stdlib.h>
michael@0 10
michael@0 11 /* Allocate memory for a new GFMethod object. */
michael@0 12 GFMethod *
michael@0 13 GFMethod_new()
michael@0 14 {
michael@0 15 mp_err res = MP_OKAY;
michael@0 16 GFMethod *meth;
michael@0 17 meth = (GFMethod *) malloc(sizeof(GFMethod));
michael@0 18 if (meth == NULL)
michael@0 19 return NULL;
michael@0 20 meth->constructed = MP_YES;
michael@0 21 MP_DIGITS(&meth->irr) = 0;
michael@0 22 meth->extra_free = NULL;
michael@0 23 MP_CHECKOK(mp_init(&meth->irr));
michael@0 24
michael@0 25 CLEANUP:
michael@0 26 if (res != MP_OKAY) {
michael@0 27 GFMethod_free(meth);
michael@0 28 return NULL;
michael@0 29 }
michael@0 30 return meth;
michael@0 31 }
michael@0 32
michael@0 33 /* Construct a generic GFMethod for arithmetic over prime fields with
michael@0 34 * irreducible irr. */
michael@0 35 GFMethod *
michael@0 36 GFMethod_consGFp(const mp_int *irr)
michael@0 37 {
michael@0 38 mp_err res = MP_OKAY;
michael@0 39 GFMethod *meth = NULL;
michael@0 40
michael@0 41 meth = GFMethod_new();
michael@0 42 if (meth == NULL)
michael@0 43 return NULL;
michael@0 44
michael@0 45 MP_CHECKOK(mp_copy(irr, &meth->irr));
michael@0 46 meth->irr_arr[0] = mpl_significant_bits(irr);
michael@0 47 meth->irr_arr[1] = meth->irr_arr[2] = meth->irr_arr[3] =
michael@0 48 meth->irr_arr[4] = 0;
michael@0 49 switch(MP_USED(&meth->irr)) {
michael@0 50 /* maybe we need 1 and 2 words here as well?*/
michael@0 51 case 3:
michael@0 52 meth->field_add = &ec_GFp_add_3;
michael@0 53 meth->field_sub = &ec_GFp_sub_3;
michael@0 54 break;
michael@0 55 case 4:
michael@0 56 meth->field_add = &ec_GFp_add_4;
michael@0 57 meth->field_sub = &ec_GFp_sub_4;
michael@0 58 break;
michael@0 59 case 5:
michael@0 60 meth->field_add = &ec_GFp_add_5;
michael@0 61 meth->field_sub = &ec_GFp_sub_5;
michael@0 62 break;
michael@0 63 case 6:
michael@0 64 meth->field_add = &ec_GFp_add_6;
michael@0 65 meth->field_sub = &ec_GFp_sub_6;
michael@0 66 break;
michael@0 67 default:
michael@0 68 meth->field_add = &ec_GFp_add;
michael@0 69 meth->field_sub = &ec_GFp_sub;
michael@0 70 }
michael@0 71 meth->field_neg = &ec_GFp_neg;
michael@0 72 meth->field_mod = &ec_GFp_mod;
michael@0 73 meth->field_mul = &ec_GFp_mul;
michael@0 74 meth->field_sqr = &ec_GFp_sqr;
michael@0 75 meth->field_div = &ec_GFp_div;
michael@0 76 meth->field_enc = NULL;
michael@0 77 meth->field_dec = NULL;
michael@0 78 meth->extra1 = NULL;
michael@0 79 meth->extra2 = NULL;
michael@0 80 meth->extra_free = NULL;
michael@0 81
michael@0 82 CLEANUP:
michael@0 83 if (res != MP_OKAY) {
michael@0 84 GFMethod_free(meth);
michael@0 85 return NULL;
michael@0 86 }
michael@0 87 return meth;
michael@0 88 }
michael@0 89
michael@0 90 /* Construct a generic GFMethod for arithmetic over binary polynomial
michael@0 91 * fields with irreducible irr that has array representation irr_arr (see
michael@0 92 * ecl-priv.h for description of the representation). If irr_arr is NULL,
michael@0 93 * then it is constructed from the bitstring representation. */
michael@0 94 GFMethod *
michael@0 95 GFMethod_consGF2m(const mp_int *irr, const unsigned int irr_arr[5])
michael@0 96 {
michael@0 97 mp_err res = MP_OKAY;
michael@0 98 int ret;
michael@0 99 GFMethod *meth = NULL;
michael@0 100
michael@0 101 meth = GFMethod_new();
michael@0 102 if (meth == NULL)
michael@0 103 return NULL;
michael@0 104
michael@0 105 MP_CHECKOK(mp_copy(irr, &meth->irr));
michael@0 106 if (irr_arr != NULL) {
michael@0 107 /* Irreducible polynomials are either trinomials or pentanomials. */
michael@0 108 meth->irr_arr[0] = irr_arr[0];
michael@0 109 meth->irr_arr[1] = irr_arr[1];
michael@0 110 meth->irr_arr[2] = irr_arr[2];
michael@0 111 if (irr_arr[2] > 0) {
michael@0 112 meth->irr_arr[3] = irr_arr[3];
michael@0 113 meth->irr_arr[4] = irr_arr[4];
michael@0 114 } else {
michael@0 115 meth->irr_arr[3] = meth->irr_arr[4] = 0;
michael@0 116 }
michael@0 117 } else {
michael@0 118 ret = mp_bpoly2arr(irr, meth->irr_arr, 5);
michael@0 119 /* Irreducible polynomials are either trinomials or pentanomials. */
michael@0 120 if ((ret != 5) && (ret != 3)) {
michael@0 121 res = MP_UNDEF;
michael@0 122 goto CLEANUP;
michael@0 123 }
michael@0 124 }
michael@0 125 meth->field_add = &ec_GF2m_add;
michael@0 126 meth->field_neg = &ec_GF2m_neg;
michael@0 127 meth->field_sub = &ec_GF2m_add;
michael@0 128 meth->field_mod = &ec_GF2m_mod;
michael@0 129 meth->field_mul = &ec_GF2m_mul;
michael@0 130 meth->field_sqr = &ec_GF2m_sqr;
michael@0 131 meth->field_div = &ec_GF2m_div;
michael@0 132 meth->field_enc = NULL;
michael@0 133 meth->field_dec = NULL;
michael@0 134 meth->extra1 = NULL;
michael@0 135 meth->extra2 = NULL;
michael@0 136 meth->extra_free = NULL;
michael@0 137
michael@0 138 CLEANUP:
michael@0 139 if (res != MP_OKAY) {
michael@0 140 GFMethod_free(meth);
michael@0 141 return NULL;
michael@0 142 }
michael@0 143 return meth;
michael@0 144 }
michael@0 145
michael@0 146 /* Free the memory allocated (if any) to a GFMethod object. */
michael@0 147 void
michael@0 148 GFMethod_free(GFMethod *meth)
michael@0 149 {
michael@0 150 if (meth == NULL)
michael@0 151 return;
michael@0 152 if (meth->constructed == MP_NO)
michael@0 153 return;
michael@0 154 mp_clear(&meth->irr);
michael@0 155 if (meth->extra_free != NULL)
michael@0 156 meth->extra_free(meth);
michael@0 157 free(meth);
michael@0 158 }
michael@0 159
michael@0 160 /* Wrapper functions for generic prime field arithmetic. */
michael@0 161
michael@0 162 /* Add two field elements. Assumes that 0 <= a, b < meth->irr */
michael@0 163 mp_err
michael@0 164 ec_GFp_add(const mp_int *a, const mp_int *b, mp_int *r,
michael@0 165 const GFMethod *meth)
michael@0 166 {
michael@0 167 /* PRE: 0 <= a, b < p = meth->irr POST: 0 <= r < p, r = a + b (mod p) */
michael@0 168 mp_err res;
michael@0 169
michael@0 170 if ((res = mp_add(a, b, r)) != MP_OKAY) {
michael@0 171 return res;
michael@0 172 }
michael@0 173 if (mp_cmp(r, &meth->irr) >= 0) {
michael@0 174 return mp_sub(r, &meth->irr, r);
michael@0 175 }
michael@0 176 return res;
michael@0 177 }
michael@0 178
michael@0 179 /* Negates a field element. Assumes that 0 <= a < meth->irr */
michael@0 180 mp_err
michael@0 181 ec_GFp_neg(const mp_int *a, mp_int *r, const GFMethod *meth)
michael@0 182 {
michael@0 183 /* PRE: 0 <= a < p = meth->irr POST: 0 <= r < p, r = -a (mod p) */
michael@0 184
michael@0 185 if (mp_cmp_z(a) == 0) {
michael@0 186 mp_zero(r);
michael@0 187 return MP_OKAY;
michael@0 188 }
michael@0 189 return mp_sub(&meth->irr, a, r);
michael@0 190 }
michael@0 191
michael@0 192 /* Subtracts two field elements. Assumes that 0 <= a, b < meth->irr */
michael@0 193 mp_err
michael@0 194 ec_GFp_sub(const mp_int *a, const mp_int *b, mp_int *r,
michael@0 195 const GFMethod *meth)
michael@0 196 {
michael@0 197 mp_err res = MP_OKAY;
michael@0 198
michael@0 199 /* PRE: 0 <= a, b < p = meth->irr POST: 0 <= r < p, r = a - b (mod p) */
michael@0 200 res = mp_sub(a, b, r);
michael@0 201 if (res == MP_RANGE) {
michael@0 202 MP_CHECKOK(mp_sub(b, a, r));
michael@0 203 if (mp_cmp_z(r) < 0) {
michael@0 204 MP_CHECKOK(mp_add(r, &meth->irr, r));
michael@0 205 }
michael@0 206 MP_CHECKOK(ec_GFp_neg(r, r, meth));
michael@0 207 }
michael@0 208 if (mp_cmp_z(r) < 0) {
michael@0 209 MP_CHECKOK(mp_add(r, &meth->irr, r));
michael@0 210 }
michael@0 211 CLEANUP:
michael@0 212 return res;
michael@0 213 }
michael@0 214 /*
michael@0 215 * Inline adds for small curve lengths.
michael@0 216 */
michael@0 217 /* 3 words */
michael@0 218 mp_err
michael@0 219 ec_GFp_add_3(const mp_int *a, const mp_int *b, mp_int *r,
michael@0 220 const GFMethod *meth)
michael@0 221 {
michael@0 222 mp_err res = MP_OKAY;
michael@0 223 mp_digit a0 = 0, a1 = 0, a2 = 0;
michael@0 224 mp_digit r0 = 0, r1 = 0, r2 = 0;
michael@0 225 mp_digit carry;
michael@0 226
michael@0 227 switch(MP_USED(a)) {
michael@0 228 case 3:
michael@0 229 a2 = MP_DIGIT(a,2);
michael@0 230 case 2:
michael@0 231 a1 = MP_DIGIT(a,1);
michael@0 232 case 1:
michael@0 233 a0 = MP_DIGIT(a,0);
michael@0 234 }
michael@0 235 switch(MP_USED(b)) {
michael@0 236 case 3:
michael@0 237 r2 = MP_DIGIT(b,2);
michael@0 238 case 2:
michael@0 239 r1 = MP_DIGIT(b,1);
michael@0 240 case 1:
michael@0 241 r0 = MP_DIGIT(b,0);
michael@0 242 }
michael@0 243
michael@0 244 #ifndef MPI_AMD64_ADD
michael@0 245 MP_ADD_CARRY(a0, r0, r0, 0, carry);
michael@0 246 MP_ADD_CARRY(a1, r1, r1, carry, carry);
michael@0 247 MP_ADD_CARRY(a2, r2, r2, carry, carry);
michael@0 248 #else
michael@0 249 __asm__ (
michael@0 250 "xorq %3,%3 \n\t"
michael@0 251 "addq %4,%0 \n\t"
michael@0 252 "adcq %5,%1 \n\t"
michael@0 253 "adcq %6,%2 \n\t"
michael@0 254 "adcq $0,%3 \n\t"
michael@0 255 : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(carry)
michael@0 256 : "r" (a0), "r" (a1), "r" (a2),
michael@0 257 "0" (r0), "1" (r1), "2" (r2)
michael@0 258 : "%cc" );
michael@0 259 #endif
michael@0 260
michael@0 261 MP_CHECKOK(s_mp_pad(r, 3));
michael@0 262 MP_DIGIT(r, 2) = r2;
michael@0 263 MP_DIGIT(r, 1) = r1;
michael@0 264 MP_DIGIT(r, 0) = r0;
michael@0 265 MP_SIGN(r) = MP_ZPOS;
michael@0 266 MP_USED(r) = 3;
michael@0 267
michael@0 268 /* Do quick 'subract' if we've gone over
michael@0 269 * (add the 2's complement of the curve field) */
michael@0 270 a2 = MP_DIGIT(&meth->irr,2);
michael@0 271 if (carry || r2 > a2 ||
michael@0 272 ((r2 == a2) && mp_cmp(r,&meth->irr) != MP_LT)) {
michael@0 273 a1 = MP_DIGIT(&meth->irr,1);
michael@0 274 a0 = MP_DIGIT(&meth->irr,0);
michael@0 275 #ifndef MPI_AMD64_ADD
michael@0 276 MP_SUB_BORROW(r0, a0, r0, 0, carry);
michael@0 277 MP_SUB_BORROW(r1, a1, r1, carry, carry);
michael@0 278 MP_SUB_BORROW(r2, a2, r2, carry, carry);
michael@0 279 #else
michael@0 280 __asm__ (
michael@0 281 "subq %3,%0 \n\t"
michael@0 282 "sbbq %4,%1 \n\t"
michael@0 283 "sbbq %5,%2 \n\t"
michael@0 284 : "=r"(r0), "=r"(r1), "=r"(r2)
michael@0 285 : "r" (a0), "r" (a1), "r" (a2),
michael@0 286 "0" (r0), "1" (r1), "2" (r2)
michael@0 287 : "%cc" );
michael@0 288 #endif
michael@0 289 MP_DIGIT(r, 2) = r2;
michael@0 290 MP_DIGIT(r, 1) = r1;
michael@0 291 MP_DIGIT(r, 0) = r0;
michael@0 292 }
michael@0 293
michael@0 294 s_mp_clamp(r);
michael@0 295
michael@0 296 CLEANUP:
michael@0 297 return res;
michael@0 298 }
michael@0 299
michael@0 300 /* 4 words */
michael@0 301 mp_err
michael@0 302 ec_GFp_add_4(const mp_int *a, const mp_int *b, mp_int *r,
michael@0 303 const GFMethod *meth)
michael@0 304 {
michael@0 305 mp_err res = MP_OKAY;
michael@0 306 mp_digit a0 = 0, a1 = 0, a2 = 0, a3 = 0;
michael@0 307 mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0;
michael@0 308 mp_digit carry;
michael@0 309
michael@0 310 switch(MP_USED(a)) {
michael@0 311 case 4:
michael@0 312 a3 = MP_DIGIT(a,3);
michael@0 313 case 3:
michael@0 314 a2 = MP_DIGIT(a,2);
michael@0 315 case 2:
michael@0 316 a1 = MP_DIGIT(a,1);
michael@0 317 case 1:
michael@0 318 a0 = MP_DIGIT(a,0);
michael@0 319 }
michael@0 320 switch(MP_USED(b)) {
michael@0 321 case 4:
michael@0 322 r3 = MP_DIGIT(b,3);
michael@0 323 case 3:
michael@0 324 r2 = MP_DIGIT(b,2);
michael@0 325 case 2:
michael@0 326 r1 = MP_DIGIT(b,1);
michael@0 327 case 1:
michael@0 328 r0 = MP_DIGIT(b,0);
michael@0 329 }
michael@0 330
michael@0 331 #ifndef MPI_AMD64_ADD
michael@0 332 MP_ADD_CARRY(a0, r0, r0, 0, carry);
michael@0 333 MP_ADD_CARRY(a1, r1, r1, carry, carry);
michael@0 334 MP_ADD_CARRY(a2, r2, r2, carry, carry);
michael@0 335 MP_ADD_CARRY(a3, r3, r3, carry, carry);
michael@0 336 #else
michael@0 337 __asm__ (
michael@0 338 "xorq %4,%4 \n\t"
michael@0 339 "addq %5,%0 \n\t"
michael@0 340 "adcq %6,%1 \n\t"
michael@0 341 "adcq %7,%2 \n\t"
michael@0 342 "adcq %8,%3 \n\t"
michael@0 343 "adcq $0,%4 \n\t"
michael@0 344 : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(carry)
michael@0 345 : "r" (a0), "r" (a1), "r" (a2), "r" (a3),
michael@0 346 "0" (r0), "1" (r1), "2" (r2), "3" (r3)
michael@0 347 : "%cc" );
michael@0 348 #endif
michael@0 349
michael@0 350 MP_CHECKOK(s_mp_pad(r, 4));
michael@0 351 MP_DIGIT(r, 3) = r3;
michael@0 352 MP_DIGIT(r, 2) = r2;
michael@0 353 MP_DIGIT(r, 1) = r1;
michael@0 354 MP_DIGIT(r, 0) = r0;
michael@0 355 MP_SIGN(r) = MP_ZPOS;
michael@0 356 MP_USED(r) = 4;
michael@0 357
michael@0 358 /* Do quick 'subract' if we've gone over
michael@0 359 * (add the 2's complement of the curve field) */
michael@0 360 a3 = MP_DIGIT(&meth->irr,3);
michael@0 361 if (carry || r3 > a3 ||
michael@0 362 ((r3 == a3) && mp_cmp(r,&meth->irr) != MP_LT)) {
michael@0 363 a2 = MP_DIGIT(&meth->irr,2);
michael@0 364 a1 = MP_DIGIT(&meth->irr,1);
michael@0 365 a0 = MP_DIGIT(&meth->irr,0);
michael@0 366 #ifndef MPI_AMD64_ADD
michael@0 367 MP_SUB_BORROW(r0, a0, r0, 0, carry);
michael@0 368 MP_SUB_BORROW(r1, a1, r1, carry, carry);
michael@0 369 MP_SUB_BORROW(r2, a2, r2, carry, carry);
michael@0 370 MP_SUB_BORROW(r3, a3, r3, carry, carry);
michael@0 371 #else
michael@0 372 __asm__ (
michael@0 373 "subq %4,%0 \n\t"
michael@0 374 "sbbq %5,%1 \n\t"
michael@0 375 "sbbq %6,%2 \n\t"
michael@0 376 "sbbq %7,%3 \n\t"
michael@0 377 : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3)
michael@0 378 : "r" (a0), "r" (a1), "r" (a2), "r" (a3),
michael@0 379 "0" (r0), "1" (r1), "2" (r2), "3" (r3)
michael@0 380 : "%cc" );
michael@0 381 #endif
michael@0 382 MP_DIGIT(r, 3) = r3;
michael@0 383 MP_DIGIT(r, 2) = r2;
michael@0 384 MP_DIGIT(r, 1) = r1;
michael@0 385 MP_DIGIT(r, 0) = r0;
michael@0 386 }
michael@0 387
michael@0 388 s_mp_clamp(r);
michael@0 389
michael@0 390 CLEANUP:
michael@0 391 return res;
michael@0 392 }
michael@0 393
michael@0 394 /* 5 words */
michael@0 395 mp_err
michael@0 396 ec_GFp_add_5(const mp_int *a, const mp_int *b, mp_int *r,
michael@0 397 const GFMethod *meth)
michael@0 398 {
michael@0 399 mp_err res = MP_OKAY;
michael@0 400 mp_digit a0 = 0, a1 = 0, a2 = 0, a3 = 0, a4 = 0;
michael@0 401 mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0;
michael@0 402 mp_digit carry;
michael@0 403
michael@0 404 switch(MP_USED(a)) {
michael@0 405 case 5:
michael@0 406 a4 = MP_DIGIT(a,4);
michael@0 407 case 4:
michael@0 408 a3 = MP_DIGIT(a,3);
michael@0 409 case 3:
michael@0 410 a2 = MP_DIGIT(a,2);
michael@0 411 case 2:
michael@0 412 a1 = MP_DIGIT(a,1);
michael@0 413 case 1:
michael@0 414 a0 = MP_DIGIT(a,0);
michael@0 415 }
michael@0 416 switch(MP_USED(b)) {
michael@0 417 case 5:
michael@0 418 r4 = MP_DIGIT(b,4);
michael@0 419 case 4:
michael@0 420 r3 = MP_DIGIT(b,3);
michael@0 421 case 3:
michael@0 422 r2 = MP_DIGIT(b,2);
michael@0 423 case 2:
michael@0 424 r1 = MP_DIGIT(b,1);
michael@0 425 case 1:
michael@0 426 r0 = MP_DIGIT(b,0);
michael@0 427 }
michael@0 428
michael@0 429 MP_ADD_CARRY(a0, r0, r0, 0, carry);
michael@0 430 MP_ADD_CARRY(a1, r1, r1, carry, carry);
michael@0 431 MP_ADD_CARRY(a2, r2, r2, carry, carry);
michael@0 432 MP_ADD_CARRY(a3, r3, r3, carry, carry);
michael@0 433 MP_ADD_CARRY(a4, r4, r4, carry, carry);
michael@0 434
michael@0 435 MP_CHECKOK(s_mp_pad(r, 5));
michael@0 436 MP_DIGIT(r, 4) = r4;
michael@0 437 MP_DIGIT(r, 3) = r3;
michael@0 438 MP_DIGIT(r, 2) = r2;
michael@0 439 MP_DIGIT(r, 1) = r1;
michael@0 440 MP_DIGIT(r, 0) = r0;
michael@0 441 MP_SIGN(r) = MP_ZPOS;
michael@0 442 MP_USED(r) = 5;
michael@0 443
michael@0 444 /* Do quick 'subract' if we've gone over
michael@0 445 * (add the 2's complement of the curve field) */
michael@0 446 a4 = MP_DIGIT(&meth->irr,4);
michael@0 447 if (carry || r4 > a4 ||
michael@0 448 ((r4 == a4) && mp_cmp(r,&meth->irr) != MP_LT)) {
michael@0 449 a3 = MP_DIGIT(&meth->irr,3);
michael@0 450 a2 = MP_DIGIT(&meth->irr,2);
michael@0 451 a1 = MP_DIGIT(&meth->irr,1);
michael@0 452 a0 = MP_DIGIT(&meth->irr,0);
michael@0 453 MP_SUB_BORROW(r0, a0, r0, 0, carry);
michael@0 454 MP_SUB_BORROW(r1, a1, r1, carry, carry);
michael@0 455 MP_SUB_BORROW(r2, a2, r2, carry, carry);
michael@0 456 MP_SUB_BORROW(r3, a3, r3, carry, carry);
michael@0 457 MP_SUB_BORROW(r4, a4, r4, carry, carry);
michael@0 458 MP_DIGIT(r, 4) = r4;
michael@0 459 MP_DIGIT(r, 3) = r3;
michael@0 460 MP_DIGIT(r, 2) = r2;
michael@0 461 MP_DIGIT(r, 1) = r1;
michael@0 462 MP_DIGIT(r, 0) = r0;
michael@0 463 }
michael@0 464
michael@0 465 s_mp_clamp(r);
michael@0 466
michael@0 467 CLEANUP:
michael@0 468 return res;
michael@0 469 }
michael@0 470
michael@0 471 /* 6 words */
michael@0 472 mp_err
michael@0 473 ec_GFp_add_6(const mp_int *a, const mp_int *b, mp_int *r,
michael@0 474 const GFMethod *meth)
michael@0 475 {
michael@0 476 mp_err res = MP_OKAY;
michael@0 477 mp_digit a0 = 0, a1 = 0, a2 = 0, a3 = 0, a4 = 0, a5 = 0;
michael@0 478 mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0;
michael@0 479 mp_digit carry;
michael@0 480
michael@0 481 switch(MP_USED(a)) {
michael@0 482 case 6:
michael@0 483 a5 = MP_DIGIT(a,5);
michael@0 484 case 5:
michael@0 485 a4 = MP_DIGIT(a,4);
michael@0 486 case 4:
michael@0 487 a3 = MP_DIGIT(a,3);
michael@0 488 case 3:
michael@0 489 a2 = MP_DIGIT(a,2);
michael@0 490 case 2:
michael@0 491 a1 = MP_DIGIT(a,1);
michael@0 492 case 1:
michael@0 493 a0 = MP_DIGIT(a,0);
michael@0 494 }
michael@0 495 switch(MP_USED(b)) {
michael@0 496 case 6:
michael@0 497 r5 = MP_DIGIT(b,5);
michael@0 498 case 5:
michael@0 499 r4 = MP_DIGIT(b,4);
michael@0 500 case 4:
michael@0 501 r3 = MP_DIGIT(b,3);
michael@0 502 case 3:
michael@0 503 r2 = MP_DIGIT(b,2);
michael@0 504 case 2:
michael@0 505 r1 = MP_DIGIT(b,1);
michael@0 506 case 1:
michael@0 507 r0 = MP_DIGIT(b,0);
michael@0 508 }
michael@0 509
michael@0 510 MP_ADD_CARRY(a0, r0, r0, 0, carry);
michael@0 511 MP_ADD_CARRY(a1, r1, r1, carry, carry);
michael@0 512 MP_ADD_CARRY(a2, r2, r2, carry, carry);
michael@0 513 MP_ADD_CARRY(a3, r3, r3, carry, carry);
michael@0 514 MP_ADD_CARRY(a4, r4, r4, carry, carry);
michael@0 515 MP_ADD_CARRY(a5, r5, r5, carry, carry);
michael@0 516
michael@0 517 MP_CHECKOK(s_mp_pad(r, 6));
michael@0 518 MP_DIGIT(r, 5) = r5;
michael@0 519 MP_DIGIT(r, 4) = r4;
michael@0 520 MP_DIGIT(r, 3) = r3;
michael@0 521 MP_DIGIT(r, 2) = r2;
michael@0 522 MP_DIGIT(r, 1) = r1;
michael@0 523 MP_DIGIT(r, 0) = r0;
michael@0 524 MP_SIGN(r) = MP_ZPOS;
michael@0 525 MP_USED(r) = 6;
michael@0 526
michael@0 527 /* Do quick 'subract' if we've gone over
michael@0 528 * (add the 2's complement of the curve field) */
michael@0 529 a5 = MP_DIGIT(&meth->irr,5);
michael@0 530 if (carry || r5 > a5 ||
michael@0 531 ((r5 == a5) && mp_cmp(r,&meth->irr) != MP_LT)) {
michael@0 532 a4 = MP_DIGIT(&meth->irr,4);
michael@0 533 a3 = MP_DIGIT(&meth->irr,3);
michael@0 534 a2 = MP_DIGIT(&meth->irr,2);
michael@0 535 a1 = MP_DIGIT(&meth->irr,1);
michael@0 536 a0 = MP_DIGIT(&meth->irr,0);
michael@0 537 MP_SUB_BORROW(r0, a0, r0, 0, carry);
michael@0 538 MP_SUB_BORROW(r1, a1, r1, carry, carry);
michael@0 539 MP_SUB_BORROW(r2, a2, r2, carry, carry);
michael@0 540 MP_SUB_BORROW(r3, a3, r3, carry, carry);
michael@0 541 MP_SUB_BORROW(r4, a4, r4, carry, carry);
michael@0 542 MP_SUB_BORROW(r5, a5, r5, carry, carry);
michael@0 543 MP_DIGIT(r, 5) = r5;
michael@0 544 MP_DIGIT(r, 4) = r4;
michael@0 545 MP_DIGIT(r, 3) = r3;
michael@0 546 MP_DIGIT(r, 2) = r2;
michael@0 547 MP_DIGIT(r, 1) = r1;
michael@0 548 MP_DIGIT(r, 0) = r0;
michael@0 549 }
michael@0 550
michael@0 551 s_mp_clamp(r);
michael@0 552
michael@0 553 CLEANUP:
michael@0 554 return res;
michael@0 555 }
michael@0 556
michael@0 557 /*
michael@0 558 * The following subraction functions do in-line subractions based
michael@0 559 * on our curve size.
michael@0 560 *
michael@0 561 * ... 3 words
michael@0 562 */
michael@0 563 mp_err
michael@0 564 ec_GFp_sub_3(const mp_int *a, const mp_int *b, mp_int *r,
michael@0 565 const GFMethod *meth)
michael@0 566 {
michael@0 567 mp_err res = MP_OKAY;
michael@0 568 mp_digit b0 = 0, b1 = 0, b2 = 0;
michael@0 569 mp_digit r0 = 0, r1 = 0, r2 = 0;
michael@0 570 mp_digit borrow;
michael@0 571
michael@0 572 switch(MP_USED(a)) {
michael@0 573 case 3:
michael@0 574 r2 = MP_DIGIT(a,2);
michael@0 575 case 2:
michael@0 576 r1 = MP_DIGIT(a,1);
michael@0 577 case 1:
michael@0 578 r0 = MP_DIGIT(a,0);
michael@0 579 }
michael@0 580 switch(MP_USED(b)) {
michael@0 581 case 3:
michael@0 582 b2 = MP_DIGIT(b,2);
michael@0 583 case 2:
michael@0 584 b1 = MP_DIGIT(b,1);
michael@0 585 case 1:
michael@0 586 b0 = MP_DIGIT(b,0);
michael@0 587 }
michael@0 588
michael@0 589 #ifndef MPI_AMD64_ADD
michael@0 590 MP_SUB_BORROW(r0, b0, r0, 0, borrow);
michael@0 591 MP_SUB_BORROW(r1, b1, r1, borrow, borrow);
michael@0 592 MP_SUB_BORROW(r2, b2, r2, borrow, borrow);
michael@0 593 #else
michael@0 594 __asm__ (
michael@0 595 "xorq %3,%3 \n\t"
michael@0 596 "subq %4,%0 \n\t"
michael@0 597 "sbbq %5,%1 \n\t"
michael@0 598 "sbbq %6,%2 \n\t"
michael@0 599 "adcq $0,%3 \n\t"
michael@0 600 : "=r"(r0), "=r"(r1), "=r"(r2), "=r" (borrow)
michael@0 601 : "r" (b0), "r" (b1), "r" (b2),
michael@0 602 "0" (r0), "1" (r1), "2" (r2)
michael@0 603 : "%cc" );
michael@0 604 #endif
michael@0 605
michael@0 606 /* Do quick 'add' if we've gone under 0
michael@0 607 * (subtract the 2's complement of the curve field) */
michael@0 608 if (borrow) {
michael@0 609 b2 = MP_DIGIT(&meth->irr,2);
michael@0 610 b1 = MP_DIGIT(&meth->irr,1);
michael@0 611 b0 = MP_DIGIT(&meth->irr,0);
michael@0 612 #ifndef MPI_AMD64_ADD
michael@0 613 MP_ADD_CARRY(b0, r0, r0, 0, borrow);
michael@0 614 MP_ADD_CARRY(b1, r1, r1, borrow, borrow);
michael@0 615 MP_ADD_CARRY(b2, r2, r2, borrow, borrow);
michael@0 616 #else
michael@0 617 __asm__ (
michael@0 618 "addq %3,%0 \n\t"
michael@0 619 "adcq %4,%1 \n\t"
michael@0 620 "adcq %5,%2 \n\t"
michael@0 621 : "=r"(r0), "=r"(r1), "=r"(r2)
michael@0 622 : "r" (b0), "r" (b1), "r" (b2),
michael@0 623 "0" (r0), "1" (r1), "2" (r2)
michael@0 624 : "%cc" );
michael@0 625 #endif
michael@0 626 }
michael@0 627
michael@0 628 #ifdef MPI_AMD64_ADD
michael@0 629 /* compiler fakeout? */
michael@0 630 if ((r2 == b0) && (r1 == b0) && (r0 == b0)) {
michael@0 631 MP_CHECKOK(s_mp_pad(r, 4));
michael@0 632 }
michael@0 633 #endif
michael@0 634 MP_CHECKOK(s_mp_pad(r, 3));
michael@0 635 MP_DIGIT(r, 2) = r2;
michael@0 636 MP_DIGIT(r, 1) = r1;
michael@0 637 MP_DIGIT(r, 0) = r0;
michael@0 638 MP_SIGN(r) = MP_ZPOS;
michael@0 639 MP_USED(r) = 3;
michael@0 640 s_mp_clamp(r);
michael@0 641
michael@0 642 CLEANUP:
michael@0 643 return res;
michael@0 644 }
michael@0 645
michael@0 646 /* 4 words */
michael@0 647 mp_err
michael@0 648 ec_GFp_sub_4(const mp_int *a, const mp_int *b, mp_int *r,
michael@0 649 const GFMethod *meth)
michael@0 650 {
michael@0 651 mp_err res = MP_OKAY;
michael@0 652 mp_digit b0 = 0, b1 = 0, b2 = 0, b3 = 0;
michael@0 653 mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0;
michael@0 654 mp_digit borrow;
michael@0 655
michael@0 656 switch(MP_USED(a)) {
michael@0 657 case 4:
michael@0 658 r3 = MP_DIGIT(a,3);
michael@0 659 case 3:
michael@0 660 r2 = MP_DIGIT(a,2);
michael@0 661 case 2:
michael@0 662 r1 = MP_DIGIT(a,1);
michael@0 663 case 1:
michael@0 664 r0 = MP_DIGIT(a,0);
michael@0 665 }
michael@0 666 switch(MP_USED(b)) {
michael@0 667 case 4:
michael@0 668 b3 = MP_DIGIT(b,3);
michael@0 669 case 3:
michael@0 670 b2 = MP_DIGIT(b,2);
michael@0 671 case 2:
michael@0 672 b1 = MP_DIGIT(b,1);
michael@0 673 case 1:
michael@0 674 b0 = MP_DIGIT(b,0);
michael@0 675 }
michael@0 676
michael@0 677 #ifndef MPI_AMD64_ADD
michael@0 678 MP_SUB_BORROW(r0, b0, r0, 0, borrow);
michael@0 679 MP_SUB_BORROW(r1, b1, r1, borrow, borrow);
michael@0 680 MP_SUB_BORROW(r2, b2, r2, borrow, borrow);
michael@0 681 MP_SUB_BORROW(r3, b3, r3, borrow, borrow);
michael@0 682 #else
michael@0 683 __asm__ (
michael@0 684 "xorq %4,%4 \n\t"
michael@0 685 "subq %5,%0 \n\t"
michael@0 686 "sbbq %6,%1 \n\t"
michael@0 687 "sbbq %7,%2 \n\t"
michael@0 688 "sbbq %8,%3 \n\t"
michael@0 689 "adcq $0,%4 \n\t"
michael@0 690 : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r" (borrow)
michael@0 691 : "r" (b0), "r" (b1), "r" (b2), "r" (b3),
michael@0 692 "0" (r0), "1" (r1), "2" (r2), "3" (r3)
michael@0 693 : "%cc" );
michael@0 694 #endif
michael@0 695
michael@0 696 /* Do quick 'add' if we've gone under 0
michael@0 697 * (subtract the 2's complement of the curve field) */
michael@0 698 if (borrow) {
michael@0 699 b3 = MP_DIGIT(&meth->irr,3);
michael@0 700 b2 = MP_DIGIT(&meth->irr,2);
michael@0 701 b1 = MP_DIGIT(&meth->irr,1);
michael@0 702 b0 = MP_DIGIT(&meth->irr,0);
michael@0 703 #ifndef MPI_AMD64_ADD
michael@0 704 MP_ADD_CARRY(b0, r0, r0, 0, borrow);
michael@0 705 MP_ADD_CARRY(b1, r1, r1, borrow, borrow);
michael@0 706 MP_ADD_CARRY(b2, r2, r2, borrow, borrow);
michael@0 707 MP_ADD_CARRY(b3, r3, r3, borrow, borrow);
michael@0 708 #else
michael@0 709 __asm__ (
michael@0 710 "addq %4,%0 \n\t"
michael@0 711 "adcq %5,%1 \n\t"
michael@0 712 "adcq %6,%2 \n\t"
michael@0 713 "adcq %7,%3 \n\t"
michael@0 714 : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3)
michael@0 715 : "r" (b0), "r" (b1), "r" (b2), "r" (b3),
michael@0 716 "0" (r0), "1" (r1), "2" (r2), "3" (r3)
michael@0 717 : "%cc" );
michael@0 718 #endif
michael@0 719 }
michael@0 720 #ifdef MPI_AMD64_ADD
michael@0 721 /* compiler fakeout? */
michael@0 722 if ((r3 == b0) && (r1 == b0) && (r0 == b0)) {
michael@0 723 MP_CHECKOK(s_mp_pad(r, 4));
michael@0 724 }
michael@0 725 #endif
michael@0 726 MP_CHECKOK(s_mp_pad(r, 4));
michael@0 727 MP_DIGIT(r, 3) = r3;
michael@0 728 MP_DIGIT(r, 2) = r2;
michael@0 729 MP_DIGIT(r, 1) = r1;
michael@0 730 MP_DIGIT(r, 0) = r0;
michael@0 731 MP_SIGN(r) = MP_ZPOS;
michael@0 732 MP_USED(r) = 4;
michael@0 733 s_mp_clamp(r);
michael@0 734
michael@0 735 CLEANUP:
michael@0 736 return res;
michael@0 737 }
michael@0 738
michael@0 739 /* 5 words */
michael@0 740 mp_err
michael@0 741 ec_GFp_sub_5(const mp_int *a, const mp_int *b, mp_int *r,
michael@0 742 const GFMethod *meth)
michael@0 743 {
michael@0 744 mp_err res = MP_OKAY;
michael@0 745 mp_digit b0 = 0, b1 = 0, b2 = 0, b3 = 0, b4 = 0;
michael@0 746 mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0;
michael@0 747 mp_digit borrow;
michael@0 748
michael@0 749 switch(MP_USED(a)) {
michael@0 750 case 5:
michael@0 751 r4 = MP_DIGIT(a,4);
michael@0 752 case 4:
michael@0 753 r3 = MP_DIGIT(a,3);
michael@0 754 case 3:
michael@0 755 r2 = MP_DIGIT(a,2);
michael@0 756 case 2:
michael@0 757 r1 = MP_DIGIT(a,1);
michael@0 758 case 1:
michael@0 759 r0 = MP_DIGIT(a,0);
michael@0 760 }
michael@0 761 switch(MP_USED(b)) {
michael@0 762 case 5:
michael@0 763 b4 = MP_DIGIT(b,4);
michael@0 764 case 4:
michael@0 765 b3 = MP_DIGIT(b,3);
michael@0 766 case 3:
michael@0 767 b2 = MP_DIGIT(b,2);
michael@0 768 case 2:
michael@0 769 b1 = MP_DIGIT(b,1);
michael@0 770 case 1:
michael@0 771 b0 = MP_DIGIT(b,0);
michael@0 772 }
michael@0 773
michael@0 774 MP_SUB_BORROW(r0, b0, r0, 0, borrow);
michael@0 775 MP_SUB_BORROW(r1, b1, r1, borrow, borrow);
michael@0 776 MP_SUB_BORROW(r2, b2, r2, borrow, borrow);
michael@0 777 MP_SUB_BORROW(r3, b3, r3, borrow, borrow);
michael@0 778 MP_SUB_BORROW(r4, b4, r4, borrow, borrow);
michael@0 779
michael@0 780 /* Do quick 'add' if we've gone under 0
michael@0 781 * (subtract the 2's complement of the curve field) */
michael@0 782 if (borrow) {
michael@0 783 b4 = MP_DIGIT(&meth->irr,4);
michael@0 784 b3 = MP_DIGIT(&meth->irr,3);
michael@0 785 b2 = MP_DIGIT(&meth->irr,2);
michael@0 786 b1 = MP_DIGIT(&meth->irr,1);
michael@0 787 b0 = MP_DIGIT(&meth->irr,0);
michael@0 788 MP_ADD_CARRY(b0, r0, r0, 0, borrow);
michael@0 789 MP_ADD_CARRY(b1, r1, r1, borrow, borrow);
michael@0 790 MP_ADD_CARRY(b2, r2, r2, borrow, borrow);
michael@0 791 MP_ADD_CARRY(b3, r3, r3, borrow, borrow);
michael@0 792 }
michael@0 793 MP_CHECKOK(s_mp_pad(r, 5));
michael@0 794 MP_DIGIT(r, 4) = r4;
michael@0 795 MP_DIGIT(r, 3) = r3;
michael@0 796 MP_DIGIT(r, 2) = r2;
michael@0 797 MP_DIGIT(r, 1) = r1;
michael@0 798 MP_DIGIT(r, 0) = r0;
michael@0 799 MP_SIGN(r) = MP_ZPOS;
michael@0 800 MP_USED(r) = 5;
michael@0 801 s_mp_clamp(r);
michael@0 802
michael@0 803 CLEANUP:
michael@0 804 return res;
michael@0 805 }
michael@0 806
michael@0 807 /* 6 words */
michael@0 808 mp_err
michael@0 809 ec_GFp_sub_6(const mp_int *a, const mp_int *b, mp_int *r,
michael@0 810 const GFMethod *meth)
michael@0 811 {
michael@0 812 mp_err res = MP_OKAY;
michael@0 813 mp_digit b0 = 0, b1 = 0, b2 = 0, b3 = 0, b4 = 0, b5 = 0;
michael@0 814 mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0;
michael@0 815 mp_digit borrow;
michael@0 816
michael@0 817 switch(MP_USED(a)) {
michael@0 818 case 6:
michael@0 819 r5 = MP_DIGIT(a,5);
michael@0 820 case 5:
michael@0 821 r4 = MP_DIGIT(a,4);
michael@0 822 case 4:
michael@0 823 r3 = MP_DIGIT(a,3);
michael@0 824 case 3:
michael@0 825 r2 = MP_DIGIT(a,2);
michael@0 826 case 2:
michael@0 827 r1 = MP_DIGIT(a,1);
michael@0 828 case 1:
michael@0 829 r0 = MP_DIGIT(a,0);
michael@0 830 }
michael@0 831 switch(MP_USED(b)) {
michael@0 832 case 6:
michael@0 833 b5 = MP_DIGIT(b,5);
michael@0 834 case 5:
michael@0 835 b4 = MP_DIGIT(b,4);
michael@0 836 case 4:
michael@0 837 b3 = MP_DIGIT(b,3);
michael@0 838 case 3:
michael@0 839 b2 = MP_DIGIT(b,2);
michael@0 840 case 2:
michael@0 841 b1 = MP_DIGIT(b,1);
michael@0 842 case 1:
michael@0 843 b0 = MP_DIGIT(b,0);
michael@0 844 }
michael@0 845
michael@0 846 MP_SUB_BORROW(r0, b0, r0, 0, borrow);
michael@0 847 MP_SUB_BORROW(r1, b1, r1, borrow, borrow);
michael@0 848 MP_SUB_BORROW(r2, b2, r2, borrow, borrow);
michael@0 849 MP_SUB_BORROW(r3, b3, r3, borrow, borrow);
michael@0 850 MP_SUB_BORROW(r4, b4, r4, borrow, borrow);
michael@0 851 MP_SUB_BORROW(r5, b5, r5, borrow, borrow);
michael@0 852
michael@0 853 /* Do quick 'add' if we've gone under 0
michael@0 854 * (subtract the 2's complement of the curve field) */
michael@0 855 if (borrow) {
michael@0 856 b5 = MP_DIGIT(&meth->irr,5);
michael@0 857 b4 = MP_DIGIT(&meth->irr,4);
michael@0 858 b3 = MP_DIGIT(&meth->irr,3);
michael@0 859 b2 = MP_DIGIT(&meth->irr,2);
michael@0 860 b1 = MP_DIGIT(&meth->irr,1);
michael@0 861 b0 = MP_DIGIT(&meth->irr,0);
michael@0 862 MP_ADD_CARRY(b0, r0, r0, 0, borrow);
michael@0 863 MP_ADD_CARRY(b1, r1, r1, borrow, borrow);
michael@0 864 MP_ADD_CARRY(b2, r2, r2, borrow, borrow);
michael@0 865 MP_ADD_CARRY(b3, r3, r3, borrow, borrow);
michael@0 866 MP_ADD_CARRY(b4, r4, r4, borrow, borrow);
michael@0 867 }
michael@0 868
michael@0 869 MP_CHECKOK(s_mp_pad(r, 6));
michael@0 870 MP_DIGIT(r, 5) = r5;
michael@0 871 MP_DIGIT(r, 4) = r4;
michael@0 872 MP_DIGIT(r, 3) = r3;
michael@0 873 MP_DIGIT(r, 2) = r2;
michael@0 874 MP_DIGIT(r, 1) = r1;
michael@0 875 MP_DIGIT(r, 0) = r0;
michael@0 876 MP_SIGN(r) = MP_ZPOS;
michael@0 877 MP_USED(r) = 6;
michael@0 878 s_mp_clamp(r);
michael@0 879
michael@0 880 CLEANUP:
michael@0 881 return res;
michael@0 882 }
michael@0 883
michael@0 884
michael@0 885 /* Reduces an integer to a field element. */
michael@0 886 mp_err
michael@0 887 ec_GFp_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
michael@0 888 {
michael@0 889 return mp_mod(a, &meth->irr, r);
michael@0 890 }
michael@0 891
michael@0 892 /* Multiplies two field elements. */
michael@0 893 mp_err
michael@0 894 ec_GFp_mul(const mp_int *a, const mp_int *b, mp_int *r,
michael@0 895 const GFMethod *meth)
michael@0 896 {
michael@0 897 return mp_mulmod(a, b, &meth->irr, r);
michael@0 898 }
michael@0 899
michael@0 900 /* Squares a field element. */
michael@0 901 mp_err
michael@0 902 ec_GFp_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
michael@0 903 {
michael@0 904 return mp_sqrmod(a, &meth->irr, r);
michael@0 905 }
michael@0 906
michael@0 907 /* Divides two field elements. If a is NULL, then returns the inverse of
michael@0 908 * b. */
michael@0 909 mp_err
michael@0 910 ec_GFp_div(const mp_int *a, const mp_int *b, mp_int *r,
michael@0 911 const GFMethod *meth)
michael@0 912 {
michael@0 913 mp_err res = MP_OKAY;
michael@0 914 mp_int t;
michael@0 915
michael@0 916 /* If a is NULL, then return the inverse of b, otherwise return a/b. */
michael@0 917 if (a == NULL) {
michael@0 918 return mp_invmod(b, &meth->irr, r);
michael@0 919 } else {
michael@0 920 /* MPI doesn't support divmod, so we implement it using invmod and
michael@0 921 * mulmod. */
michael@0 922 MP_CHECKOK(mp_init(&t));
michael@0 923 MP_CHECKOK(mp_invmod(b, &meth->irr, &t));
michael@0 924 MP_CHECKOK(mp_mulmod(a, &t, &meth->irr, r));
michael@0 925 CLEANUP:
michael@0 926 mp_clear(&t);
michael@0 927 return res;
michael@0 928 }
michael@0 929 }
michael@0 930
michael@0 931 /* Wrapper functions for generic binary polynomial field arithmetic. */
michael@0 932
michael@0 933 /* Adds two field elements. */
michael@0 934 mp_err
michael@0 935 ec_GF2m_add(const mp_int *a, const mp_int *b, mp_int *r,
michael@0 936 const GFMethod *meth)
michael@0 937 {
michael@0 938 return mp_badd(a, b, r);
michael@0 939 }
michael@0 940
michael@0 941 /* Negates a field element. Note that for binary polynomial fields, the
michael@0 942 * negation of a field element is the field element itself. */
michael@0 943 mp_err
michael@0 944 ec_GF2m_neg(const mp_int *a, mp_int *r, const GFMethod *meth)
michael@0 945 {
michael@0 946 if (a == r) {
michael@0 947 return MP_OKAY;
michael@0 948 } else {
michael@0 949 return mp_copy(a, r);
michael@0 950 }
michael@0 951 }
michael@0 952
michael@0 953 /* Reduces a binary polynomial to a field element. */
michael@0 954 mp_err
michael@0 955 ec_GF2m_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
michael@0 956 {
michael@0 957 return mp_bmod(a, meth->irr_arr, r);
michael@0 958 }
michael@0 959
michael@0 960 /* Multiplies two field elements. */
michael@0 961 mp_err
michael@0 962 ec_GF2m_mul(const mp_int *a, const mp_int *b, mp_int *r,
michael@0 963 const GFMethod *meth)
michael@0 964 {
michael@0 965 return mp_bmulmod(a, b, meth->irr_arr, r);
michael@0 966 }
michael@0 967
michael@0 968 /* Squares a field element. */
michael@0 969 mp_err
michael@0 970 ec_GF2m_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
michael@0 971 {
michael@0 972 return mp_bsqrmod(a, meth->irr_arr, r);
michael@0 973 }
michael@0 974
michael@0 975 /* Divides two field elements. If a is NULL, then returns the inverse of
michael@0 976 * b. */
michael@0 977 mp_err
michael@0 978 ec_GF2m_div(const mp_int *a, const mp_int *b, mp_int *r,
michael@0 979 const GFMethod *meth)
michael@0 980 {
michael@0 981 mp_err res = MP_OKAY;
michael@0 982 mp_int t;
michael@0 983
michael@0 984 /* If a is NULL, then return the inverse of b, otherwise return a/b. */
michael@0 985 if (a == NULL) {
michael@0 986 /* The GF(2^m) portion of MPI doesn't support invmod, so we
michael@0 987 * compute 1/b. */
michael@0 988 MP_CHECKOK(mp_init(&t));
michael@0 989 MP_CHECKOK(mp_set_int(&t, 1));
michael@0 990 MP_CHECKOK(mp_bdivmod(&t, b, &meth->irr, meth->irr_arr, r));
michael@0 991 CLEANUP:
michael@0 992 mp_clear(&t);
michael@0 993 return res;
michael@0 994 } else {
michael@0 995 return mp_bdivmod(a, b, &meth->irr, meth->irr_arr, r);
michael@0 996 }
michael@0 997 }

mercurial