annotate src/share/native/sun/security/ec/impl/ecp_192.c @ 4272:b49a0af85821

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