annotate src/share/native/sun/security/ec/impl/ecp_192.c @ 1674:845fefff00a4

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