2
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
* The contents of this file are subject to the Mozilla Public License Version
5
* 1.1 (the "License"); you may not use this file except in compliance with
6
* the License. You may obtain a copy of the License at
7
* http://www.mozilla.org/MPL/
9
* Software distributed under the License is distributed on an "AS IS" basis,
10
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
* for the specific language governing rights and limitations under the
14
* The Original Code is the elliptic curve math library for prime
17
* The Initial Developer of the Original Code is Sun Microsystems, Inc.
18
* Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
19
* Sun Microsystems, Inc. All Rights Reserved.
22
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
24
* Alternatively, the contents of this file may be used under the terms of
25
* either the GNU General Public License Version 2 or later (the "GPL"), or
26
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27
* in which case the provisions of the GPL or the LGPL are applicable instead
28
* of those above. If you wish to allow use of your version of this file only
29
* under the terms of either the GPL or the LGPL, and not to allow others to
30
* use your version of this file under the terms of the MPL, indicate your
31
* decision by deleting the provisions above and replace them with the notice
32
* and other provisions required by the GPL or the LGPL. If you do not delete
33
* the provisions above, a recipient may use your version of this file under
34
* the terms of any one of the MPL, the GPL or the LGPL.
44
/* Fast modular reduction for p224 = 2^224 - 2^96 + 1. a can be r. Uses
45
* algorithm 7 from Brown, Hankerson, Lopez, Menezes. Software
46
* Implementation of the NIST Elliptic Curves over Prime Fields. */
48
ec_GFp_nistp224_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
51
mp_size a_used = MP_USED(a);
53
/* s is a statically-allocated mp_int of exactly the size we need */
56
#ifdef ECL_THIRTY_TWO_BIT
58
mp_digit a13 = 0, a12 = 0, a11 = 0, a10, a9 = 0, a8, a7;
60
MP_SIGN(&s) = MP_ZPOS;
66
mp_digit a6 = 0, a5 = 0, a4 = 0, a3 = 0;
68
MP_SIGN(&s) = MP_ZPOS;
74
/* reduction not needed if a is not larger than field size */
75
#ifdef ECL_THIRTY_TWO_BIT
82
#ifdef ECL_THIRTY_TWO_BIT
83
/* for polynomials larger than twice the field size, use regular
86
MP_CHECKOK(mp_mod(a, &meth->irr, r));
88
/* copy out upper words of a */
91
a13 = MP_DIGIT(a, 13);
93
a12 = MP_DIGIT(a, 12);
95
a11 = MP_DIGIT(a, 11);
97
a10 = MP_DIGIT(a, 10);
105
/* set the lower words of r */
107
MP_CHECKOK(s_mp_pad(r, 8));
108
MP_DIGIT(r, 6) = MP_DIGIT(a, 6);
109
MP_DIGIT(r, 5) = MP_DIGIT(a, 5);
110
MP_DIGIT(r, 4) = MP_DIGIT(a, 4);
111
MP_DIGIT(r, 3) = MP_DIGIT(a, 3);
112
MP_DIGIT(r, 2) = MP_DIGIT(a, 2);
113
MP_DIGIT(r, 1) = MP_DIGIT(a, 1);
114
MP_DIGIT(r, 0) = MP_DIGIT(a, 0);
129
sa[2] = sa[1] = sa[0] = 0;
130
MP_USED(&s) = a_used - 4;
133
MP_CHECKOK(mp_add(r, &s, r));
142
sa[2] = sa[1] = sa[0] = 0;
143
MP_USED(&s) = a_used - 8;
144
MP_CHECKOK(mp_add(r, &s, r));
161
MP_USED(&s) = a_used - 7;
162
MP_CHECKOK(mp_sub(r, &s, r));
171
MP_USED(&s) = a_used - 11;
172
MP_CHECKOK(mp_sub(r, &s, r));
174
/* there might be 1 or 2 bits left to reduce; use regular
175
* reduction for this */
176
MP_CHECKOK(mp_mod(r, &meth->irr, r));
179
/* for polynomials larger than twice the field size, use regular
182
MP_CHECKOK(mp_mod(a, &meth->irr, r));
184
/* copy out upper words of a */
193
a3 = MP_DIGIT(a, 3) >> 32;
195
/* set the lower words of r */
197
MP_CHECKOK(s_mp_pad(r, 5));
198
MP_DIGIT(r, 3) = MP_DIGIT(a, 3) & 0xFFFFFFFF;
199
MP_DIGIT(r, 2) = MP_DIGIT(a, 2);
200
MP_DIGIT(r, 1) = MP_DIGIT(a, 1);
201
MP_DIGIT(r, 0) = MP_DIGIT(a, 0);
203
MP_DIGIT(r, 3) &= 0xFFFFFFFF;
209
sa[3] = a5 & 0xFFFFFFFF;
215
MP_USED(&s) = a_used - 2;
216
if (MP_USED(&s) == 5)
218
MP_CHECKOK(mp_add(r, &s, r));
224
sa[1] = (a5 >> 32) << 32;
226
MP_USED(&s) = a_used - 4;
227
MP_CHECKOK(mp_add(r, &s, r));
229
sa[2] = sa[1] = sa[0] = 0;
242
MP_USED(&s) = a_used - 3;
243
MP_CHECKOK(mp_sub(r, &s, r));
252
MP_USED(&s) = a_used - 5;
253
MP_CHECKOK(mp_sub(r, &s, r));
255
/* there might be 1 or 2 bits left to reduce; use regular
256
* reduction for this */
257
MP_CHECKOK(mp_mod(r, &meth->irr, r));
265
/* Compute the square of polynomial a, reduce modulo p224. Store the
266
* result in r. r could be a. Uses optimized modular reduction for p224.
269
ec_GFp_nistp224_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
271
mp_err res = MP_OKAY;
273
MP_CHECKOK(mp_sqr(a, r));
274
MP_CHECKOK(ec_GFp_nistp224_mod(r, r, meth));
279
/* Compute the product of two polynomials a and b, reduce modulo p224.
280
* Store the result in r. r could be a or b; a could be b. Uses
281
* optimized modular reduction for p224. */
283
ec_GFp_nistp224_mul(const mp_int *a, const mp_int *b, mp_int *r,
284
const GFMethod *meth)
286
mp_err res = MP_OKAY;
288
MP_CHECKOK(mp_mul(a, b, r));
289
MP_CHECKOK(ec_GFp_nistp224_mod(r, r, meth));
294
/* Wire in fast field arithmetic and precomputation of base point for
297
ec_group_set_gfp224(ECGroup *group, ECCurveName name)
299
if (name == ECCurve_NIST_P224) {
300
group->meth->field_mod = &ec_GFp_nistp224_mod;
301
group->meth->field_mul = &ec_GFp_nistp224_mul;
302
group->meth->field_sqr = &ec_GFp_nistp224_sqr;