jdk/src/share/native/sun/security/ec/ecp_192.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 for prime field curves.
       
    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  *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
       
    38  *
       
    39  * Alternatively, the contents of this file may be used under the terms of
       
    40  * either the GNU General Public License Version 2 or later (the "GPL"), or
       
    41  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
       
    42  * in which case the provisions of the GPL or the LGPL are applicable instead
       
    43  * of those above. If you wish to allow use of your version of this file only
       
    44  * under the terms of either the GPL or the LGPL, and not to allow others to
       
    45  * use your version of this file under the terms of the MPL, indicate your
       
    46  * decision by deleting the provisions above and replace them with the notice
       
    47  * and other provisions required by the GPL or the LGPL. If you do not delete
       
    48  * the provisions above, a recipient may use your version of this file under
       
    49  * the terms of any one of the MPL, the GPL or the LGPL.
       
    50  *
       
    51  *********************************************************************** */
       
    52 /*
       
    53  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
       
    54  * Use is subject to license terms.
       
    55  */
       
    56 
       
    57 #pragma ident   "%Z%%M% %I%     %E% SMI"
       
    58 
       
    59 #include "ecp.h"
       
    60 #include "mpi.h"
       
    61 #include "mplogic.h"
       
    62 #include "mpi-priv.h"
       
    63 #ifndef _KERNEL
       
    64 #include <stdlib.h>
       
    65 #endif
       
    66 
       
    67 #define ECP192_DIGITS ECL_CURVE_DIGITS(192)
       
    68 
       
    69 /* Fast modular reduction for p192 = 2^192 - 2^64 - 1.  a can be r. Uses
       
    70  * algorithm 7 from Brown, Hankerson, Lopez, Menezes. Software
       
    71  * Implementation of the NIST Elliptic Curves over Prime Fields. */
       
    72 mp_err
       
    73 ec_GFp_nistp192_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
       
    74 {
       
    75         mp_err res = MP_OKAY;
       
    76         mp_size a_used = MP_USED(a);
       
    77         mp_digit r3;
       
    78 #ifndef MPI_AMD64_ADD
       
    79         mp_digit carry;
       
    80 #endif
       
    81 #ifdef ECL_THIRTY_TWO_BIT
       
    82         mp_digit a5a = 0, a5b = 0, a4a = 0, a4b = 0, a3a = 0, a3b = 0;
       
    83         mp_digit r0a, r0b, r1a, r1b, r2a, r2b;
       
    84 #else
       
    85         mp_digit a5 = 0, a4 = 0, a3 = 0;
       
    86         mp_digit r0, r1, r2;
       
    87 #endif
       
    88 
       
    89         /* reduction not needed if a is not larger than field size */
       
    90         if (a_used < ECP192_DIGITS) {
       
    91                 if (a == r) {
       
    92                         return MP_OKAY;
       
    93                 }
       
    94                 return mp_copy(a, r);
       
    95         }
       
    96 
       
    97         /* for polynomials larger than twice the field size, use regular
       
    98          * reduction */
       
    99         if (a_used > ECP192_DIGITS*2) {
       
   100                 MP_CHECKOK(mp_mod(a, &meth->irr, r));
       
   101         } else {
       
   102                 /* copy out upper words of a */
       
   103 
       
   104 #ifdef ECL_THIRTY_TWO_BIT
       
   105 
       
   106                 /* in all the math below,
       
   107                  * nXb is most signifiant, nXa is least significant */
       
   108                 switch (a_used) {
       
   109                 case 12:
       
   110                         a5b = MP_DIGIT(a, 11);
       
   111                 case 11:
       
   112                         a5a = MP_DIGIT(a, 10);
       
   113                 case 10:
       
   114                         a4b = MP_DIGIT(a, 9);
       
   115                 case 9:
       
   116                         a4a = MP_DIGIT(a, 8);
       
   117                 case 8:
       
   118                         a3b = MP_DIGIT(a, 7);
       
   119                 case 7:
       
   120                         a3a = MP_DIGIT(a, 6);
       
   121                 }
       
   122 
       
   123 
       
   124                 r2b= MP_DIGIT(a, 5);
       
   125                 r2a= MP_DIGIT(a, 4);
       
   126                 r1b = MP_DIGIT(a, 3);
       
   127                 r1a = MP_DIGIT(a, 2);
       
   128                 r0b = MP_DIGIT(a, 1);
       
   129                 r0a = MP_DIGIT(a, 0);
       
   130 
       
   131                 /* implement r = (a2,a1,a0)+(a5,a5,a5)+(a4,a4,0)+(0,a3,a3) */
       
   132                 MP_ADD_CARRY(r0a, a3a, r0a, 0,    carry);
       
   133                 MP_ADD_CARRY(r0b, a3b, r0b, carry, carry);
       
   134                 MP_ADD_CARRY(r1a, a3a, r1a, carry, carry);
       
   135                 MP_ADD_CARRY(r1b, a3b, r1b, carry, carry);
       
   136                 MP_ADD_CARRY(r2a, a4a, r2a, carry, carry);
       
   137                 MP_ADD_CARRY(r2b, a4b, r2b, carry, carry);
       
   138                 r3 = carry; carry = 0;
       
   139                 MP_ADD_CARRY(r0a, a5a, r0a, 0,     carry);
       
   140                 MP_ADD_CARRY(r0b, a5b, r0b, carry, carry);
       
   141                 MP_ADD_CARRY(r1a, a5a, r1a, carry, carry);
       
   142                 MP_ADD_CARRY(r1b, a5b, r1b, carry, carry);
       
   143                 MP_ADD_CARRY(r2a, a5a, r2a, carry, carry);
       
   144                 MP_ADD_CARRY(r2b, a5b, r2b, carry, carry);
       
   145                 r3 += carry;
       
   146                 MP_ADD_CARRY(r1a, a4a, r1a, 0,     carry);
       
   147                 MP_ADD_CARRY(r1b, a4b, r1b, carry, carry);
       
   148                 MP_ADD_CARRY(r2a,   0, r2a, carry, carry);
       
   149                 MP_ADD_CARRY(r2b,   0, r2b, carry, carry);
       
   150                 r3 += carry;
       
   151 
       
   152                 /* reduce out the carry */
       
   153                 while (r3) {
       
   154                         MP_ADD_CARRY(r0a, r3, r0a, 0,     carry);
       
   155                         MP_ADD_CARRY(r0b,  0, r0b, carry, carry);
       
   156                         MP_ADD_CARRY(r1a, r3, r1a, carry, carry);
       
   157                         MP_ADD_CARRY(r1b,  0, r1b, carry, carry);
       
   158                         MP_ADD_CARRY(r2a,  0, r2a, carry, carry);
       
   159                         MP_ADD_CARRY(r2b,  0, r2b, carry, carry);
       
   160                         r3 = carry;
       
   161                 }
       
   162 
       
   163                 /* check for final reduction */
       
   164                 /*
       
   165                  * our field is 0xffffffffffffffff, 0xfffffffffffffffe,
       
   166                  * 0xffffffffffffffff. That means we can only be over and need
       
   167                  * one more reduction
       
   168                  *  if r2 == 0xffffffffffffffffff (same as r2+1 == 0)
       
   169                  *     and
       
   170                  *     r1 == 0xffffffffffffffffff   or
       
   171                  *     r1 == 0xfffffffffffffffffe and r0 = 0xfffffffffffffffff
       
   172                  * In all cases, we subtract the field (or add the 2's
       
   173                  * complement value (1,1,0)).  (r0, r1, r2)
       
   174                  */
       
   175                 if (((r2b == 0xffffffff) && (r2a == 0xffffffff)
       
   176                         && (r1b == 0xffffffff) ) &&
       
   177                            ((r1a == 0xffffffff) ||
       
   178                             (r1a == 0xfffffffe) && (r0a == 0xffffffff) &&
       
   179                                         (r0b == 0xffffffff)) ) {
       
   180                         /* do a quick subtract */
       
   181                         MP_ADD_CARRY(r0a, 1, r0a, 0, carry);
       
   182                         r0b += carry;
       
   183                         r1a = r1b = r2a = r2b = 0;
       
   184                 }
       
   185 
       
   186                 /* set the lower words of r */
       
   187                 if (a != r) {
       
   188                         MP_CHECKOK(s_mp_pad(r, 6));
       
   189                 }
       
   190                 MP_DIGIT(r, 5) = r2b;
       
   191                 MP_DIGIT(r, 4) = r2a;
       
   192                 MP_DIGIT(r, 3) = r1b;
       
   193                 MP_DIGIT(r, 2) = r1a;
       
   194                 MP_DIGIT(r, 1) = r0b;
       
   195                 MP_DIGIT(r, 0) = r0a;
       
   196                 MP_USED(r) = 6;
       
   197 #else
       
   198                 switch (a_used) {
       
   199                 case 6:
       
   200                         a5 = MP_DIGIT(a, 5);
       
   201                 case 5:
       
   202                         a4 = MP_DIGIT(a, 4);
       
   203                 case 4:
       
   204                         a3 = MP_DIGIT(a, 3);
       
   205                 }
       
   206 
       
   207                 r2 = MP_DIGIT(a, 2);
       
   208                 r1 = MP_DIGIT(a, 1);
       
   209                 r0 = MP_DIGIT(a, 0);
       
   210 
       
   211                 /* implement r = (a2,a1,a0)+(a5,a5,a5)+(a4,a4,0)+(0,a3,a3) */
       
   212 #ifndef MPI_AMD64_ADD
       
   213                 MP_ADD_CARRY(r0, a3, r0, 0,     carry);
       
   214                 MP_ADD_CARRY(r1, a3, r1, carry, carry);
       
   215                 MP_ADD_CARRY(r2, a4, r2, carry, carry);
       
   216                 r3 = carry;
       
   217                 MP_ADD_CARRY(r0, a5, r0, 0,     carry);
       
   218                 MP_ADD_CARRY(r1, a5, r1, carry, carry);
       
   219                 MP_ADD_CARRY(r2, a5, r2, carry, carry);
       
   220                 r3 += carry;
       
   221                 MP_ADD_CARRY(r1, a4, r1, 0,     carry);
       
   222                 MP_ADD_CARRY(r2,  0, r2, carry, carry);
       
   223                 r3 += carry;
       
   224 
       
   225 #else
       
   226                 r2 = MP_DIGIT(a, 2);
       
   227                 r1 = MP_DIGIT(a, 1);
       
   228                 r0 = MP_DIGIT(a, 0);
       
   229 
       
   230                 /* set the lower words of r */
       
   231                 __asm__ (
       
   232                 "xorq   %3,%3           \n\t"
       
   233                 "addq   %4,%0           \n\t"
       
   234                 "adcq   %4,%1           \n\t"
       
   235                 "adcq   %5,%2           \n\t"
       
   236                 "adcq   $0,%3           \n\t"
       
   237                 "addq   %6,%0           \n\t"
       
   238                 "adcq   %6,%1           \n\t"
       
   239                 "adcq   %6,%2           \n\t"
       
   240                 "adcq   $0,%3           \n\t"
       
   241                 "addq   %5,%1           \n\t"
       
   242                 "adcq   $0,%2           \n\t"
       
   243                 "adcq   $0,%3           \n\t"
       
   244                 : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(a3),
       
   245                   "=r"(a4), "=r"(a5)
       
   246                 : "0" (r0), "1" (r1), "2" (r2), "3" (r3),
       
   247                   "4" (a3), "5" (a4), "6"(a5)
       
   248                 : "%cc" );
       
   249 #endif
       
   250 
       
   251                 /* reduce out the carry */
       
   252                 while (r3) {
       
   253 #ifndef MPI_AMD64_ADD
       
   254                         MP_ADD_CARRY(r0, r3, r0, 0,     carry);
       
   255                         MP_ADD_CARRY(r1, r3, r1, carry, carry);
       
   256                         MP_ADD_CARRY(r2,  0, r2, carry, carry);
       
   257                         r3 = carry;
       
   258 #else
       
   259                         a3=r3;
       
   260                         __asm__ (
       
   261                         "xorq   %3,%3           \n\t"
       
   262                         "addq   %4,%0           \n\t"
       
   263                         "adcq   %4,%1           \n\t"
       
   264                         "adcq   $0,%2           \n\t"
       
   265                         "adcq   $0,%3           \n\t"
       
   266                         : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(a3)
       
   267                         : "0" (r0), "1" (r1), "2" (r2), "3" (r3), "4"(a3)
       
   268                         : "%cc" );
       
   269 #endif
       
   270                 }
       
   271 
       
   272                 /* check for final reduction */
       
   273                 /*
       
   274                  * our field is 0xffffffffffffffff, 0xfffffffffffffffe,
       
   275                  * 0xffffffffffffffff. That means we can only be over and need
       
   276                  * one more reduction
       
   277                  *  if r2 == 0xffffffffffffffffff (same as r2+1 == 0)
       
   278                  *     and
       
   279                  *     r1 == 0xffffffffffffffffff   or
       
   280                  *     r1 == 0xfffffffffffffffffe and r0 = 0xfffffffffffffffff
       
   281                  * In all cases, we subtract the field (or add the 2's
       
   282                  * complement value (1,1,0)).  (r0, r1, r2)
       
   283                  */
       
   284                 if (r3 || ((r2 == MP_DIGIT_MAX) &&
       
   285                       ((r1 == MP_DIGIT_MAX) ||
       
   286                         ((r1 == (MP_DIGIT_MAX-1)) && (r0 == MP_DIGIT_MAX))))) {
       
   287                         /* do a quick subtract */
       
   288                         r0++;
       
   289                         r1 = r2 = 0;
       
   290                 }
       
   291                 /* set the lower words of r */
       
   292                 if (a != r) {
       
   293                         MP_CHECKOK(s_mp_pad(r, 3));
       
   294                 }
       
   295                 MP_DIGIT(r, 2) = r2;
       
   296                 MP_DIGIT(r, 1) = r1;
       
   297                 MP_DIGIT(r, 0) = r0;
       
   298                 MP_USED(r) = 3;
       
   299 #endif
       
   300         }
       
   301 
       
   302   CLEANUP:
       
   303         return res;
       
   304 }
       
   305 
       
   306 #ifndef ECL_THIRTY_TWO_BIT
       
   307 /* Compute the sum of 192 bit curves. Do the work in-line since the
       
   308  * number of words are so small, we don't want to overhead of mp function
       
   309  * calls.  Uses optimized modular reduction for p192.
       
   310  */
       
   311 mp_err
       
   312 ec_GFp_nistp192_add(const mp_int *a, const mp_int *b, mp_int *r,
       
   313                         const GFMethod *meth)
       
   314 {
       
   315         mp_err res = MP_OKAY;
       
   316         mp_digit a0 = 0, a1 = 0, a2 = 0;
       
   317         mp_digit r0 = 0, r1 = 0, r2 = 0;
       
   318         mp_digit carry;
       
   319 
       
   320         switch(MP_USED(a)) {
       
   321         case 3:
       
   322                 a2 = MP_DIGIT(a,2);
       
   323         case 2:
       
   324                 a1 = MP_DIGIT(a,1);
       
   325         case 1:
       
   326                 a0 = MP_DIGIT(a,0);
       
   327         }
       
   328         switch(MP_USED(b)) {
       
   329         case 3:
       
   330                 r2 = MP_DIGIT(b,2);
       
   331         case 2:
       
   332                 r1 = MP_DIGIT(b,1);
       
   333         case 1:
       
   334                 r0 = MP_DIGIT(b,0);
       
   335         }
       
   336 
       
   337 #ifndef MPI_AMD64_ADD
       
   338         MP_ADD_CARRY(a0, r0, r0, 0,     carry);
       
   339         MP_ADD_CARRY(a1, r1, r1, carry, carry);
       
   340         MP_ADD_CARRY(a2, r2, r2, carry, carry);
       
   341 #else
       
   342         __asm__ (
       
   343                 "xorq   %3,%3           \n\t"
       
   344                 "addq   %4,%0           \n\t"
       
   345                 "adcq   %5,%1           \n\t"
       
   346                 "adcq   %6,%2           \n\t"
       
   347                 "adcq   $0,%3           \n\t"
       
   348                 : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(carry)
       
   349                 : "r" (a0), "r" (a1), "r" (a2), "0" (r0),
       
   350                   "1" (r1), "2" (r2)
       
   351                 : "%cc" );
       
   352 #endif
       
   353 
       
   354         /* Do quick 'subract' if we've gone over
       
   355          * (add the 2's complement of the curve field) */
       
   356         if (carry || ((r2 == MP_DIGIT_MAX) &&
       
   357                       ((r1 == MP_DIGIT_MAX) ||
       
   358                         ((r1 == (MP_DIGIT_MAX-1)) && (r0 == MP_DIGIT_MAX))))) {
       
   359 #ifndef MPI_AMD64_ADD
       
   360                 MP_ADD_CARRY(r0, 1, r0, 0,     carry);
       
   361                 MP_ADD_CARRY(r1, 1, r1, carry, carry);
       
   362                 MP_ADD_CARRY(r2, 0, r2, carry, carry);
       
   363 #else
       
   364                 __asm__ (
       
   365                         "addq   $1,%0           \n\t"
       
   366                         "adcq   $1,%1           \n\t"
       
   367                         "adcq   $0,%2           \n\t"
       
   368                         : "=r"(r0), "=r"(r1), "=r"(r2)
       
   369                         : "0" (r0), "1" (r1), "2" (r2)
       
   370                         : "%cc" );
       
   371 #endif
       
   372         }
       
   373 
       
   374 
       
   375         MP_CHECKOK(s_mp_pad(r, 3));
       
   376         MP_DIGIT(r, 2) = r2;
       
   377         MP_DIGIT(r, 1) = r1;
       
   378         MP_DIGIT(r, 0) = r0;
       
   379         MP_SIGN(r) = MP_ZPOS;
       
   380         MP_USED(r) = 3;
       
   381         s_mp_clamp(r);
       
   382 
       
   383 
       
   384   CLEANUP:
       
   385         return res;
       
   386 }
       
   387 
       
   388 /* Compute the diff of 192 bit curves. Do the work in-line since the
       
   389  * number of words are so small, we don't want to overhead of mp function
       
   390  * calls.  Uses optimized modular reduction for p192.
       
   391  */
       
   392 mp_err
       
   393 ec_GFp_nistp192_sub(const mp_int *a, const mp_int *b, mp_int *r,
       
   394                         const GFMethod *meth)
       
   395 {
       
   396         mp_err res = MP_OKAY;
       
   397         mp_digit b0 = 0, b1 = 0, b2 = 0;
       
   398         mp_digit r0 = 0, r1 = 0, r2 = 0;
       
   399         mp_digit borrow;
       
   400 
       
   401         switch(MP_USED(a)) {
       
   402         case 3:
       
   403                 r2 = MP_DIGIT(a,2);
       
   404         case 2:
       
   405                 r1 = MP_DIGIT(a,1);
       
   406         case 1:
       
   407                 r0 = MP_DIGIT(a,0);
       
   408         }
       
   409 
       
   410         switch(MP_USED(b)) {
       
   411         case 3:
       
   412                 b2 = MP_DIGIT(b,2);
       
   413         case 2:
       
   414                 b1 = MP_DIGIT(b,1);
       
   415         case 1:
       
   416                 b0 = MP_DIGIT(b,0);
       
   417         }
       
   418 
       
   419 #ifndef MPI_AMD64_ADD
       
   420         MP_SUB_BORROW(r0, b0, r0, 0,     borrow);
       
   421         MP_SUB_BORROW(r1, b1, r1, borrow, borrow);
       
   422         MP_SUB_BORROW(r2, b2, r2, borrow, borrow);
       
   423 #else
       
   424         __asm__ (
       
   425                 "xorq   %3,%3           \n\t"
       
   426                 "subq   %4,%0           \n\t"
       
   427                 "sbbq   %5,%1           \n\t"
       
   428                 "sbbq   %6,%2           \n\t"
       
   429                 "adcq   $0,%3           \n\t"
       
   430                 : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(borrow)
       
   431                 : "r" (b0), "r" (b1), "r" (b2), "0" (r0),
       
   432                   "1" (r1), "2" (r2)
       
   433                 : "%cc" );
       
   434 #endif
       
   435 
       
   436         /* Do quick 'add' if we've gone under 0
       
   437          * (subtract the 2's complement of the curve field) */
       
   438         if (borrow) {
       
   439 #ifndef MPI_AMD64_ADD
       
   440                 MP_SUB_BORROW(r0, 1, r0, 0,     borrow);
       
   441                 MP_SUB_BORROW(r1, 1, r1, borrow, borrow);
       
   442                 MP_SUB_BORROW(r2,  0, r2, borrow, borrow);
       
   443 #else
       
   444                 __asm__ (
       
   445                         "subq   $1,%0           \n\t"
       
   446                         "sbbq   $1,%1           \n\t"
       
   447                         "sbbq   $0,%2           \n\t"
       
   448                         : "=r"(r0), "=r"(r1), "=r"(r2)
       
   449                         : "0" (r0), "1" (r1), "2" (r2)
       
   450                         : "%cc" );
       
   451 #endif
       
   452         }
       
   453 
       
   454         MP_CHECKOK(s_mp_pad(r, 3));
       
   455         MP_DIGIT(r, 2) = r2;
       
   456         MP_DIGIT(r, 1) = r1;
       
   457         MP_DIGIT(r, 0) = r0;
       
   458         MP_SIGN(r) = MP_ZPOS;
       
   459         MP_USED(r) = 3;
       
   460         s_mp_clamp(r);
       
   461 
       
   462   CLEANUP:
       
   463         return res;
       
   464 }
       
   465 
       
   466 #endif
       
   467 
       
   468 /* Compute the square of polynomial a, reduce modulo p192. Store the
       
   469  * result in r.  r could be a.  Uses optimized modular reduction for p192.
       
   470  */
       
   471 mp_err
       
   472 ec_GFp_nistp192_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
       
   473 {
       
   474         mp_err res = MP_OKAY;
       
   475 
       
   476         MP_CHECKOK(mp_sqr(a, r));
       
   477         MP_CHECKOK(ec_GFp_nistp192_mod(r, r, meth));
       
   478   CLEANUP:
       
   479         return res;
       
   480 }
       
   481 
       
   482 /* Compute the product of two polynomials a and b, reduce modulo p192.
       
   483  * Store the result in r.  r could be a or b; a could be b.  Uses
       
   484  * optimized modular reduction for p192. */
       
   485 mp_err
       
   486 ec_GFp_nistp192_mul(const mp_int *a, const mp_int *b, mp_int *r,
       
   487                                         const GFMethod *meth)
       
   488 {
       
   489         mp_err res = MP_OKAY;
       
   490 
       
   491         MP_CHECKOK(mp_mul(a, b, r));
       
   492         MP_CHECKOK(ec_GFp_nistp192_mod(r, r, meth));
       
   493   CLEANUP:
       
   494         return res;
       
   495 }
       
   496 
       
   497 /* Divides two field elements. If a is NULL, then returns the inverse of
       
   498  * b. */
       
   499 mp_err
       
   500 ec_GFp_nistp192_div(const mp_int *a, const mp_int *b, mp_int *r,
       
   501                    const GFMethod *meth)
       
   502 {
       
   503         mp_err res = MP_OKAY;
       
   504         mp_int t;
       
   505 
       
   506         /* If a is NULL, then return the inverse of b, otherwise return a/b. */
       
   507         if (a == NULL) {
       
   508                 return  mp_invmod(b, &meth->irr, r);
       
   509         } else {
       
   510                 /* MPI doesn't support divmod, so we implement it using invmod and
       
   511                  * mulmod. */
       
   512                 MP_CHECKOK(mp_init(&t, FLAG(b)));
       
   513                 MP_CHECKOK(mp_invmod(b, &meth->irr, &t));
       
   514                 MP_CHECKOK(mp_mul(a, &t, r));
       
   515                 MP_CHECKOK(ec_GFp_nistp192_mod(r, r, meth));
       
   516           CLEANUP:
       
   517                 mp_clear(&t);
       
   518                 return res;
       
   519         }
       
   520 }
       
   521 
       
   522 /* Wire in fast field arithmetic and precomputation of base point for
       
   523  * named curves. */
       
   524 mp_err
       
   525 ec_group_set_gfp192(ECGroup *group, ECCurveName name)
       
   526 {
       
   527         if (name == ECCurve_NIST_P192) {
       
   528                 group->meth->field_mod = &ec_GFp_nistp192_mod;
       
   529                 group->meth->field_mul = &ec_GFp_nistp192_mul;
       
   530                 group->meth->field_sqr = &ec_GFp_nistp192_sqr;
       
   531                 group->meth->field_div = &ec_GFp_nistp192_div;
       
   532 #ifndef ECL_THIRTY_TWO_BIT
       
   533                 group->meth->field_add = &ec_GFp_nistp192_add;
       
   534                 group->meth->field_sub = &ec_GFp_nistp192_sub;
       
   535 #endif
       
   536         }
       
   537         return MP_OKAY;
       
   538 }