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

mercurial