2 * ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is the elliptic curve math library for prime field curves.
17 * The Initial Developer of the Original Code is
18 * Sun Microsystems, Inc.
19 * Portions created by the Initial Developer are Copyright (C) 2003
20 * the Initial Developer. All Rights Reserved.
23 * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
40 * Use is subject to license terms.
42 * Sun elects to use this software under the MPL license.
45 #pragma ident "%Z%%M% %I% %E% SMI"
55 #define ECP224_DIGITS ECL_CURVE_DIGITS(224)
57 /* Fast modular reduction for p224 = 2^224 - 2^96 + 1. a can be r. Uses
58 * algorithm 7 from Brown, Hankerson, Lopez, Menezes. Software
59 * Implementation of the NIST Elliptic Curves over Prime Fields. */
61 ec_GFp_nistp224_mod(const mp_int
*a
, mp_int
*r
, const GFMethod
*meth
)
64 mp_size a_used
= MP_USED(a
);
68 #ifdef ECL_THIRTY_TWO_BIT
69 mp_digit a6a
= 0, a6b
= 0,
70 a5a
= 0, a5b
= 0, a4a
= 0, a4b
= 0, a3a
= 0, a3b
= 0;
71 mp_digit r0a
, r0b
, r1a
, r1b
, r2a
, r2b
, r3a
;
73 mp_digit a6
= 0, a5
= 0, a4
= 0, a3b
= 0, a5a
= 0;
74 mp_digit a6b
= 0, a6a_a5b
= 0, a5b
= 0, a5a_a4b
= 0, a4a_a3b
= 0;
75 mp_digit r0
, r1
, r2
, r3
;
78 /* reduction not needed if a is not larger than field size */
79 if (a_used
< ECP224_DIGITS
) {
80 if (a
== r
) return MP_OKAY
;
83 /* for polynomials larger than twice the field size, use regular
85 if (a_used
> ECL_CURVE_DIGITS(224*2)) {
86 MP_CHECKOK(mp_mod(a
, &meth
->irr
, r
));
88 #ifdef ECL_THIRTY_TWO_BIT
89 /* copy out upper words of a */
92 a6b
= MP_DIGIT(a
, 13);
94 a6a
= MP_DIGIT(a
, 12);
96 a5b
= MP_DIGIT(a
, 11);
98 a5a
= MP_DIGIT(a
, 10);
100 a4b
= MP_DIGIT(a
, 9);
102 a4a
= MP_DIGIT(a
, 8);
104 a3b
= MP_DIGIT(a
, 7);
106 r3a
= MP_DIGIT(a
, 6);
109 r1b
= MP_DIGIT(a
, 3);
110 r1a
= MP_DIGIT(a
, 2);
111 r0b
= MP_DIGIT(a
, 1);
112 r0a
= MP_DIGIT(a
, 0);
115 /* implement r = (a3a,a2,a1,a0)
118 -( 0 0, 0|a6b, a6a|a5b )
119 -( a6b, a6a|a5b, a5a|a4b, a4a|a3b ) */
120 MP_ADD_CARRY (r1b
, a3b
, r1b
, 0, carry
);
121 MP_ADD_CARRY (r2a
, a4a
, r2a
, carry
, carry
);
122 MP_ADD_CARRY (r2b
, a4b
, r2b
, carry
, carry
);
123 MP_ADD_CARRY (r3a
, a5a
, r3a
, carry
, carry
);
125 MP_ADD_CARRY (r1b
, a5b
, r1b
, 0, carry
);
126 MP_ADD_CARRY (r2a
, a6a
, r2a
, carry
, carry
);
127 MP_ADD_CARRY (r2b
, a6b
, r2b
, carry
, carry
);
128 MP_ADD_CARRY (r3a
, 0, r3a
, carry
, carry
);
130 MP_SUB_BORROW(r0a
, a3b
, r0a
, 0, carry
);
131 MP_SUB_BORROW(r0b
, a4a
, r0b
, carry
, carry
);
132 MP_SUB_BORROW(r1a
, a4b
, r1a
, carry
, carry
);
133 MP_SUB_BORROW(r1b
, a5a
, r1b
, carry
, carry
);
134 MP_SUB_BORROW(r2a
, a5b
, r2a
, carry
, carry
);
135 MP_SUB_BORROW(r2b
, a6a
, r2b
, carry
, carry
);
136 MP_SUB_BORROW(r3a
, a6b
, r3a
, carry
, carry
);
138 MP_SUB_BORROW(r0a
, a5b
, r0a
, 0, carry
);
139 MP_SUB_BORROW(r0b
, a6a
, r0b
, carry
, carry
);
140 MP_SUB_BORROW(r1a
, a6b
, r1a
, carry
, carry
);
142 MP_SUB_BORROW(r1b
, 0, r1b
, carry
, carry
);
143 MP_SUB_BORROW(r2a
, 0, r2a
, carry
, carry
);
144 MP_SUB_BORROW(r2b
, 0, r2b
, carry
, carry
);
145 MP_SUB_BORROW(r3a
, 0, r3a
, carry
, carry
);
151 MP_ADD_CARRY(r1b
, r3b
, r1b
, 0, carry
);
153 MP_ADD_CARRY(r2a
, 0, r2a
, carry
, carry
);
154 MP_ADD_CARRY(r2b
, 0, r2b
, carry
, carry
);
155 MP_ADD_CARRY(r3a
, 0, r3a
, carry
, carry
);
158 MP_SUB_BORROW(r0a
, r3b
, r0a
, 0, carry
);
160 MP_SUB_BORROW(r0b
, 0, r0b
, carry
, carry
);
161 MP_SUB_BORROW(r1a
, 0, r1a
, carry
, carry
);
162 MP_SUB_BORROW(r1b
, 0, r1b
, carry
, carry
);
163 MP_SUB_BORROW(r2a
, 0, r2a
, carry
, carry
);
164 MP_SUB_BORROW(r2b
, 0, r2b
, carry
, carry
);
165 MP_SUB_BORROW(r3a
, 0, r3a
, carry
, carry
);
172 mp_digit maxInt
= MP_DIGIT_MAX
;
173 MP_ADD_CARRY (r0a
, 1, r0a
, 0, carry
);
174 MP_ADD_CARRY (r0b
, 0, r0b
, carry
, carry
);
175 MP_ADD_CARRY (r1a
, 0, r1a
, carry
, carry
);
176 MP_ADD_CARRY (r1b
, maxInt
, r1b
, carry
, carry
);
177 MP_ADD_CARRY (r2a
, maxInt
, r2a
, carry
, carry
);
178 MP_ADD_CARRY (r2b
, maxInt
, r2b
, carry
, carry
);
179 MP_ADD_CARRY (r3a
, maxInt
, r3a
, carry
, carry
);
182 /* check for final reduction */
183 /* now the only way we are over is if the top 4 words are all ones */
184 if ((r3a
== MP_DIGIT_MAX
) && (r2b
== MP_DIGIT_MAX
)
185 && (r2a
== MP_DIGIT_MAX
) && (r1b
== MP_DIGIT_MAX
) &&
186 ((r1a
!= 0) || (r0b
!= 0) || (r0a
!= 0)) ) {
187 /* one last subraction */
188 MP_SUB_BORROW(r0a
, 1, r0a
, 0, carry
);
189 MP_SUB_BORROW(r0b
, 0, r0b
, carry
, carry
);
190 MP_SUB_BORROW(r1a
, 0, r1a
, carry
, carry
);
191 r1b
= r2a
= r2b
= r3a
= 0;
196 MP_CHECKOK(s_mp_pad(r
, 7));
198 /* set the lower words of r */
199 MP_SIGN(r
) = MP_ZPOS
;
201 MP_DIGIT(r
, 6) = r3a
;
202 MP_DIGIT(r
, 5) = r2b
;
203 MP_DIGIT(r
, 4) = r2a
;
204 MP_DIGIT(r
, 3) = r1b
;
205 MP_DIGIT(r
, 2) = r1a
;
206 MP_DIGIT(r
, 1) = r0b
;
207 MP_DIGIT(r
, 0) = r0a
;
209 /* copy out upper words of a */
221 a5a
= a5
& 0xffffffff;
227 a3b
= MP_DIGIT(a
, 3) >> 32;
232 r3
= MP_DIGIT(a
, 3) & 0xffffffff;
237 /* implement r = (a3a,a2,a1,a0)
240 -( 0 0, 0|a6b, a6a|a5b )
241 -( a6b, a6a|a5b, a5a|a4b, a4a|a3b ) */
242 MP_ADD_CARRY (r1
, a3b
, r1
, 0, carry
);
243 MP_ADD_CARRY (r2
, a4
, r2
, carry
, carry
);
244 MP_ADD_CARRY (r3
, a5a
, r3
, carry
, carry
);
245 MP_ADD_CARRY (r1
, a5b
, r1
, 0, carry
);
246 MP_ADD_CARRY (r2
, a6
, r2
, carry
, carry
);
247 MP_ADD_CARRY (r3
, 0, r3
, carry
, carry
);
249 MP_SUB_BORROW(r0
, a4a_a3b
, r0
, 0, carry
);
250 MP_SUB_BORROW(r1
, a5a_a4b
, r1
, carry
, carry
);
251 MP_SUB_BORROW(r2
, a6a_a5b
, r2
, carry
, carry
);
252 MP_SUB_BORROW(r3
, a6b
, r3
, carry
, carry
);
253 MP_SUB_BORROW(r0
, a6a_a5b
, r0
, 0, carry
);
254 MP_SUB_BORROW(r1
, a6b
, r1
, carry
, carry
);
256 MP_SUB_BORROW(r2
, 0, r2
, carry
, carry
);
257 MP_SUB_BORROW(r3
, 0, r3
, carry
, carry
);
261 /* if the value is negative, r3 has a 2's complement
263 r3b
= (int)(r3
>>32);
266 MP_ADD_CARRY(r1
,((mp_digit
)r3b
) << 32, r1
, 0, carry
);
268 MP_ADD_CARRY(r2
, 0, r2
, carry
, carry
);
269 MP_ADD_CARRY(r3
, 0, r3
, carry
, carry
);
271 MP_SUB_BORROW(r0
, r3b
, r0
, 0, carry
);
273 MP_SUB_BORROW(r1
, 0, r1
, carry
, carry
);
274 MP_SUB_BORROW(r2
, 0, r2
, carry
, carry
);
275 MP_SUB_BORROW(r3
, 0, r3
, carry
, carry
);
277 r3b
= (int)(r3
>>32);
281 MP_ADD_CARRY (r0
, 1, r0
, 0, carry
);
282 MP_ADD_CARRY (r1
, MP_DIGIT_MAX
<<32, r1
, carry
, carry
);
283 MP_ADD_CARRY (r2
, MP_DIGIT_MAX
, r2
, carry
, carry
);
284 MP_ADD_CARRY (r3
, MP_DIGIT_MAX
>> 32, r3
, carry
, carry
);
285 r3b
= (int)(r3
>>32);
287 /* check for final reduction */
288 /* now the only way we are over is if the top 4 words are all ones */
289 if ((r3
== (MP_DIGIT_MAX
>> 32)) && (r2
== MP_DIGIT_MAX
)
290 && ((r1
& MP_DIGIT_MAX
<< 32)== MP_DIGIT_MAX
<< 32) &&
291 ((r1
!= MP_DIGIT_MAX
<< 32 ) || (r0
!= 0)) ) {
292 /* one last subraction */
293 MP_SUB_BORROW(r0
, 1, r0
, 0, carry
);
294 MP_SUB_BORROW(r1
, 0, r1
, carry
, carry
);
300 MP_CHECKOK(s_mp_pad(r
, 4));
302 /* set the lower words of r */
303 MP_SIGN(r
) = MP_ZPOS
;
316 /* Compute the square of polynomial a, reduce modulo p224. Store the
317 * result in r. r could be a. Uses optimized modular reduction for p224.
320 ec_GFp_nistp224_sqr(const mp_int
*a
, mp_int
*r
, const GFMethod
*meth
)
322 mp_err res
= MP_OKAY
;
324 MP_CHECKOK(mp_sqr(a
, r
));
325 MP_CHECKOK(ec_GFp_nistp224_mod(r
, r
, meth
));
330 /* Compute the product of two polynomials a and b, reduce modulo p224.
331 * Store the result in r. r could be a or b; a could be b. Uses
332 * optimized modular reduction for p224. */
334 ec_GFp_nistp224_mul(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
335 const GFMethod
*meth
)
337 mp_err res
= MP_OKAY
;
339 MP_CHECKOK(mp_mul(a
, b
, r
));
340 MP_CHECKOK(ec_GFp_nistp224_mod(r
, r
, meth
));
345 /* Divides two field elements. If a is NULL, then returns the inverse of
348 ec_GFp_nistp224_div(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
349 const GFMethod
*meth
)
351 mp_err res
= MP_OKAY
;
354 /* If a is NULL, then return the inverse of b, otherwise return a/b. */
356 return mp_invmod(b
, &meth
->irr
, r
);
358 /* MPI doesn't support divmod, so we implement it using invmod and
360 MP_CHECKOK(mp_init(&t
, FLAG(b
)));
361 MP_CHECKOK(mp_invmod(b
, &meth
->irr
, &t
));
362 MP_CHECKOK(mp_mul(a
, &t
, r
));
363 MP_CHECKOK(ec_GFp_nistp224_mod(r
, r
, meth
));
370 /* Wire in fast field arithmetic and precomputation of base point for
373 ec_group_set_gfp224(ECGroup
*group
, ECCurveName name
)
375 if (name
== ECCurve_NIST_P224
) {
376 group
->meth
->field_mod
= &ec_GFp_nistp224_mod
;
377 group
->meth
->field_mul
= &ec_GFp_nistp224_mul
;
378 group
->meth
->field_sqr
= &ec_GFp_nistp224_sqr
;
379 group
->meth
->field_div
= &ec_GFp_nistp224_div
;