security/nss/lib/freebl/ecl/ecp_224.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 #include "ecp.h"
michael@0 6 #include "mpi.h"
michael@0 7 #include "mplogic.h"
michael@0 8 #include "mpi-priv.h"
michael@0 9
michael@0 10 #define ECP224_DIGITS ECL_CURVE_DIGITS(224)
michael@0 11
michael@0 12 /* Fast modular reduction for p224 = 2^224 - 2^96 + 1. a can be r. Uses
michael@0 13 * algorithm 7 from Brown, Hankerson, Lopez, Menezes. Software
michael@0 14 * Implementation of the NIST Elliptic Curves over Prime Fields. */
michael@0 15 static mp_err
michael@0 16 ec_GFp_nistp224_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
michael@0 17 {
michael@0 18 mp_err res = MP_OKAY;
michael@0 19 mp_size a_used = MP_USED(a);
michael@0 20
michael@0 21 int r3b;
michael@0 22 mp_digit carry;
michael@0 23 #ifdef ECL_THIRTY_TWO_BIT
michael@0 24 mp_digit a6a = 0, a6b = 0,
michael@0 25 a5a = 0, a5b = 0, a4a = 0, a4b = 0, a3a = 0, a3b = 0;
michael@0 26 mp_digit r0a, r0b, r1a, r1b, r2a, r2b, r3a;
michael@0 27 #else
michael@0 28 mp_digit a6 = 0, a5 = 0, a4 = 0, a3b = 0, a5a = 0;
michael@0 29 mp_digit a6b = 0, a6a_a5b = 0, a5b = 0, a5a_a4b = 0, a4a_a3b = 0;
michael@0 30 mp_digit r0, r1, r2, r3;
michael@0 31 #endif
michael@0 32
michael@0 33 /* reduction not needed if a is not larger than field size */
michael@0 34 if (a_used < ECP224_DIGITS) {
michael@0 35 if (a == r) return MP_OKAY;
michael@0 36 return mp_copy(a, r);
michael@0 37 }
michael@0 38 /* for polynomials larger than twice the field size, use regular
michael@0 39 * reduction */
michael@0 40 if (a_used > ECL_CURVE_DIGITS(224*2)) {
michael@0 41 MP_CHECKOK(mp_mod(a, &meth->irr, r));
michael@0 42 } else {
michael@0 43 #ifdef ECL_THIRTY_TWO_BIT
michael@0 44 /* copy out upper words of a */
michael@0 45 switch (a_used) {
michael@0 46 case 14:
michael@0 47 a6b = MP_DIGIT(a, 13);
michael@0 48 case 13:
michael@0 49 a6a = MP_DIGIT(a, 12);
michael@0 50 case 12:
michael@0 51 a5b = MP_DIGIT(a, 11);
michael@0 52 case 11:
michael@0 53 a5a = MP_DIGIT(a, 10);
michael@0 54 case 10:
michael@0 55 a4b = MP_DIGIT(a, 9);
michael@0 56 case 9:
michael@0 57 a4a = MP_DIGIT(a, 8);
michael@0 58 case 8:
michael@0 59 a3b = MP_DIGIT(a, 7);
michael@0 60 }
michael@0 61 r3a = MP_DIGIT(a, 6);
michael@0 62 r2b= MP_DIGIT(a, 5);
michael@0 63 r2a= MP_DIGIT(a, 4);
michael@0 64 r1b = MP_DIGIT(a, 3);
michael@0 65 r1a = MP_DIGIT(a, 2);
michael@0 66 r0b = MP_DIGIT(a, 1);
michael@0 67 r0a = MP_DIGIT(a, 0);
michael@0 68
michael@0 69
michael@0 70 /* implement r = (a3a,a2,a1,a0)
michael@0 71 +(a5a, a4,a3b, 0)
michael@0 72 +( 0, a6,a5b, 0)
michael@0 73 -( 0 0, 0|a6b, a6a|a5b )
michael@0 74 -( a6b, a6a|a5b, a5a|a4b, a4a|a3b ) */
michael@0 75 MP_ADD_CARRY (r1b, a3b, r1b, 0, carry);
michael@0 76 MP_ADD_CARRY (r2a, a4a, r2a, carry, carry);
michael@0 77 MP_ADD_CARRY (r2b, a4b, r2b, carry, carry);
michael@0 78 MP_ADD_CARRY (r3a, a5a, r3a, carry, carry);
michael@0 79 r3b = carry;
michael@0 80 MP_ADD_CARRY (r1b, a5b, r1b, 0, carry);
michael@0 81 MP_ADD_CARRY (r2a, a6a, r2a, carry, carry);
michael@0 82 MP_ADD_CARRY (r2b, a6b, r2b, carry, carry);
michael@0 83 MP_ADD_CARRY (r3a, 0, r3a, carry, carry);
michael@0 84 r3b += carry;
michael@0 85 MP_SUB_BORROW(r0a, a3b, r0a, 0, carry);
michael@0 86 MP_SUB_BORROW(r0b, a4a, r0b, carry, carry);
michael@0 87 MP_SUB_BORROW(r1a, a4b, r1a, carry, carry);
michael@0 88 MP_SUB_BORROW(r1b, a5a, r1b, carry, carry);
michael@0 89 MP_SUB_BORROW(r2a, a5b, r2a, carry, carry);
michael@0 90 MP_SUB_BORROW(r2b, a6a, r2b, carry, carry);
michael@0 91 MP_SUB_BORROW(r3a, a6b, r3a, carry, carry);
michael@0 92 r3b -= carry;
michael@0 93 MP_SUB_BORROW(r0a, a5b, r0a, 0, carry);
michael@0 94 MP_SUB_BORROW(r0b, a6a, r0b, carry, carry);
michael@0 95 MP_SUB_BORROW(r1a, a6b, r1a, carry, carry);
michael@0 96 if (carry) {
michael@0 97 MP_SUB_BORROW(r1b, 0, r1b, carry, carry);
michael@0 98 MP_SUB_BORROW(r2a, 0, r2a, carry, carry);
michael@0 99 MP_SUB_BORROW(r2b, 0, r2b, carry, carry);
michael@0 100 MP_SUB_BORROW(r3a, 0, r3a, carry, carry);
michael@0 101 r3b -= carry;
michael@0 102 }
michael@0 103
michael@0 104 while (r3b > 0) {
michael@0 105 int tmp;
michael@0 106 MP_ADD_CARRY(r1b, r3b, r1b, 0, carry);
michael@0 107 if (carry) {
michael@0 108 MP_ADD_CARRY(r2a, 0, r2a, carry, carry);
michael@0 109 MP_ADD_CARRY(r2b, 0, r2b, carry, carry);
michael@0 110 MP_ADD_CARRY(r3a, 0, r3a, carry, carry);
michael@0 111 }
michael@0 112 tmp = carry;
michael@0 113 MP_SUB_BORROW(r0a, r3b, r0a, 0, carry);
michael@0 114 if (carry) {
michael@0 115 MP_SUB_BORROW(r0b, 0, r0b, carry, carry);
michael@0 116 MP_SUB_BORROW(r1a, 0, r1a, carry, carry);
michael@0 117 MP_SUB_BORROW(r1b, 0, r1b, carry, carry);
michael@0 118 MP_SUB_BORROW(r2a, 0, r2a, carry, carry);
michael@0 119 MP_SUB_BORROW(r2b, 0, r2b, carry, carry);
michael@0 120 MP_SUB_BORROW(r3a, 0, r3a, carry, carry);
michael@0 121 tmp -= carry;
michael@0 122 }
michael@0 123 r3b = tmp;
michael@0 124 }
michael@0 125
michael@0 126 while (r3b < 0) {
michael@0 127 mp_digit maxInt = MP_DIGIT_MAX;
michael@0 128 MP_ADD_CARRY (r0a, 1, r0a, 0, carry);
michael@0 129 MP_ADD_CARRY (r0b, 0, r0b, carry, carry);
michael@0 130 MP_ADD_CARRY (r1a, 0, r1a, carry, carry);
michael@0 131 MP_ADD_CARRY (r1b, maxInt, r1b, carry, carry);
michael@0 132 MP_ADD_CARRY (r2a, maxInt, r2a, carry, carry);
michael@0 133 MP_ADD_CARRY (r2b, maxInt, r2b, carry, carry);
michael@0 134 MP_ADD_CARRY (r3a, maxInt, r3a, carry, carry);
michael@0 135 r3b += carry;
michael@0 136 }
michael@0 137 /* check for final reduction */
michael@0 138 /* now the only way we are over is if the top 4 words are all ones */
michael@0 139 if ((r3a == MP_DIGIT_MAX) && (r2b == MP_DIGIT_MAX)
michael@0 140 && (r2a == MP_DIGIT_MAX) && (r1b == MP_DIGIT_MAX) &&
michael@0 141 ((r1a != 0) || (r0b != 0) || (r0a != 0)) ) {
michael@0 142 /* one last subraction */
michael@0 143 MP_SUB_BORROW(r0a, 1, r0a, 0, carry);
michael@0 144 MP_SUB_BORROW(r0b, 0, r0b, carry, carry);
michael@0 145 MP_SUB_BORROW(r1a, 0, r1a, carry, carry);
michael@0 146 r1b = r2a = r2b = r3a = 0;
michael@0 147 }
michael@0 148
michael@0 149
michael@0 150 if (a != r) {
michael@0 151 MP_CHECKOK(s_mp_pad(r, 7));
michael@0 152 }
michael@0 153 /* set the lower words of r */
michael@0 154 MP_SIGN(r) = MP_ZPOS;
michael@0 155 MP_USED(r) = 7;
michael@0 156 MP_DIGIT(r, 6) = r3a;
michael@0 157 MP_DIGIT(r, 5) = r2b;
michael@0 158 MP_DIGIT(r, 4) = r2a;
michael@0 159 MP_DIGIT(r, 3) = r1b;
michael@0 160 MP_DIGIT(r, 2) = r1a;
michael@0 161 MP_DIGIT(r, 1) = r0b;
michael@0 162 MP_DIGIT(r, 0) = r0a;
michael@0 163 #else
michael@0 164 /* copy out upper words of a */
michael@0 165 switch (a_used) {
michael@0 166 case 7:
michael@0 167 a6 = MP_DIGIT(a, 6);
michael@0 168 a6b = a6 >> 32;
michael@0 169 a6a_a5b = a6 << 32;
michael@0 170 case 6:
michael@0 171 a5 = MP_DIGIT(a, 5);
michael@0 172 a5b = a5 >> 32;
michael@0 173 a6a_a5b |= a5b;
michael@0 174 a5b = a5b << 32;
michael@0 175 a5a_a4b = a5 << 32;
michael@0 176 a5a = a5 & 0xffffffff;
michael@0 177 case 5:
michael@0 178 a4 = MP_DIGIT(a, 4);
michael@0 179 a5a_a4b |= a4 >> 32;
michael@0 180 a4a_a3b = a4 << 32;
michael@0 181 case 4:
michael@0 182 a3b = MP_DIGIT(a, 3) >> 32;
michael@0 183 a4a_a3b |= a3b;
michael@0 184 a3b = a3b << 32;
michael@0 185 }
michael@0 186
michael@0 187 r3 = MP_DIGIT(a, 3) & 0xffffffff;
michael@0 188 r2 = MP_DIGIT(a, 2);
michael@0 189 r1 = MP_DIGIT(a, 1);
michael@0 190 r0 = MP_DIGIT(a, 0);
michael@0 191
michael@0 192 /* implement r = (a3a,a2,a1,a0)
michael@0 193 +(a5a, a4,a3b, 0)
michael@0 194 +( 0, a6,a5b, 0)
michael@0 195 -( 0 0, 0|a6b, a6a|a5b )
michael@0 196 -( a6b, a6a|a5b, a5a|a4b, a4a|a3b ) */
michael@0 197 MP_ADD_CARRY (r1, a3b, r1, 0, carry);
michael@0 198 MP_ADD_CARRY (r2, a4 , r2, carry, carry);
michael@0 199 MP_ADD_CARRY (r3, a5a, r3, carry, carry);
michael@0 200 MP_ADD_CARRY (r1, a5b, r1, 0, carry);
michael@0 201 MP_ADD_CARRY (r2, a6 , r2, carry, carry);
michael@0 202 MP_ADD_CARRY (r3, 0, r3, carry, carry);
michael@0 203
michael@0 204 MP_SUB_BORROW(r0, a4a_a3b, r0, 0, carry);
michael@0 205 MP_SUB_BORROW(r1, a5a_a4b, r1, carry, carry);
michael@0 206 MP_SUB_BORROW(r2, a6a_a5b, r2, carry, carry);
michael@0 207 MP_SUB_BORROW(r3, a6b , r3, carry, carry);
michael@0 208 MP_SUB_BORROW(r0, a6a_a5b, r0, 0, carry);
michael@0 209 MP_SUB_BORROW(r1, a6b , r1, carry, carry);
michael@0 210 if (carry) {
michael@0 211 MP_SUB_BORROW(r2, 0, r2, carry, carry);
michael@0 212 MP_SUB_BORROW(r3, 0, r3, carry, carry);
michael@0 213 }
michael@0 214
michael@0 215
michael@0 216 /* if the value is negative, r3 has a 2's complement
michael@0 217 * high value */
michael@0 218 r3b = (int)(r3 >>32);
michael@0 219 while (r3b > 0) {
michael@0 220 r3 &= 0xffffffff;
michael@0 221 MP_ADD_CARRY(r1,((mp_digit)r3b) << 32, r1, 0, carry);
michael@0 222 if (carry) {
michael@0 223 MP_ADD_CARRY(r2, 0, r2, carry, carry);
michael@0 224 MP_ADD_CARRY(r3, 0, r3, carry, carry);
michael@0 225 }
michael@0 226 MP_SUB_BORROW(r0, r3b, r0, 0, carry);
michael@0 227 if (carry) {
michael@0 228 MP_SUB_BORROW(r1, 0, r1, carry, carry);
michael@0 229 MP_SUB_BORROW(r2, 0, r2, carry, carry);
michael@0 230 MP_SUB_BORROW(r3, 0, r3, carry, carry);
michael@0 231 }
michael@0 232 r3b = (int)(r3 >>32);
michael@0 233 }
michael@0 234
michael@0 235 while (r3b < 0) {
michael@0 236 MP_ADD_CARRY (r0, 1, r0, 0, carry);
michael@0 237 MP_ADD_CARRY (r1, MP_DIGIT_MAX <<32, r1, carry, carry);
michael@0 238 MP_ADD_CARRY (r2, MP_DIGIT_MAX, r2, carry, carry);
michael@0 239 MP_ADD_CARRY (r3, MP_DIGIT_MAX >> 32, r3, carry, carry);
michael@0 240 r3b = (int)(r3 >>32);
michael@0 241 }
michael@0 242 /* check for final reduction */
michael@0 243 /* now the only way we are over is if the top 4 words are
michael@0 244 * all ones. Subtract the curve. (curve is 2^224 - 2^96 +1)
michael@0 245 */
michael@0 246 if ((r3 == (MP_DIGIT_MAX >> 32)) && (r2 == MP_DIGIT_MAX)
michael@0 247 && ((r1 & MP_DIGIT_MAX << 32)== MP_DIGIT_MAX << 32) &&
michael@0 248 ((r1 != MP_DIGIT_MAX << 32 ) || (r0 != 0)) ) {
michael@0 249 /* one last subraction */
michael@0 250 MP_SUB_BORROW(r0, 1, r0, 0, carry);
michael@0 251 MP_SUB_BORROW(r1, MP_DIGIT_MAX << 32, r1, carry, carry);
michael@0 252 r2 = r3 = 0;
michael@0 253 }
michael@0 254
michael@0 255
michael@0 256 if (a != r) {
michael@0 257 MP_CHECKOK(s_mp_pad(r, 4));
michael@0 258 }
michael@0 259 /* set the lower words of r */
michael@0 260 MP_SIGN(r) = MP_ZPOS;
michael@0 261 MP_USED(r) = 4;
michael@0 262 MP_DIGIT(r, 3) = r3;
michael@0 263 MP_DIGIT(r, 2) = r2;
michael@0 264 MP_DIGIT(r, 1) = r1;
michael@0 265 MP_DIGIT(r, 0) = r0;
michael@0 266 #endif
michael@0 267 }
michael@0 268 s_mp_clamp(r);
michael@0 269
michael@0 270 CLEANUP:
michael@0 271 return res;
michael@0 272 }
michael@0 273
michael@0 274 /* Compute the square of polynomial a, reduce modulo p224. Store the
michael@0 275 * result in r. r could be a. Uses optimized modular reduction for p224.
michael@0 276 */
michael@0 277 static mp_err
michael@0 278 ec_GFp_nistp224_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
michael@0 279 {
michael@0 280 mp_err res = MP_OKAY;
michael@0 281
michael@0 282 MP_CHECKOK(mp_sqr(a, r));
michael@0 283 MP_CHECKOK(ec_GFp_nistp224_mod(r, r, meth));
michael@0 284 CLEANUP:
michael@0 285 return res;
michael@0 286 }
michael@0 287
michael@0 288 /* Compute the product of two polynomials a and b, reduce modulo p224.
michael@0 289 * Store the result in r. r could be a or b; a could be b. Uses
michael@0 290 * optimized modular reduction for p224. */
michael@0 291 static mp_err
michael@0 292 ec_GFp_nistp224_mul(const mp_int *a, const mp_int *b, mp_int *r,
michael@0 293 const GFMethod *meth)
michael@0 294 {
michael@0 295 mp_err res = MP_OKAY;
michael@0 296
michael@0 297 MP_CHECKOK(mp_mul(a, b, r));
michael@0 298 MP_CHECKOK(ec_GFp_nistp224_mod(r, r, meth));
michael@0 299 CLEANUP:
michael@0 300 return res;
michael@0 301 }
michael@0 302
michael@0 303 /* Divides two field elements. If a is NULL, then returns the inverse of
michael@0 304 * b. */
michael@0 305 static mp_err
michael@0 306 ec_GFp_nistp224_div(const mp_int *a, const mp_int *b, mp_int *r,
michael@0 307 const GFMethod *meth)
michael@0 308 {
michael@0 309 mp_err res = MP_OKAY;
michael@0 310 mp_int t;
michael@0 311
michael@0 312 /* If a is NULL, then return the inverse of b, otherwise return a/b. */
michael@0 313 if (a == NULL) {
michael@0 314 return mp_invmod(b, &meth->irr, r);
michael@0 315 } else {
michael@0 316 /* MPI doesn't support divmod, so we implement it using invmod and
michael@0 317 * mulmod. */
michael@0 318 MP_CHECKOK(mp_init(&t));
michael@0 319 MP_CHECKOK(mp_invmod(b, &meth->irr, &t));
michael@0 320 MP_CHECKOK(mp_mul(a, &t, r));
michael@0 321 MP_CHECKOK(ec_GFp_nistp224_mod(r, r, meth));
michael@0 322 CLEANUP:
michael@0 323 mp_clear(&t);
michael@0 324 return res;
michael@0 325 }
michael@0 326 }
michael@0 327
michael@0 328 /* Wire in fast field arithmetic and precomputation of base point for
michael@0 329 * named curves. */
michael@0 330 mp_err
michael@0 331 ec_group_set_gfp224(ECGroup *group, ECCurveName name)
michael@0 332 {
michael@0 333 if (name == ECCurve_NIST_P224) {
michael@0 334 group->meth->field_mod = &ec_GFp_nistp224_mod;
michael@0 335 group->meth->field_mul = &ec_GFp_nistp224_mul;
michael@0 336 group->meth->field_sqr = &ec_GFp_nistp224_sqr;
michael@0 337 group->meth->field_div = &ec_GFp_nistp224_div;
michael@0 338 }
michael@0 339 return MP_OKAY;
michael@0 340 }

mercurial