Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(51)

Side by Side Diff: nss/lib/freebl/ecl/ecl_gf.c

Issue 2078763002: Delete bundled copy of NSS and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss@master
Patch Set: Delete bundled copy of NSS and replace with README. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « nss/lib/freebl/ecl/ecl_curve.c ('k') | nss/lib/freebl/ecl/ecl_mult.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 #include "mpi.h"
6 #include "mp_gf2m.h"
7 #include "ecl-priv.h"
8 #include "mpi-priv.h"
9 #include <stdlib.h>
10
11 /* Allocate memory for a new GFMethod object. */
12 GFMethod *
13 GFMethod_new()
14 {
15 mp_err res = MP_OKAY;
16 GFMethod *meth;
17 meth = (GFMethod *) malloc(sizeof(GFMethod));
18 if (meth == NULL)
19 return NULL;
20 meth->constructed = MP_YES;
21 MP_DIGITS(&meth->irr) = 0;
22 meth->extra_free = NULL;
23 MP_CHECKOK(mp_init(&meth->irr));
24
25 CLEANUP:
26 if (res != MP_OKAY) {
27 GFMethod_free(meth);
28 return NULL;
29 }
30 return meth;
31 }
32
33 /* Construct a generic GFMethod for arithmetic over prime fields with
34 * irreducible irr. */
35 GFMethod *
36 GFMethod_consGFp(const mp_int *irr)
37 {
38 mp_err res = MP_OKAY;
39 GFMethod *meth = NULL;
40
41 meth = GFMethod_new();
42 if (meth == NULL)
43 return NULL;
44
45 MP_CHECKOK(mp_copy(irr, &meth->irr));
46 meth->irr_arr[0] = mpl_significant_bits(irr);
47 meth->irr_arr[1] = meth->irr_arr[2] = meth->irr_arr[3] =
48 meth->irr_arr[4] = 0;
49 switch(MP_USED(&meth->irr)) {
50 /* maybe we need 1 and 2 words here as well?*/
51 case 3:
52 meth->field_add = &ec_GFp_add_3;
53 meth->field_sub = &ec_GFp_sub_3;
54 break;
55 case 4:
56 meth->field_add = &ec_GFp_add_4;
57 meth->field_sub = &ec_GFp_sub_4;
58 break;
59 case 5:
60 meth->field_add = &ec_GFp_add_5;
61 meth->field_sub = &ec_GFp_sub_5;
62 break;
63 case 6:
64 meth->field_add = &ec_GFp_add_6;
65 meth->field_sub = &ec_GFp_sub_6;
66 break;
67 default:
68 meth->field_add = &ec_GFp_add;
69 meth->field_sub = &ec_GFp_sub;
70 }
71 meth->field_neg = &ec_GFp_neg;
72 meth->field_mod = &ec_GFp_mod;
73 meth->field_mul = &ec_GFp_mul;
74 meth->field_sqr = &ec_GFp_sqr;
75 meth->field_div = &ec_GFp_div;
76 meth->field_enc = NULL;
77 meth->field_dec = NULL;
78 meth->extra1 = NULL;
79 meth->extra2 = NULL;
80 meth->extra_free = NULL;
81
82 CLEANUP:
83 if (res != MP_OKAY) {
84 GFMethod_free(meth);
85 return NULL;
86 }
87 return meth;
88 }
89
90 /* Construct a generic GFMethod for arithmetic over binary polynomial
91 * fields with irreducible irr that has array representation irr_arr (see
92 * ecl-priv.h for description of the representation). If irr_arr is NULL,
93 * then it is constructed from the bitstring representation. */
94 GFMethod *
95 GFMethod_consGF2m(const mp_int *irr, const unsigned int irr_arr[5])
96 {
97 mp_err res = MP_OKAY;
98 int ret;
99 GFMethod *meth = NULL;
100
101 meth = GFMethod_new();
102 if (meth == NULL)
103 return NULL;
104
105 MP_CHECKOK(mp_copy(irr, &meth->irr));
106 if (irr_arr != NULL) {
107 /* Irreducible polynomials are either trinomials or pentanomials . */
108 meth->irr_arr[0] = irr_arr[0];
109 meth->irr_arr[1] = irr_arr[1];
110 meth->irr_arr[2] = irr_arr[2];
111 if (irr_arr[2] > 0) {
112 meth->irr_arr[3] = irr_arr[3];
113 meth->irr_arr[4] = irr_arr[4];
114 } else {
115 meth->irr_arr[3] = meth->irr_arr[4] = 0;
116 }
117 } else {
118 ret = mp_bpoly2arr(irr, meth->irr_arr, 5);
119 /* Irreducible polynomials are either trinomials or pentanomials . */
120 if ((ret != 5) && (ret != 3)) {
121 res = MP_UNDEF;
122 goto CLEANUP;
123 }
124 }
125 meth->field_add = &ec_GF2m_add;
126 meth->field_neg = &ec_GF2m_neg;
127 meth->field_sub = &ec_GF2m_add;
128 meth->field_mod = &ec_GF2m_mod;
129 meth->field_mul = &ec_GF2m_mul;
130 meth->field_sqr = &ec_GF2m_sqr;
131 meth->field_div = &ec_GF2m_div;
132 meth->field_enc = NULL;
133 meth->field_dec = NULL;
134 meth->extra1 = NULL;
135 meth->extra2 = NULL;
136 meth->extra_free = NULL;
137
138 CLEANUP:
139 if (res != MP_OKAY) {
140 GFMethod_free(meth);
141 return NULL;
142 }
143 return meth;
144 }
145
146 /* Free the memory allocated (if any) to a GFMethod object. */
147 void
148 GFMethod_free(GFMethod *meth)
149 {
150 if (meth == NULL)
151 return;
152 if (meth->constructed == MP_NO)
153 return;
154 mp_clear(&meth->irr);
155 if (meth->extra_free != NULL)
156 meth->extra_free(meth);
157 free(meth);
158 }
159
160 /* Wrapper functions for generic prime field arithmetic. */
161
162 /* Add two field elements. Assumes that 0 <= a, b < meth->irr */
163 mp_err
164 ec_GFp_add(const mp_int *a, const mp_int *b, mp_int *r,
165 const GFMethod *meth)
166 {
167 /* PRE: 0 <= a, b < p = meth->irr POST: 0 <= r < p, r = a + b (mod p) */
168 mp_err res;
169
170 if ((res = mp_add(a, b, r)) != MP_OKAY) {
171 return res;
172 }
173 if (mp_cmp(r, &meth->irr) >= 0) {
174 return mp_sub(r, &meth->irr, r);
175 }
176 return res;
177 }
178
179 /* Negates a field element. Assumes that 0 <= a < meth->irr */
180 mp_err
181 ec_GFp_neg(const mp_int *a, mp_int *r, const GFMethod *meth)
182 {
183 /* PRE: 0 <= a < p = meth->irr POST: 0 <= r < p, r = -a (mod p) */
184
185 if (mp_cmp_z(a) == 0) {
186 mp_zero(r);
187 return MP_OKAY;
188 }
189 return mp_sub(&meth->irr, a, r);
190 }
191
192 /* Subtracts two field elements. Assumes that 0 <= a, b < meth->irr */
193 mp_err
194 ec_GFp_sub(const mp_int *a, const mp_int *b, mp_int *r,
195 const GFMethod *meth)
196 {
197 mp_err res = MP_OKAY;
198
199 /* PRE: 0 <= a, b < p = meth->irr POST: 0 <= r < p, r = a - b (mod p) */
200 res = mp_sub(a, b, r);
201 if (res == MP_RANGE) {
202 MP_CHECKOK(mp_sub(b, a, r));
203 if (mp_cmp_z(r) < 0) {
204 MP_CHECKOK(mp_add(r, &meth->irr, r));
205 }
206 MP_CHECKOK(ec_GFp_neg(r, r, meth));
207 }
208 if (mp_cmp_z(r) < 0) {
209 MP_CHECKOK(mp_add(r, &meth->irr, r));
210 }
211 CLEANUP:
212 return res;
213 }
214 /*
215 * Inline adds for small curve lengths.
216 */
217 /* 3 words */
218 mp_err
219 ec_GFp_add_3(const mp_int *a, const mp_int *b, mp_int *r,
220 const GFMethod *meth)
221 {
222 mp_err res = MP_OKAY;
223 mp_digit a0 = 0, a1 = 0, a2 = 0;
224 mp_digit r0 = 0, r1 = 0, r2 = 0;
225 mp_digit carry;
226
227 switch(MP_USED(a)) {
228 case 3:
229 a2 = MP_DIGIT(a,2);
230 case 2:
231 a1 = MP_DIGIT(a,1);
232 case 1:
233 a0 = MP_DIGIT(a,0);
234 }
235 switch(MP_USED(b)) {
236 case 3:
237 r2 = MP_DIGIT(b,2);
238 case 2:
239 r1 = MP_DIGIT(b,1);
240 case 1:
241 r0 = MP_DIGIT(b,0);
242 }
243
244 #ifndef MPI_AMD64_ADD
245 carry = 0;
246 MP_ADD_CARRY(a0, r0, r0, carry);
247 MP_ADD_CARRY(a1, r1, r1, carry);
248 MP_ADD_CARRY(a2, r2, r2, carry);
249 #else
250 __asm__ (
251 "xorq %3,%3 \n\t"
252 "addq %4,%0 \n\t"
253 "adcq %5,%1 \n\t"
254 "adcq %6,%2 \n\t"
255 "adcq $0,%3 \n\t"
256 : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(carry)
257 : "r" (a0), "r" (a1), "r" (a2),
258 "0" (r0), "1" (r1), "2" (r2)
259 : "%cc" );
260 #endif
261
262 MP_CHECKOK(s_mp_pad(r, 3));
263 MP_DIGIT(r, 2) = r2;
264 MP_DIGIT(r, 1) = r1;
265 MP_DIGIT(r, 0) = r0;
266 MP_SIGN(r) = MP_ZPOS;
267 MP_USED(r) = 3;
268
269 /* Do quick 'subract' if we've gone over
270 * (add the 2's complement of the curve field) */
271 a2 = MP_DIGIT(&meth->irr,2);
272 if (carry || r2 > a2 ||
273 ((r2 == a2) && mp_cmp(r,&meth->irr) != MP_LT)) {
274 a1 = MP_DIGIT(&meth->irr,1);
275 a0 = MP_DIGIT(&meth->irr,0);
276 #ifndef MPI_AMD64_ADD
277 carry = 0;
278 MP_SUB_BORROW(r0, a0, r0, carry);
279 MP_SUB_BORROW(r1, a1, r1, carry);
280 MP_SUB_BORROW(r2, a2, r2, carry);
281 #else
282 __asm__ (
283 "subq %3,%0 \n\t"
284 "sbbq %4,%1 \n\t"
285 "sbbq %5,%2 \n\t"
286 : "=r"(r0), "=r"(r1), "=r"(r2)
287 : "r" (a0), "r" (a1), "r" (a2),
288 "0" (r0), "1" (r1), "2" (r2)
289 : "%cc" );
290 #endif
291 MP_DIGIT(r, 2) = r2;
292 MP_DIGIT(r, 1) = r1;
293 MP_DIGIT(r, 0) = r0;
294 }
295
296 s_mp_clamp(r);
297
298 CLEANUP:
299 return res;
300 }
301
302 /* 4 words */
303 mp_err
304 ec_GFp_add_4(const mp_int *a, const mp_int *b, mp_int *r,
305 const GFMethod *meth)
306 {
307 mp_err res = MP_OKAY;
308 mp_digit a0 = 0, a1 = 0, a2 = 0, a3 = 0;
309 mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0;
310 mp_digit carry;
311
312 switch(MP_USED(a)) {
313 case 4:
314 a3 = MP_DIGIT(a,3);
315 case 3:
316 a2 = MP_DIGIT(a,2);
317 case 2:
318 a1 = MP_DIGIT(a,1);
319 case 1:
320 a0 = MP_DIGIT(a,0);
321 }
322 switch(MP_USED(b)) {
323 case 4:
324 r3 = MP_DIGIT(b,3);
325 case 3:
326 r2 = MP_DIGIT(b,2);
327 case 2:
328 r1 = MP_DIGIT(b,1);
329 case 1:
330 r0 = MP_DIGIT(b,0);
331 }
332
333 #ifndef MPI_AMD64_ADD
334 carry = 0;
335 MP_ADD_CARRY(a0, r0, r0, carry);
336 MP_ADD_CARRY(a1, r1, r1, carry);
337 MP_ADD_CARRY(a2, r2, r2, carry);
338 MP_ADD_CARRY(a3, r3, r3, carry);
339 #else
340 __asm__ (
341 "xorq %4,%4 \n\t"
342 "addq %5,%0 \n\t"
343 "adcq %6,%1 \n\t"
344 "adcq %7,%2 \n\t"
345 "adcq %8,%3 \n\t"
346 "adcq $0,%4 \n\t"
347 : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(carry)
348 : "r" (a0), "r" (a1), "r" (a2), "r" (a3),
349 "0" (r0), "1" (r1), "2" (r2), "3" (r3)
350 : "%cc" );
351 #endif
352
353 MP_CHECKOK(s_mp_pad(r, 4));
354 MP_DIGIT(r, 3) = r3;
355 MP_DIGIT(r, 2) = r2;
356 MP_DIGIT(r, 1) = r1;
357 MP_DIGIT(r, 0) = r0;
358 MP_SIGN(r) = MP_ZPOS;
359 MP_USED(r) = 4;
360
361 /* Do quick 'subract' if we've gone over
362 * (add the 2's complement of the curve field) */
363 a3 = MP_DIGIT(&meth->irr,3);
364 if (carry || r3 > a3 ||
365 ((r3 == a3) && mp_cmp(r,&meth->irr) != MP_LT)) {
366 a2 = MP_DIGIT(&meth->irr,2);
367 a1 = MP_DIGIT(&meth->irr,1);
368 a0 = MP_DIGIT(&meth->irr,0);
369 #ifndef MPI_AMD64_ADD
370 carry = 0;
371 MP_SUB_BORROW(r0, a0, r0, carry);
372 MP_SUB_BORROW(r1, a1, r1, carry);
373 MP_SUB_BORROW(r2, a2, r2, carry);
374 MP_SUB_BORROW(r3, a3, r3, carry);
375 #else
376 __asm__ (
377 "subq %4,%0 \n\t"
378 "sbbq %5,%1 \n\t"
379 "sbbq %6,%2 \n\t"
380 "sbbq %7,%3 \n\t"
381 : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3)
382 : "r" (a0), "r" (a1), "r" (a2), "r" (a3),
383 "0" (r0), "1" (r1), "2" (r2), "3" (r3)
384 : "%cc" );
385 #endif
386 MP_DIGIT(r, 3) = r3;
387 MP_DIGIT(r, 2) = r2;
388 MP_DIGIT(r, 1) = r1;
389 MP_DIGIT(r, 0) = r0;
390 }
391
392 s_mp_clamp(r);
393
394 CLEANUP:
395 return res;
396 }
397
398 /* 5 words */
399 mp_err
400 ec_GFp_add_5(const mp_int *a, const mp_int *b, mp_int *r,
401 const GFMethod *meth)
402 {
403 mp_err res = MP_OKAY;
404 mp_digit a0 = 0, a1 = 0, a2 = 0, a3 = 0, a4 = 0;
405 mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0;
406 mp_digit carry;
407
408 switch(MP_USED(a)) {
409 case 5:
410 a4 = MP_DIGIT(a,4);
411 case 4:
412 a3 = MP_DIGIT(a,3);
413 case 3:
414 a2 = MP_DIGIT(a,2);
415 case 2:
416 a1 = MP_DIGIT(a,1);
417 case 1:
418 a0 = MP_DIGIT(a,0);
419 }
420 switch(MP_USED(b)) {
421 case 5:
422 r4 = MP_DIGIT(b,4);
423 case 4:
424 r3 = MP_DIGIT(b,3);
425 case 3:
426 r2 = MP_DIGIT(b,2);
427 case 2:
428 r1 = MP_DIGIT(b,1);
429 case 1:
430 r0 = MP_DIGIT(b,0);
431 }
432
433 carry = 0;
434 MP_ADD_CARRY(a0, r0, r0, carry);
435 MP_ADD_CARRY(a1, r1, r1, carry);
436 MP_ADD_CARRY(a2, r2, r2, carry);
437 MP_ADD_CARRY(a3, r3, r3, carry);
438 MP_ADD_CARRY(a4, r4, r4, carry);
439
440 MP_CHECKOK(s_mp_pad(r, 5));
441 MP_DIGIT(r, 4) = r4;
442 MP_DIGIT(r, 3) = r3;
443 MP_DIGIT(r, 2) = r2;
444 MP_DIGIT(r, 1) = r1;
445 MP_DIGIT(r, 0) = r0;
446 MP_SIGN(r) = MP_ZPOS;
447 MP_USED(r) = 5;
448
449 /* Do quick 'subract' if we've gone over
450 * (add the 2's complement of the curve field) */
451 a4 = MP_DIGIT(&meth->irr,4);
452 if (carry || r4 > a4 ||
453 ((r4 == a4) && mp_cmp(r,&meth->irr) != MP_LT)) {
454 a3 = MP_DIGIT(&meth->irr,3);
455 a2 = MP_DIGIT(&meth->irr,2);
456 a1 = MP_DIGIT(&meth->irr,1);
457 a0 = MP_DIGIT(&meth->irr,0);
458 carry = 0;
459 MP_SUB_BORROW(r0, a0, r0, carry);
460 MP_SUB_BORROW(r1, a1, r1, carry);
461 MP_SUB_BORROW(r2, a2, r2, carry);
462 MP_SUB_BORROW(r3, a3, r3, carry);
463 MP_SUB_BORROW(r4, a4, r4, carry);
464 MP_DIGIT(r, 4) = r4;
465 MP_DIGIT(r, 3) = r3;
466 MP_DIGIT(r, 2) = r2;
467 MP_DIGIT(r, 1) = r1;
468 MP_DIGIT(r, 0) = r0;
469 }
470
471 s_mp_clamp(r);
472
473 CLEANUP:
474 return res;
475 }
476
477 /* 6 words */
478 mp_err
479 ec_GFp_add_6(const mp_int *a, const mp_int *b, mp_int *r,
480 const GFMethod *meth)
481 {
482 mp_err res = MP_OKAY;
483 mp_digit a0 = 0, a1 = 0, a2 = 0, a3 = 0, a4 = 0, a5 = 0;
484 mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0;
485 mp_digit carry;
486
487 switch(MP_USED(a)) {
488 case 6:
489 a5 = MP_DIGIT(a,5);
490 case 5:
491 a4 = MP_DIGIT(a,4);
492 case 4:
493 a3 = MP_DIGIT(a,3);
494 case 3:
495 a2 = MP_DIGIT(a,2);
496 case 2:
497 a1 = MP_DIGIT(a,1);
498 case 1:
499 a0 = MP_DIGIT(a,0);
500 }
501 switch(MP_USED(b)) {
502 case 6:
503 r5 = MP_DIGIT(b,5);
504 case 5:
505 r4 = MP_DIGIT(b,4);
506 case 4:
507 r3 = MP_DIGIT(b,3);
508 case 3:
509 r2 = MP_DIGIT(b,2);
510 case 2:
511 r1 = MP_DIGIT(b,1);
512 case 1:
513 r0 = MP_DIGIT(b,0);
514 }
515
516 carry = 0;
517 MP_ADD_CARRY(a0, r0, r0, carry);
518 MP_ADD_CARRY(a1, r1, r1, carry);
519 MP_ADD_CARRY(a2, r2, r2, carry);
520 MP_ADD_CARRY(a3, r3, r3, carry);
521 MP_ADD_CARRY(a4, r4, r4, carry);
522 MP_ADD_CARRY(a5, r5, r5, carry);
523
524 MP_CHECKOK(s_mp_pad(r, 6));
525 MP_DIGIT(r, 5) = r5;
526 MP_DIGIT(r, 4) = r4;
527 MP_DIGIT(r, 3) = r3;
528 MP_DIGIT(r, 2) = r2;
529 MP_DIGIT(r, 1) = r1;
530 MP_DIGIT(r, 0) = r0;
531 MP_SIGN(r) = MP_ZPOS;
532 MP_USED(r) = 6;
533
534 /* Do quick 'subract' if we've gone over
535 * (add the 2's complement of the curve field) */
536 a5 = MP_DIGIT(&meth->irr,5);
537 if (carry || r5 > a5 ||
538 ((r5 == a5) && mp_cmp(r,&meth->irr) != MP_LT)) {
539 a4 = MP_DIGIT(&meth->irr,4);
540 a3 = MP_DIGIT(&meth->irr,3);
541 a2 = MP_DIGIT(&meth->irr,2);
542 a1 = MP_DIGIT(&meth->irr,1);
543 a0 = MP_DIGIT(&meth->irr,0);
544 carry = 0;
545 MP_SUB_BORROW(r0, a0, r0, carry);
546 MP_SUB_BORROW(r1, a1, r1, carry);
547 MP_SUB_BORROW(r2, a2, r2, carry);
548 MP_SUB_BORROW(r3, a3, r3, carry);
549 MP_SUB_BORROW(r4, a4, r4, carry);
550 MP_SUB_BORROW(r5, a5, r5, carry);
551 MP_DIGIT(r, 5) = r5;
552 MP_DIGIT(r, 4) = r4;
553 MP_DIGIT(r, 3) = r3;
554 MP_DIGIT(r, 2) = r2;
555 MP_DIGIT(r, 1) = r1;
556 MP_DIGIT(r, 0) = r0;
557 }
558
559 s_mp_clamp(r);
560
561 CLEANUP:
562 return res;
563 }
564
565 /*
566 * The following subraction functions do in-line subractions based
567 * on our curve size.
568 *
569 * ... 3 words
570 */
571 mp_err
572 ec_GFp_sub_3(const mp_int *a, const mp_int *b, mp_int *r,
573 const GFMethod *meth)
574 {
575 mp_err res = MP_OKAY;
576 mp_digit b0 = 0, b1 = 0, b2 = 0;
577 mp_digit r0 = 0, r1 = 0, r2 = 0;
578 mp_digit borrow;
579
580 switch(MP_USED(a)) {
581 case 3:
582 r2 = MP_DIGIT(a,2);
583 case 2:
584 r1 = MP_DIGIT(a,1);
585 case 1:
586 r0 = MP_DIGIT(a,0);
587 }
588 switch(MP_USED(b)) {
589 case 3:
590 b2 = MP_DIGIT(b,2);
591 case 2:
592 b1 = MP_DIGIT(b,1);
593 case 1:
594 b0 = MP_DIGIT(b,0);
595 }
596
597 #ifndef MPI_AMD64_ADD
598 borrow = 0;
599 MP_SUB_BORROW(r0, b0, r0, borrow);
600 MP_SUB_BORROW(r1, b1, r1, borrow);
601 MP_SUB_BORROW(r2, b2, r2, borrow);
602 #else
603 __asm__ (
604 "xorq %3,%3 \n\t"
605 "subq %4,%0 \n\t"
606 "sbbq %5,%1 \n\t"
607 "sbbq %6,%2 \n\t"
608 "adcq $0,%3 \n\t"
609 : "=r"(r0), "=r"(r1), "=r"(r2), "=r" (borrow)
610 : "r" (b0), "r" (b1), "r" (b2),
611 "0" (r0), "1" (r1), "2" (r2)
612 : "%cc" );
613 #endif
614
615 /* Do quick 'add' if we've gone under 0
616 * (subtract the 2's complement of the curve field) */
617 if (borrow) {
618 b2 = MP_DIGIT(&meth->irr,2);
619 b1 = MP_DIGIT(&meth->irr,1);
620 b0 = MP_DIGIT(&meth->irr,0);
621 #ifndef MPI_AMD64_ADD
622 borrow = 0;
623 MP_ADD_CARRY(b0, r0, r0, borrow);
624 MP_ADD_CARRY(b1, r1, r1, borrow);
625 MP_ADD_CARRY(b2, r2, r2, borrow);
626 #else
627 __asm__ (
628 "addq %3,%0 \n\t"
629 "adcq %4,%1 \n\t"
630 "adcq %5,%2 \n\t"
631 : "=r"(r0), "=r"(r1), "=r"(r2)
632 : "r" (b0), "r" (b1), "r" (b2),
633 "0" (r0), "1" (r1), "2" (r2)
634 : "%cc" );
635 #endif
636 }
637
638 #ifdef MPI_AMD64_ADD
639 /* compiler fakeout? */
640 if ((r2 == b0) && (r1 == b0) && (r0 == b0)) {
641 MP_CHECKOK(s_mp_pad(r, 4));
642 }
643 #endif
644 MP_CHECKOK(s_mp_pad(r, 3));
645 MP_DIGIT(r, 2) = r2;
646 MP_DIGIT(r, 1) = r1;
647 MP_DIGIT(r, 0) = r0;
648 MP_SIGN(r) = MP_ZPOS;
649 MP_USED(r) = 3;
650 s_mp_clamp(r);
651
652 CLEANUP:
653 return res;
654 }
655
656 /* 4 words */
657 mp_err
658 ec_GFp_sub_4(const mp_int *a, const mp_int *b, mp_int *r,
659 const GFMethod *meth)
660 {
661 mp_err res = MP_OKAY;
662 mp_digit b0 = 0, b1 = 0, b2 = 0, b3 = 0;
663 mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0;
664 mp_digit borrow;
665
666 switch(MP_USED(a)) {
667 case 4:
668 r3 = MP_DIGIT(a,3);
669 case 3:
670 r2 = MP_DIGIT(a,2);
671 case 2:
672 r1 = MP_DIGIT(a,1);
673 case 1:
674 r0 = MP_DIGIT(a,0);
675 }
676 switch(MP_USED(b)) {
677 case 4:
678 b3 = MP_DIGIT(b,3);
679 case 3:
680 b2 = MP_DIGIT(b,2);
681 case 2:
682 b1 = MP_DIGIT(b,1);
683 case 1:
684 b0 = MP_DIGIT(b,0);
685 }
686
687 #ifndef MPI_AMD64_ADD
688 borrow = 0;
689 MP_SUB_BORROW(r0, b0, r0, borrow);
690 MP_SUB_BORROW(r1, b1, r1, borrow);
691 MP_SUB_BORROW(r2, b2, r2, borrow);
692 MP_SUB_BORROW(r3, b3, r3, borrow);
693 #else
694 __asm__ (
695 "xorq %4,%4 \n\t"
696 "subq %5,%0 \n\t"
697 "sbbq %6,%1 \n\t"
698 "sbbq %7,%2 \n\t"
699 "sbbq %8,%3 \n\t"
700 "adcq $0,%4 \n\t"
701 : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r" (borrow)
702 : "r" (b0), "r" (b1), "r" (b2), "r" (b3),
703 "0" (r0), "1" (r1), "2" (r2), "3" (r3)
704 : "%cc" );
705 #endif
706
707 /* Do quick 'add' if we've gone under 0
708 * (subtract the 2's complement of the curve field) */
709 if (borrow) {
710 b3 = MP_DIGIT(&meth->irr,3);
711 b2 = MP_DIGIT(&meth->irr,2);
712 b1 = MP_DIGIT(&meth->irr,1);
713 b0 = MP_DIGIT(&meth->irr,0);
714 #ifndef MPI_AMD64_ADD
715 borrow = 0;
716 MP_ADD_CARRY(b0, r0, r0, borrow);
717 MP_ADD_CARRY(b1, r1, r1, borrow);
718 MP_ADD_CARRY(b2, r2, r2, borrow);
719 MP_ADD_CARRY(b3, r3, r3, borrow);
720 #else
721 __asm__ (
722 "addq %4,%0 \n\t"
723 "adcq %5,%1 \n\t"
724 "adcq %6,%2 \n\t"
725 "adcq %7,%3 \n\t"
726 : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3)
727 : "r" (b0), "r" (b1), "r" (b2), "r" (b3),
728 "0" (r0), "1" (r1), "2" (r2), "3" (r3)
729 : "%cc" );
730 #endif
731 }
732 #ifdef MPI_AMD64_ADD
733 /* compiler fakeout? */
734 if ((r3 == b0) && (r1 == b0) && (r0 == b0)) {
735 MP_CHECKOK(s_mp_pad(r, 4));
736 }
737 #endif
738 MP_CHECKOK(s_mp_pad(r, 4));
739 MP_DIGIT(r, 3) = r3;
740 MP_DIGIT(r, 2) = r2;
741 MP_DIGIT(r, 1) = r1;
742 MP_DIGIT(r, 0) = r0;
743 MP_SIGN(r) = MP_ZPOS;
744 MP_USED(r) = 4;
745 s_mp_clamp(r);
746
747 CLEANUP:
748 return res;
749 }
750
751 /* 5 words */
752 mp_err
753 ec_GFp_sub_5(const mp_int *a, const mp_int *b, mp_int *r,
754 const GFMethod *meth)
755 {
756 mp_err res = MP_OKAY;
757 mp_digit b0 = 0, b1 = 0, b2 = 0, b3 = 0, b4 = 0;
758 mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0;
759 mp_digit borrow;
760
761 switch(MP_USED(a)) {
762 case 5:
763 r4 = MP_DIGIT(a,4);
764 case 4:
765 r3 = MP_DIGIT(a,3);
766 case 3:
767 r2 = MP_DIGIT(a,2);
768 case 2:
769 r1 = MP_DIGIT(a,1);
770 case 1:
771 r0 = MP_DIGIT(a,0);
772 }
773 switch(MP_USED(b)) {
774 case 5:
775 b4 = MP_DIGIT(b,4);
776 case 4:
777 b3 = MP_DIGIT(b,3);
778 case 3:
779 b2 = MP_DIGIT(b,2);
780 case 2:
781 b1 = MP_DIGIT(b,1);
782 case 1:
783 b0 = MP_DIGIT(b,0);
784 }
785
786 borrow = 0;
787 MP_SUB_BORROW(r0, b0, r0, borrow);
788 MP_SUB_BORROW(r1, b1, r1, borrow);
789 MP_SUB_BORROW(r2, b2, r2, borrow);
790 MP_SUB_BORROW(r3, b3, r3, borrow);
791 MP_SUB_BORROW(r4, b4, r4, borrow);
792
793 /* Do quick 'add' if we've gone under 0
794 * (subtract the 2's complement of the curve field) */
795 if (borrow) {
796 b4 = MP_DIGIT(&meth->irr,4);
797 b3 = MP_DIGIT(&meth->irr,3);
798 b2 = MP_DIGIT(&meth->irr,2);
799 b1 = MP_DIGIT(&meth->irr,1);
800 b0 = MP_DIGIT(&meth->irr,0);
801 borrow = 0;
802 MP_ADD_CARRY(b0, r0, r0, borrow);
803 MP_ADD_CARRY(b1, r1, r1, borrow);
804 MP_ADD_CARRY(b2, r2, r2, borrow);
805 MP_ADD_CARRY(b3, r3, r3, borrow);
806 }
807 MP_CHECKOK(s_mp_pad(r, 5));
808 MP_DIGIT(r, 4) = r4;
809 MP_DIGIT(r, 3) = r3;
810 MP_DIGIT(r, 2) = r2;
811 MP_DIGIT(r, 1) = r1;
812 MP_DIGIT(r, 0) = r0;
813 MP_SIGN(r) = MP_ZPOS;
814 MP_USED(r) = 5;
815 s_mp_clamp(r);
816
817 CLEANUP:
818 return res;
819 }
820
821 /* 6 words */
822 mp_err
823 ec_GFp_sub_6(const mp_int *a, const mp_int *b, mp_int *r,
824 const GFMethod *meth)
825 {
826 mp_err res = MP_OKAY;
827 mp_digit b0 = 0, b1 = 0, b2 = 0, b3 = 0, b4 = 0, b5 = 0;
828 mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0;
829 mp_digit borrow;
830
831 switch(MP_USED(a)) {
832 case 6:
833 r5 = MP_DIGIT(a,5);
834 case 5:
835 r4 = MP_DIGIT(a,4);
836 case 4:
837 r3 = MP_DIGIT(a,3);
838 case 3:
839 r2 = MP_DIGIT(a,2);
840 case 2:
841 r1 = MP_DIGIT(a,1);
842 case 1:
843 r0 = MP_DIGIT(a,0);
844 }
845 switch(MP_USED(b)) {
846 case 6:
847 b5 = MP_DIGIT(b,5);
848 case 5:
849 b4 = MP_DIGIT(b,4);
850 case 4:
851 b3 = MP_DIGIT(b,3);
852 case 3:
853 b2 = MP_DIGIT(b,2);
854 case 2:
855 b1 = MP_DIGIT(b,1);
856 case 1:
857 b0 = MP_DIGIT(b,0);
858 }
859
860 borrow = 0;
861 MP_SUB_BORROW(r0, b0, r0, borrow);
862 MP_SUB_BORROW(r1, b1, r1, borrow);
863 MP_SUB_BORROW(r2, b2, r2, borrow);
864 MP_SUB_BORROW(r3, b3, r3, borrow);
865 MP_SUB_BORROW(r4, b4, r4, borrow);
866 MP_SUB_BORROW(r5, b5, r5, borrow);
867
868 /* Do quick 'add' if we've gone under 0
869 * (subtract the 2's complement of the curve field) */
870 if (borrow) {
871 b5 = MP_DIGIT(&meth->irr,5);
872 b4 = MP_DIGIT(&meth->irr,4);
873 b3 = MP_DIGIT(&meth->irr,3);
874 b2 = MP_DIGIT(&meth->irr,2);
875 b1 = MP_DIGIT(&meth->irr,1);
876 b0 = MP_DIGIT(&meth->irr,0);
877 borrow = 0;
878 MP_ADD_CARRY(b0, r0, r0, borrow);
879 MP_ADD_CARRY(b1, r1, r1, borrow);
880 MP_ADD_CARRY(b2, r2, r2, borrow);
881 MP_ADD_CARRY(b3, r3, r3, borrow);
882 MP_ADD_CARRY(b4, r4, r4, borrow);
883 }
884
885 MP_CHECKOK(s_mp_pad(r, 6));
886 MP_DIGIT(r, 5) = r5;
887 MP_DIGIT(r, 4) = r4;
888 MP_DIGIT(r, 3) = r3;
889 MP_DIGIT(r, 2) = r2;
890 MP_DIGIT(r, 1) = r1;
891 MP_DIGIT(r, 0) = r0;
892 MP_SIGN(r) = MP_ZPOS;
893 MP_USED(r) = 6;
894 s_mp_clamp(r);
895
896 CLEANUP:
897 return res;
898 }
899
900
901 /* Reduces an integer to a field element. */
902 mp_err
903 ec_GFp_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
904 {
905 return mp_mod(a, &meth->irr, r);
906 }
907
908 /* Multiplies two field elements. */
909 mp_err
910 ec_GFp_mul(const mp_int *a, const mp_int *b, mp_int *r,
911 const GFMethod *meth)
912 {
913 return mp_mulmod(a, b, &meth->irr, r);
914 }
915
916 /* Squares a field element. */
917 mp_err
918 ec_GFp_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
919 {
920 return mp_sqrmod(a, &meth->irr, r);
921 }
922
923 /* Divides two field elements. If a is NULL, then returns the inverse of
924 * b. */
925 mp_err
926 ec_GFp_div(const mp_int *a, const mp_int *b, mp_int *r,
927 const GFMethod *meth)
928 {
929 mp_err res = MP_OKAY;
930 mp_int t;
931
932 /* If a is NULL, then return the inverse of b, otherwise return a/b. */
933 if (a == NULL) {
934 return mp_invmod(b, &meth->irr, r);
935 } else {
936 /* MPI doesn't support divmod, so we implement it using invmod a nd
937 * mulmod. */
938 MP_CHECKOK(mp_init(&t));
939 MP_CHECKOK(mp_invmod(b, &meth->irr, &t));
940 MP_CHECKOK(mp_mulmod(a, &t, &meth->irr, r));
941 CLEANUP:
942 mp_clear(&t);
943 return res;
944 }
945 }
946
947 /* Wrapper functions for generic binary polynomial field arithmetic. */
948
949 /* Adds two field elements. */
950 mp_err
951 ec_GF2m_add(const mp_int *a, const mp_int *b, mp_int *r,
952 const GFMethod *meth)
953 {
954 return mp_badd(a, b, r);
955 }
956
957 /* Negates a field element. Note that for binary polynomial fields, the
958 * negation of a field element is the field element itself. */
959 mp_err
960 ec_GF2m_neg(const mp_int *a, mp_int *r, const GFMethod *meth)
961 {
962 if (a == r) {
963 return MP_OKAY;
964 } else {
965 return mp_copy(a, r);
966 }
967 }
968
969 /* Reduces a binary polynomial to a field element. */
970 mp_err
971 ec_GF2m_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
972 {
973 return mp_bmod(a, meth->irr_arr, r);
974 }
975
976 /* Multiplies two field elements. */
977 mp_err
978 ec_GF2m_mul(const mp_int *a, const mp_int *b, mp_int *r,
979 const GFMethod *meth)
980 {
981 return mp_bmulmod(a, b, meth->irr_arr, r);
982 }
983
984 /* Squares a field element. */
985 mp_err
986 ec_GF2m_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
987 {
988 return mp_bsqrmod(a, meth->irr_arr, r);
989 }
990
991 /* Divides two field elements. If a is NULL, then returns the inverse of
992 * b. */
993 mp_err
994 ec_GF2m_div(const mp_int *a, const mp_int *b, mp_int *r,
995 const GFMethod *meth)
996 {
997 mp_err res = MP_OKAY;
998 mp_int t;
999
1000 /* If a is NULL, then return the inverse of b, otherwise return a/b. */
1001 if (a == NULL) {
1002 /* The GF(2^m) portion of MPI doesn't support invmod, so we
1003 * compute 1/b. */
1004 MP_CHECKOK(mp_init(&t));
1005 MP_CHECKOK(mp_set_int(&t, 1));
1006 MP_CHECKOK(mp_bdivmod(&t, b, &meth->irr, meth->irr_arr, r));
1007 CLEANUP:
1008 mp_clear(&t);
1009 return res;
1010 } else {
1011 return mp_bdivmod(a, b, &meth->irr, meth->irr_arr, r);
1012 }
1013 }
OLDNEW
« no previous file with comments | « nss/lib/freebl/ecl/ecl_curve.c ('k') | nss/lib/freebl/ecl/ecl_mult.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698