jdk/src/share/native/sun/security/ec/ecp_521.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>
       
    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 ECP521_DIGITS ECL_CURVE_DIGITS(521)
       
    68 
       
    69 /* Fast modular reduction for p521 = 2^521 - 1.  a can be r. Uses
       
    70  * algorithm 2.31 from Hankerson, Menezes, Vanstone. Guide to
       
    71  * Elliptic Curve Cryptography. */
       
    72 mp_err
       
    73 ec_GFp_nistp521_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
       
    74 {
       
    75         mp_err res = MP_OKAY;
       
    76         int a_bits = mpl_significant_bits(a);
       
    77         int i;
       
    78 
       
    79         /* m1, m2 are statically-allocated mp_int of exactly the size we need */
       
    80         mp_int m1;
       
    81 
       
    82         mp_digit s1[ECP521_DIGITS] = { 0 };
       
    83 
       
    84         MP_SIGN(&m1) = MP_ZPOS;
       
    85         MP_ALLOC(&m1) = ECP521_DIGITS;
       
    86         MP_USED(&m1) = ECP521_DIGITS;
       
    87         MP_DIGITS(&m1) = s1;
       
    88 
       
    89         if (a_bits < 521) {
       
    90                 if (a==r) return MP_OKAY;
       
    91                 return mp_copy(a, r);
       
    92         }
       
    93         /* for polynomials larger than twice the field size or polynomials
       
    94          * not using all words, use regular reduction */
       
    95         if (a_bits > (521*2)) {
       
    96                 MP_CHECKOK(mp_mod(a, &meth->irr, r));
       
    97         } else {
       
    98 #define FIRST_DIGIT (ECP521_DIGITS-1)
       
    99                 for (i = FIRST_DIGIT; i < MP_USED(a)-1; i++) {
       
   100                         s1[i-FIRST_DIGIT] = (MP_DIGIT(a, i) >> 9)
       
   101                                 | (MP_DIGIT(a, 1+i) << (MP_DIGIT_BIT-9));
       
   102                 }
       
   103                 s1[i-FIRST_DIGIT] = MP_DIGIT(a, i) >> 9;
       
   104 
       
   105                 if ( a != r ) {
       
   106                         MP_CHECKOK(s_mp_pad(r,ECP521_DIGITS));
       
   107                         for (i = 0; i < ECP521_DIGITS; i++) {
       
   108                                 MP_DIGIT(r,i) = MP_DIGIT(a, i);
       
   109                         }
       
   110                 }
       
   111                 MP_USED(r) = ECP521_DIGITS;
       
   112                 MP_DIGIT(r,FIRST_DIGIT) &=  0x1FF;
       
   113 
       
   114                 MP_CHECKOK(s_mp_add(r, &m1));
       
   115                 if (MP_DIGIT(r, FIRST_DIGIT) & 0x200) {
       
   116                         MP_CHECKOK(s_mp_add_d(r,1));
       
   117                         MP_DIGIT(r,FIRST_DIGIT) &=  0x1FF;
       
   118                 }
       
   119                 s_mp_clamp(r);
       
   120         }
       
   121 
       
   122   CLEANUP:
       
   123         return res;
       
   124 }
       
   125 
       
   126 /* Compute the square of polynomial a, reduce modulo p521. Store the
       
   127  * result in r.  r could be a.  Uses optimized modular reduction for p521.
       
   128  */
       
   129 mp_err
       
   130 ec_GFp_nistp521_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
       
   131 {
       
   132         mp_err res = MP_OKAY;
       
   133 
       
   134         MP_CHECKOK(mp_sqr(a, r));
       
   135         MP_CHECKOK(ec_GFp_nistp521_mod(r, r, meth));
       
   136   CLEANUP:
       
   137         return res;
       
   138 }
       
   139 
       
   140 /* Compute the product of two polynomials a and b, reduce modulo p521.
       
   141  * Store the result in r.  r could be a or b; a could be b.  Uses
       
   142  * optimized modular reduction for p521. */
       
   143 mp_err
       
   144 ec_GFp_nistp521_mul(const mp_int *a, const mp_int *b, mp_int *r,
       
   145                                         const GFMethod *meth)
       
   146 {
       
   147         mp_err res = MP_OKAY;
       
   148 
       
   149         MP_CHECKOK(mp_mul(a, b, r));
       
   150         MP_CHECKOK(ec_GFp_nistp521_mod(r, r, meth));
       
   151   CLEANUP:
       
   152         return res;
       
   153 }
       
   154 
       
   155 /* Divides two field elements. If a is NULL, then returns the inverse of
       
   156  * b. */
       
   157 mp_err
       
   158 ec_GFp_nistp521_div(const mp_int *a, const mp_int *b, mp_int *r,
       
   159                    const GFMethod *meth)
       
   160 {
       
   161         mp_err res = MP_OKAY;
       
   162         mp_int t;
       
   163 
       
   164         /* If a is NULL, then return the inverse of b, otherwise return a/b. */
       
   165         if (a == NULL) {
       
   166                 return mp_invmod(b, &meth->irr, r);
       
   167         } else {
       
   168                 /* MPI doesn't support divmod, so we implement it using invmod and
       
   169                  * mulmod. */
       
   170                 MP_CHECKOK(mp_init(&t, FLAG(b)));
       
   171                 MP_CHECKOK(mp_invmod(b, &meth->irr, &t));
       
   172                 MP_CHECKOK(mp_mul(a, &t, r));
       
   173                 MP_CHECKOK(ec_GFp_nistp521_mod(r, r, meth));
       
   174           CLEANUP:
       
   175                 mp_clear(&t);
       
   176                 return res;
       
   177         }
       
   178 }
       
   179 
       
   180 /* Wire in fast field arithmetic and precomputation of base point for
       
   181  * named curves. */
       
   182 mp_err
       
   183 ec_group_set_gfp521(ECGroup *group, ECCurveName name)
       
   184 {
       
   185         if (name == ECCurve_NIST_P521) {
       
   186                 group->meth->field_mod = &ec_GFp_nistp521_mod;
       
   187                 group->meth->field_mul = &ec_GFp_nistp521_mul;
       
   188                 group->meth->field_sqr = &ec_GFp_nistp521_sqr;
       
   189                 group->meth->field_div = &ec_GFp_nistp521_div;
       
   190         }
       
   191         return MP_OKAY;
       
   192 }