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