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