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 binary polynomial 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  *   Sheueling Chang-Shantz <sheueling.chang@sun.com>,
  38  *   Stephen Fung <fungstep@hotmail.com>, and
  39  *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
  40  *
  41  * Alternatively, the contents of this file may be used under the terms of
  42  * either the GNU General Public License Version 2 or later (the "GPL"), or
  43  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  44  * in which case the provisions of the GPL or the LGPL are applicable instead
  45  * of those above. If you wish to allow use of your version of this file only
  46  * under the terms of either the GPL or the LGPL, and not to allow others to
  47  * use your version of this file under the terms of the MPL, indicate your
  48  * decision by deleting the provisions above and replace them with the notice
  49  * and other provisions required by the GPL or the LGPL. If you do not delete
  50  * the provisions above, a recipient may use your version of this file under
  51  * the terms of any one of the MPL, the GPL or the LGPL.
  52  *
  53  *********************************************************************** */
  54 /*
  55  * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
  56  * Use is subject to license terms.
  57  */
  58 
  59 #include "ec2.h"
  60 #include "mp_gf2m.h"
  61 #include "mp_gf2m-priv.h"
  62 #include "mpi.h"
  63 #include "mpi-priv.h"
  64 #ifndef _KERNEL
  65 #include <stdlib.h>
  66 #endif
  67 
  68 /* Fast reduction for polynomials over a 163-bit curve. Assumes reduction
  69  * polynomial with terms {163, 7, 6, 3, 0}. */
  70 mp_err
  71 ec_GF2m_163_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
  72 {
  73         mp_err res = MP_OKAY;
  74         mp_digit *u, z;
  75 
  76         if (a != r) {
  77                 MP_CHECKOK(mp_copy(a, r));
  78         }
  79 #ifdef ECL_SIXTY_FOUR_BIT
  80         if (MP_USED(r) < 6) {
  81                 MP_CHECKOK(s_mp_pad(r, 6));
  82         }
  83         u = MP_DIGITS(r);
  84         MP_USED(r) = 6;
  85 
  86         /* u[5] only has 6 significant bits */
  87         z = u[5];
  88         u[2] ^= (z << 36) ^ (z << 35) ^ (z << 32) ^ (z << 29);
  89         z = u[4];
  90         u[2] ^= (z >> 28) ^ (z >> 29) ^ (z >> 32) ^ (z >> 35);
  91         u[1] ^= (z << 36) ^ (z << 35) ^ (z << 32) ^ (z << 29);
  92         z = u[3];
  93         u[1] ^= (z >> 28) ^ (z >> 29) ^ (z >> 32) ^ (z >> 35);
  94         u[0] ^= (z << 36) ^ (z << 35) ^ (z << 32) ^ (z << 29);
  95         z = u[2] >> 35;                         /* z only has 29 significant bits */
  96         u[0] ^= (z << 7) ^ (z << 6) ^ (z << 3) ^ z;
  97         /* clear bits above 163 */
  98         u[5] = u[4] = u[3] = 0;
  99         u[2] ^= z << 35;
 100 #else
 101         if (MP_USED(r) < 11) {
 102                 MP_CHECKOK(s_mp_pad(r, 11));
 103         }
 104         u = MP_DIGITS(r);
 105         MP_USED(r) = 11;
 106 
 107         /* u[11] only has 6 significant bits */
 108         z = u[10];
 109         u[5] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3);
 110         u[4] ^= (z << 29);
 111         z = u[9];
 112         u[5] ^= (z >> 28) ^ (z >> 29);
 113         u[4] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3);
 114         u[3] ^= (z << 29);
 115         z = u[8];
 116         u[4] ^= (z >> 28) ^ (z >> 29);
 117         u[3] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3);
 118         u[2] ^= (z << 29);
 119         z = u[7];
 120         u[3] ^= (z >> 28) ^ (z >> 29);
 121         u[2] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3);
 122         u[1] ^= (z << 29);
 123         z = u[6];
 124         u[2] ^= (z >> 28) ^ (z >> 29);
 125         u[1] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3);
 126         u[0] ^= (z << 29);
 127         z = u[5] >> 3;                          /* z only has 29 significant bits */
 128         u[1] ^= (z >> 25) ^ (z >> 26);
 129         u[0] ^= (z << 7) ^ (z << 6) ^ (z << 3) ^ z;
 130         /* clear bits above 163 */
 131         u[11] = u[10] = u[9] = u[8] = u[7] = u[6] = 0;
 132         u[5] ^= z << 3;
 133 #endif
 134         s_mp_clamp(r);
 135 
 136   CLEANUP:
 137         return res;
 138 }
 139 
 140 /* Fast squaring for polynomials over a 163-bit curve. Assumes reduction
 141  * polynomial with terms {163, 7, 6, 3, 0}. */
 142 mp_err
 143 ec_GF2m_163_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
 144 {
 145         mp_err res = MP_OKAY;
 146         mp_digit *u, *v;
 147 
 148         v = MP_DIGITS(a);
 149 
 150 #ifdef ECL_SIXTY_FOUR_BIT
 151         if (MP_USED(a) < 3) {
 152                 return mp_bsqrmod(a, meth->irr_arr, r);
 153         }
 154         if (MP_USED(r) < 6) {
 155                 MP_CHECKOK(s_mp_pad(r, 6));
 156         }
 157         MP_USED(r) = 6;
 158 #else
 159         if (MP_USED(a) < 6) {
 160                 return mp_bsqrmod(a, meth->irr_arr, r);
 161         }
 162         if (MP_USED(r) < 12) {
 163                 MP_CHECKOK(s_mp_pad(r, 12));
 164         }
 165         MP_USED(r) = 12;
 166 #endif
 167         u = MP_DIGITS(r);
 168 
 169 #ifdef ECL_THIRTY_TWO_BIT
 170         u[11] = gf2m_SQR1(v[5]);
 171         u[10] = gf2m_SQR0(v[5]);
 172         u[9] = gf2m_SQR1(v[4]);
 173         u[8] = gf2m_SQR0(v[4]);
 174         u[7] = gf2m_SQR1(v[3]);
 175         u[6] = gf2m_SQR0(v[3]);
 176 #endif
 177         u[5] = gf2m_SQR1(v[2]);
 178         u[4] = gf2m_SQR0(v[2]);
 179         u[3] = gf2m_SQR1(v[1]);
 180         u[2] = gf2m_SQR0(v[1]);
 181         u[1] = gf2m_SQR1(v[0]);
 182         u[0] = gf2m_SQR0(v[0]);
 183         return ec_GF2m_163_mod(r, r, meth);
 184 
 185   CLEANUP:
 186         return res;
 187 }
 188 
 189 /* Fast multiplication for polynomials over a 163-bit curve. Assumes
 190  * reduction polynomial with terms {163, 7, 6, 3, 0}. */
 191 mp_err
 192 ec_GF2m_163_mul(const mp_int *a, const mp_int *b, mp_int *r,
 193                                 const GFMethod *meth)
 194 {
 195         mp_err res = MP_OKAY;
 196         mp_digit a2 = 0, a1 = 0, a0, b2 = 0, b1 = 0, b0;
 197 
 198 #ifdef ECL_THIRTY_TWO_BIT
 199         mp_digit a5 = 0, a4 = 0, a3 = 0, b5 = 0, b4 = 0, b3 = 0;
 200         mp_digit rm[6];
 201 #endif
 202 
 203         if (a == b) {
 204                 return ec_GF2m_163_sqr(a, r, meth);
 205         } else {
 206                 switch (MP_USED(a)) {
 207 #ifdef ECL_THIRTY_TWO_BIT
 208                 case 6:
 209                         a5 = MP_DIGIT(a, 5);
 210                 case 5:
 211                         a4 = MP_DIGIT(a, 4);
 212                 case 4:
 213                         a3 = MP_DIGIT(a, 3);
 214 #endif
 215                 case 3:
 216                         a2 = MP_DIGIT(a, 2);
 217                 case 2:
 218                         a1 = MP_DIGIT(a, 1);
 219                 default:
 220                         a0 = MP_DIGIT(a, 0);
 221                 }
 222                 switch (MP_USED(b)) {
 223 #ifdef ECL_THIRTY_TWO_BIT
 224                 case 6:
 225                         b5 = MP_DIGIT(b, 5);
 226                 case 5:
 227                         b4 = MP_DIGIT(b, 4);
 228                 case 4:
 229                         b3 = MP_DIGIT(b, 3);
 230 #endif
 231                 case 3:
 232                         b2 = MP_DIGIT(b, 2);
 233                 case 2:
 234                         b1 = MP_DIGIT(b, 1);
 235                 default:
 236                         b0 = MP_DIGIT(b, 0);
 237                 }
 238 #ifdef ECL_SIXTY_FOUR_BIT
 239                 MP_CHECKOK(s_mp_pad(r, 6));
 240                 s_bmul_3x3(MP_DIGITS(r), a2, a1, a0, b2, b1, b0);
 241                 MP_USED(r) = 6;
 242                 s_mp_clamp(r);
 243 #else
 244                 MP_CHECKOK(s_mp_pad(r, 12));
 245                 s_bmul_3x3(MP_DIGITS(r) + 6, a5, a4, a3, b5, b4, b3);
 246                 s_bmul_3x3(MP_DIGITS(r), a2, a1, a0, b2, b1, b0);
 247                 s_bmul_3x3(rm, a5 ^ a2, a4 ^ a1, a3 ^ a0, b5 ^ b2, b4 ^ b1,
 248                                    b3 ^ b0);
 249                 rm[5] ^= MP_DIGIT(r, 5) ^ MP_DIGIT(r, 11);
 250                 rm[4] ^= MP_DIGIT(r, 4) ^ MP_DIGIT(r, 10);
 251                 rm[3] ^= MP_DIGIT(r, 3) ^ MP_DIGIT(r, 9);
 252                 rm[2] ^= MP_DIGIT(r, 2) ^ MP_DIGIT(r, 8);
 253                 rm[1] ^= MP_DIGIT(r, 1) ^ MP_DIGIT(r, 7);
 254                 rm[0] ^= MP_DIGIT(r, 0) ^ MP_DIGIT(r, 6);
 255                 MP_DIGIT(r, 8) ^= rm[5];
 256                 MP_DIGIT(r, 7) ^= rm[4];
 257                 MP_DIGIT(r, 6) ^= rm[3];
 258                 MP_DIGIT(r, 5) ^= rm[2];
 259                 MP_DIGIT(r, 4) ^= rm[1];
 260                 MP_DIGIT(r, 3) ^= rm[0];
 261                 MP_USED(r) = 12;
 262                 s_mp_clamp(r);
 263 #endif
 264                 return ec_GF2m_163_mod(r, r, meth);
 265         }
 266 
 267   CLEANUP:
 268         return res;
 269 }
 270 
 271 /* Wire in fast field arithmetic for 163-bit curves. */
 272 mp_err
 273 ec_group_set_gf2m163(ECGroup *group, ECCurveName name)
 274 {
 275         group->meth->field_mod = &ec_GF2m_163_mod;
 276         group->meth->field_mul = &ec_GF2m_163_mul;
 277         group->meth->field_sqr = &ec_GF2m_163_sqr;
 278         return MP_OKAY;
 279 }