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.
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 * Stephen Fung <fungstep@hotmail.com> and
24 * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
41 * Use is subject to license terms.
43 * Sun elects to use this software under the MPL license.
46 #pragma ident "%Z%%M% %I% %E% SMI"
56 /* Allocate memory for a new GFMethod object. */
58 GFMethod_new(int kmflag
)
63 meth
= (GFMethod
*) kmem_alloc(sizeof(GFMethod
), kmflag
);
65 meth
= (GFMethod
*) malloc(sizeof(GFMethod
));
69 meth
->constructed
= MP_YES
;
70 MP_DIGITS(&meth
->irr
) = 0;
71 meth
->extra_free
= NULL
;
72 MP_CHECKOK(mp_init(&meth
->irr
, kmflag
));
82 /* Construct a generic GFMethod for arithmetic over prime fields with
85 GFMethod_consGFp(const mp_int
*irr
)
88 GFMethod
*meth
= NULL
;
90 meth
= GFMethod_new(FLAG(irr
));
94 MP_CHECKOK(mp_copy(irr
, &meth
->irr
));
95 meth
->irr_arr
[0] = mpl_significant_bits(irr
);
96 meth
->irr_arr
[1] = meth
->irr_arr
[2] = meth
->irr_arr
[3] =
98 switch(MP_USED(&meth
->irr
)) {
99 /* maybe we need 1 and 2 words here as well?*/
101 meth
->field_add
= &ec_GFp_add_3
;
102 meth
->field_sub
= &ec_GFp_sub_3
;
105 meth
->field_add
= &ec_GFp_add_4
;
106 meth
->field_sub
= &ec_GFp_sub_4
;
109 meth
->field_add
= &ec_GFp_add_5
;
110 meth
->field_sub
= &ec_GFp_sub_5
;
113 meth
->field_add
= &ec_GFp_add_6
;
114 meth
->field_sub
= &ec_GFp_sub_6
;
117 meth
->field_add
= &ec_GFp_add
;
118 meth
->field_sub
= &ec_GFp_sub
;
120 meth
->field_neg
= &ec_GFp_neg
;
121 meth
->field_mod
= &ec_GFp_mod
;
122 meth
->field_mul
= &ec_GFp_mul
;
123 meth
->field_sqr
= &ec_GFp_sqr
;
124 meth
->field_div
= &ec_GFp_div
;
125 meth
->field_enc
= NULL
;
126 meth
->field_dec
= NULL
;
129 meth
->extra_free
= NULL
;
132 if (res
!= MP_OKAY
) {
139 /* Construct a generic GFMethod for arithmetic over binary polynomial
140 * fields with irreducible irr that has array representation irr_arr (see
141 * ecl-priv.h for description of the representation). If irr_arr is NULL,
142 * then it is constructed from the bitstring representation. */
144 GFMethod_consGF2m(const mp_int
*irr
, const unsigned int irr_arr
[5])
146 mp_err res
= MP_OKAY
;
148 GFMethod
*meth
= NULL
;
150 meth
= GFMethod_new(FLAG(irr
));
154 MP_CHECKOK(mp_copy(irr
, &meth
->irr
));
155 if (irr_arr
!= NULL
) {
156 /* Irreducible polynomials are either trinomials or pentanomials. */
157 meth
->irr_arr
[0] = irr_arr
[0];
158 meth
->irr_arr
[1] = irr_arr
[1];
159 meth
->irr_arr
[2] = irr_arr
[2];
160 if (irr_arr
[2] > 0) {
161 meth
->irr_arr
[3] = irr_arr
[3];
162 meth
->irr_arr
[4] = irr_arr
[4];
164 meth
->irr_arr
[3] = meth
->irr_arr
[4] = 0;
167 ret
= mp_bpoly2arr(irr
, meth
->irr_arr
, 5);
168 /* Irreducible polynomials are either trinomials or pentanomials. */
169 if ((ret
!= 5) && (ret
!= 3)) {
174 meth
->field_add
= &ec_GF2m_add
;
175 meth
->field_neg
= &ec_GF2m_neg
;
176 meth
->field_sub
= &ec_GF2m_add
;
177 meth
->field_mod
= &ec_GF2m_mod
;
178 meth
->field_mul
= &ec_GF2m_mul
;
179 meth
->field_sqr
= &ec_GF2m_sqr
;
180 meth
->field_div
= &ec_GF2m_div
;
181 meth
->field_enc
= NULL
;
182 meth
->field_dec
= NULL
;
185 meth
->extra_free
= NULL
;
188 if (res
!= MP_OKAY
) {
195 /* Free the memory allocated (if any) to a GFMethod object. */
197 GFMethod_free(GFMethod
*meth
)
201 if (meth
->constructed
== MP_NO
)
203 mp_clear(&meth
->irr
);
204 if (meth
->extra_free
!= NULL
)
205 meth
->extra_free(meth
);
207 kmem_free(meth
, sizeof(GFMethod
));
213 /* Wrapper functions for generic prime field arithmetic. */
215 /* Add two field elements. Assumes that 0 <= a, b < meth->irr */
217 ec_GFp_add(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
218 const GFMethod
*meth
)
220 /* PRE: 0 <= a, b < p = meth->irr POST: 0 <= r < p, r = a + b (mod p) */
223 if ((res
= mp_add(a
, b
, r
)) != MP_OKAY
) {
226 if (mp_cmp(r
, &meth
->irr
) >= 0) {
227 return mp_sub(r
, &meth
->irr
, r
);
232 /* Negates a field element. Assumes that 0 <= a < meth->irr */
234 ec_GFp_neg(const mp_int
*a
, mp_int
*r
, const GFMethod
*meth
)
236 /* PRE: 0 <= a < p = meth->irr POST: 0 <= r < p, r = -a (mod p) */
238 if (mp_cmp_z(a
) == 0) {
242 return mp_sub(&meth
->irr
, a
, r
);
245 /* Subtracts two field elements. Assumes that 0 <= a, b < meth->irr */
247 ec_GFp_sub(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
248 const GFMethod
*meth
)
250 mp_err res
= MP_OKAY
;
252 /* PRE: 0 <= a, b < p = meth->irr POST: 0 <= r < p, r = a - b (mod p) */
253 res
= mp_sub(a
, b
, r
);
254 if (res
== MP_RANGE
) {
255 MP_CHECKOK(mp_sub(b
, a
, r
));
256 if (mp_cmp_z(r
) < 0) {
257 MP_CHECKOK(mp_add(r
, &meth
->irr
, r
));
259 MP_CHECKOK(ec_GFp_neg(r
, r
, meth
));
261 if (mp_cmp_z(r
) < 0) {
262 MP_CHECKOK(mp_add(r
, &meth
->irr
, r
));
268 * Inline adds for small curve lengths.
272 ec_GFp_add_3(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
273 const GFMethod
*meth
)
275 mp_err res
= MP_OKAY
;
276 mp_digit a0
= 0, a1
= 0, a2
= 0;
277 mp_digit r0
= 0, r1
= 0, r2
= 0;
297 #ifndef MPI_AMD64_ADD
298 MP_ADD_CARRY(a0
, r0
, r0
, 0, carry
);
299 MP_ADD_CARRY(a1
, r1
, r1
, carry
, carry
);
300 MP_ADD_CARRY(a2
, r2
, r2
, carry
, carry
);
308 : "=r"(r0
), "=r"(r1
), "=r"(r2
), "=r"(carry
)
309 : "r" (a0
), "r" (a1
), "r" (a2
),
310 "0" (r0
), "1" (r1
), "2" (r2
)
314 MP_CHECKOK(s_mp_pad(r
, 3));
318 MP_SIGN(r
) = MP_ZPOS
;
321 /* Do quick 'subract' if we've gone over
322 * (add the 2's complement of the curve field) */
323 a2
= MP_DIGIT(&meth
->irr
,2);
324 if (carry
|| r2
> a2
||
325 ((r2
== a2
) && mp_cmp(r
,&meth
->irr
) != MP_LT
)) {
326 a1
= MP_DIGIT(&meth
->irr
,1);
327 a0
= MP_DIGIT(&meth
->irr
,0);
328 #ifndef MPI_AMD64_ADD
329 MP_SUB_BORROW(r0
, a0
, r0
, 0, carry
);
330 MP_SUB_BORROW(r1
, a1
, r1
, carry
, carry
);
331 MP_SUB_BORROW(r2
, a2
, r2
, carry
, carry
);
337 : "=r"(r0
), "=r"(r1
), "=r"(r2
)
338 : "r" (a0
), "r" (a1
), "r" (a2
),
339 "0" (r0
), "1" (r1
), "2" (r2
)
355 ec_GFp_add_4(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
356 const GFMethod
*meth
)
358 mp_err res
= MP_OKAY
;
359 mp_digit a0
= 0, a1
= 0, a2
= 0, a3
= 0;
360 mp_digit r0
= 0, r1
= 0, r2
= 0, r3
= 0;
384 #ifndef MPI_AMD64_ADD
385 MP_ADD_CARRY(a0
, r0
, r0
, 0, carry
);
386 MP_ADD_CARRY(a1
, r1
, r1
, carry
, carry
);
387 MP_ADD_CARRY(a2
, r2
, r2
, carry
, carry
);
388 MP_ADD_CARRY(a3
, r3
, r3
, carry
, carry
);
397 : "=r"(r0
), "=r"(r1
), "=r"(r2
), "=r"(r3
), "=r"(carry
)
398 : "r" (a0
), "r" (a1
), "r" (a2
), "r" (a3
),
399 "0" (r0
), "1" (r1
), "2" (r2
), "3" (r3
)
403 MP_CHECKOK(s_mp_pad(r
, 4));
408 MP_SIGN(r
) = MP_ZPOS
;
411 /* Do quick 'subract' if we've gone over
412 * (add the 2's complement of the curve field) */
413 a3
= MP_DIGIT(&meth
->irr
,3);
414 if (carry
|| r3
> a3
||
415 ((r3
== a3
) && mp_cmp(r
,&meth
->irr
) != MP_LT
)) {
416 a2
= MP_DIGIT(&meth
->irr
,2);
417 a1
= MP_DIGIT(&meth
->irr
,1);
418 a0
= MP_DIGIT(&meth
->irr
,0);
419 #ifndef MPI_AMD64_ADD
420 MP_SUB_BORROW(r0
, a0
, r0
, 0, carry
);
421 MP_SUB_BORROW(r1
, a1
, r1
, carry
, carry
);
422 MP_SUB_BORROW(r2
, a2
, r2
, carry
, carry
);
423 MP_SUB_BORROW(r3
, a3
, r3
, carry
, carry
);
430 : "=r"(r0
), "=r"(r1
), "=r"(r2
), "=r"(r3
)
431 : "r" (a0
), "r" (a1
), "r" (a2
), "r" (a3
),
432 "0" (r0
), "1" (r1
), "2" (r2
), "3" (r3
)
449 ec_GFp_add_5(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
450 const GFMethod
*meth
)
452 mp_err res
= MP_OKAY
;
453 mp_digit a0
= 0, a1
= 0, a2
= 0, a3
= 0, a4
= 0;
454 mp_digit r0
= 0, r1
= 0, r2
= 0, r3
= 0, r4
= 0;
482 MP_ADD_CARRY(a0
, r0
, r0
, 0, carry
);
483 MP_ADD_CARRY(a1
, r1
, r1
, carry
, carry
);
484 MP_ADD_CARRY(a2
, r2
, r2
, carry
, carry
);
485 MP_ADD_CARRY(a3
, r3
, r3
, carry
, carry
);
486 MP_ADD_CARRY(a4
, r4
, r4
, carry
, carry
);
488 MP_CHECKOK(s_mp_pad(r
, 5));
494 MP_SIGN(r
) = MP_ZPOS
;
497 /* Do quick 'subract' if we've gone over
498 * (add the 2's complement of the curve field) */
499 a4
= MP_DIGIT(&meth
->irr
,4);
500 if (carry
|| r4
> a4
||
501 ((r4
== a4
) && mp_cmp(r
,&meth
->irr
) != MP_LT
)) {
502 a3
= MP_DIGIT(&meth
->irr
,3);
503 a2
= MP_DIGIT(&meth
->irr
,2);
504 a1
= MP_DIGIT(&meth
->irr
,1);
505 a0
= MP_DIGIT(&meth
->irr
,0);
506 MP_SUB_BORROW(r0
, a0
, r0
, 0, carry
);
507 MP_SUB_BORROW(r1
, a1
, r1
, carry
, carry
);
508 MP_SUB_BORROW(r2
, a2
, r2
, carry
, carry
);
509 MP_SUB_BORROW(r3
, a3
, r3
, carry
, carry
);
510 MP_SUB_BORROW(r4
, a4
, r4
, carry
, carry
);
526 ec_GFp_add_6(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
527 const GFMethod
*meth
)
529 mp_err res
= MP_OKAY
;
530 mp_digit a0
= 0, a1
= 0, a2
= 0, a3
= 0, a4
= 0, a5
= 0;
531 mp_digit r0
= 0, r1
= 0, r2
= 0, r3
= 0, r4
= 0, r5
= 0;
563 MP_ADD_CARRY(a0
, r0
, r0
, 0, carry
);
564 MP_ADD_CARRY(a1
, r1
, r1
, carry
, carry
);
565 MP_ADD_CARRY(a2
, r2
, r2
, carry
, carry
);
566 MP_ADD_CARRY(a3
, r3
, r3
, carry
, carry
);
567 MP_ADD_CARRY(a4
, r4
, r4
, carry
, carry
);
568 MP_ADD_CARRY(a5
, r5
, r5
, carry
, carry
);
570 MP_CHECKOK(s_mp_pad(r
, 6));
577 MP_SIGN(r
) = MP_ZPOS
;
580 /* Do quick 'subract' if we've gone over
581 * (add the 2's complement of the curve field) */
582 a5
= MP_DIGIT(&meth
->irr
,5);
583 if (carry
|| r5
> a5
||
584 ((r5
== a5
) && mp_cmp(r
,&meth
->irr
) != MP_LT
)) {
585 a4
= MP_DIGIT(&meth
->irr
,4);
586 a3
= MP_DIGIT(&meth
->irr
,3);
587 a2
= MP_DIGIT(&meth
->irr
,2);
588 a1
= MP_DIGIT(&meth
->irr
,1);
589 a0
= MP_DIGIT(&meth
->irr
,0);
590 MP_SUB_BORROW(r0
, a0
, r0
, 0, carry
);
591 MP_SUB_BORROW(r1
, a1
, r1
, carry
, carry
);
592 MP_SUB_BORROW(r2
, a2
, r2
, carry
, carry
);
593 MP_SUB_BORROW(r3
, a3
, r3
, carry
, carry
);
594 MP_SUB_BORROW(r4
, a4
, r4
, carry
, carry
);
595 MP_SUB_BORROW(r5
, a5
, r5
, carry
, carry
);
611 * The following subraction functions do in-line subractions based
617 ec_GFp_sub_3(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
618 const GFMethod
*meth
)
620 mp_err res
= MP_OKAY
;
621 mp_digit b0
= 0, b1
= 0, b2
= 0;
622 mp_digit r0
= 0, r1
= 0, r2
= 0;
642 #ifndef MPI_AMD64_ADD
643 MP_SUB_BORROW(r0
, b0
, r0
, 0, borrow
);
644 MP_SUB_BORROW(r1
, b1
, r1
, borrow
, borrow
);
645 MP_SUB_BORROW(r2
, b2
, r2
, borrow
, borrow
);
653 : "=r"(r0
), "=r"(r1
), "=r"(r2
), "=r" (borrow
)
654 : "r" (b0
), "r" (b1
), "r" (b2
),
655 "0" (r0
), "1" (r1
), "2" (r2
)
659 /* Do quick 'add' if we've gone under 0
660 * (subtract the 2's complement of the curve field) */
662 b2
= MP_DIGIT(&meth
->irr
,2);
663 b1
= MP_DIGIT(&meth
->irr
,1);
664 b0
= MP_DIGIT(&meth
->irr
,0);
665 #ifndef MPI_AMD64_ADD
666 MP_ADD_CARRY(b0
, r0
, r0
, 0, borrow
);
667 MP_ADD_CARRY(b1
, r1
, r1
, borrow
, borrow
);
668 MP_ADD_CARRY(b2
, r2
, r2
, borrow
, borrow
);
674 : "=r"(r0
), "=r"(r1
), "=r"(r2
)
675 : "r" (b0
), "r" (b1
), "r" (b2
),
676 "0" (r0
), "1" (r1
), "2" (r2
)
682 /* compiler fakeout? */
683 if ((r2
== b0
) && (r1
== b0
) && (r0
== b0
)) {
684 MP_CHECKOK(s_mp_pad(r
, 4));
687 MP_CHECKOK(s_mp_pad(r
, 3));
691 MP_SIGN(r
) = MP_ZPOS
;
701 ec_GFp_sub_4(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
702 const GFMethod
*meth
)
704 mp_err res
= MP_OKAY
;
705 mp_digit b0
= 0, b1
= 0, b2
= 0, b3
= 0;
706 mp_digit r0
= 0, r1
= 0, r2
= 0, r3
= 0;
730 #ifndef MPI_AMD64_ADD
731 MP_SUB_BORROW(r0
, b0
, r0
, 0, borrow
);
732 MP_SUB_BORROW(r1
, b1
, r1
, borrow
, borrow
);
733 MP_SUB_BORROW(r2
, b2
, r2
, borrow
, borrow
);
734 MP_SUB_BORROW(r3
, b3
, r3
, borrow
, borrow
);
743 : "=r"(r0
), "=r"(r1
), "=r"(r2
), "=r"(r3
), "=r" (borrow
)
744 : "r" (b0
), "r" (b1
), "r" (b2
), "r" (b3
),
745 "0" (r0
), "1" (r1
), "2" (r2
), "3" (r3
)
749 /* Do quick 'add' if we've gone under 0
750 * (subtract the 2's complement of the curve field) */
752 b3
= MP_DIGIT(&meth
->irr
,3);
753 b2
= MP_DIGIT(&meth
->irr
,2);
754 b1
= MP_DIGIT(&meth
->irr
,1);
755 b0
= MP_DIGIT(&meth
->irr
,0);
756 #ifndef MPI_AMD64_ADD
757 MP_ADD_CARRY(b0
, r0
, r0
, 0, borrow
);
758 MP_ADD_CARRY(b1
, r1
, r1
, borrow
, borrow
);
759 MP_ADD_CARRY(b2
, r2
, r2
, borrow
, borrow
);
760 MP_ADD_CARRY(b3
, r3
, r3
, borrow
, borrow
);
767 : "=r"(r0
), "=r"(r1
), "=r"(r2
), "=r"(r3
)
768 : "r" (b0
), "r" (b1
), "r" (b2
), "r" (b3
),
769 "0" (r0
), "1" (r1
), "2" (r2
), "3" (r3
)
774 /* compiler fakeout? */
775 if ((r3
== b0
) && (r1
== b0
) && (r0
== b0
)) {
776 MP_CHECKOK(s_mp_pad(r
, 4));
779 MP_CHECKOK(s_mp_pad(r
, 4));
784 MP_SIGN(r
) = MP_ZPOS
;
794 ec_GFp_sub_5(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
795 const GFMethod
*meth
)
797 mp_err res
= MP_OKAY
;
798 mp_digit b0
= 0, b1
= 0, b2
= 0, b3
= 0, b4
= 0;
799 mp_digit r0
= 0, r1
= 0, r2
= 0, r3
= 0, r4
= 0;
827 MP_SUB_BORROW(r0
, b0
, r0
, 0, borrow
);
828 MP_SUB_BORROW(r1
, b1
, r1
, borrow
, borrow
);
829 MP_SUB_BORROW(r2
, b2
, r2
, borrow
, borrow
);
830 MP_SUB_BORROW(r3
, b3
, r3
, borrow
, borrow
);
831 MP_SUB_BORROW(r4
, b4
, r4
, borrow
, borrow
);
833 /* Do quick 'add' if we've gone under 0
834 * (subtract the 2's complement of the curve field) */
836 b4
= MP_DIGIT(&meth
->irr
,4);
837 b3
= MP_DIGIT(&meth
->irr
,3);
838 b2
= MP_DIGIT(&meth
->irr
,2);
839 b1
= MP_DIGIT(&meth
->irr
,1);
840 b0
= MP_DIGIT(&meth
->irr
,0);
841 MP_ADD_CARRY(b0
, r0
, r0
, 0, borrow
);
842 MP_ADD_CARRY(b1
, r1
, r1
, borrow
, borrow
);
843 MP_ADD_CARRY(b2
, r2
, r2
, borrow
, borrow
);
844 MP_ADD_CARRY(b3
, r3
, r3
, borrow
, borrow
);
846 MP_CHECKOK(s_mp_pad(r
, 5));
852 MP_SIGN(r
) = MP_ZPOS
;
862 ec_GFp_sub_6(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
863 const GFMethod
*meth
)
865 mp_err res
= MP_OKAY
;
866 mp_digit b0
= 0, b1
= 0, b2
= 0, b3
= 0, b4
= 0, b5
= 0;
867 mp_digit r0
= 0, r1
= 0, r2
= 0, r3
= 0, r4
= 0, r5
= 0;
899 MP_SUB_BORROW(r0
, b0
, r0
, 0, borrow
);
900 MP_SUB_BORROW(r1
, b1
, r1
, borrow
, borrow
);
901 MP_SUB_BORROW(r2
, b2
, r2
, borrow
, borrow
);
902 MP_SUB_BORROW(r3
, b3
, r3
, borrow
, borrow
);
903 MP_SUB_BORROW(r4
, b4
, r4
, borrow
, borrow
);
904 MP_SUB_BORROW(r5
, b5
, r5
, borrow
, borrow
);
906 /* Do quick 'add' if we've gone under 0
907 * (subtract the 2's complement of the curve field) */
909 b5
= MP_DIGIT(&meth
->irr
,5);
910 b4
= MP_DIGIT(&meth
->irr
,4);
911 b3
= MP_DIGIT(&meth
->irr
,3);
912 b2
= MP_DIGIT(&meth
->irr
,2);
913 b1
= MP_DIGIT(&meth
->irr
,1);
914 b0
= MP_DIGIT(&meth
->irr
,0);
915 MP_ADD_CARRY(b0
, r0
, r0
, 0, borrow
);
916 MP_ADD_CARRY(b1
, r1
, r1
, borrow
, borrow
);
917 MP_ADD_CARRY(b2
, r2
, r2
, borrow
, borrow
);
918 MP_ADD_CARRY(b3
, r3
, r3
, borrow
, borrow
);
919 MP_ADD_CARRY(b4
, r4
, r4
, borrow
, borrow
);
922 MP_CHECKOK(s_mp_pad(r
, 6));
929 MP_SIGN(r
) = MP_ZPOS
;
938 /* Reduces an integer to a field element. */
940 ec_GFp_mod(const mp_int
*a
, mp_int
*r
, const GFMethod
*meth
)
942 return mp_mod(a
, &meth
->irr
, r
);
945 /* Multiplies two field elements. */
947 ec_GFp_mul(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
948 const GFMethod
*meth
)
950 return mp_mulmod(a
, b
, &meth
->irr
, r
);
953 /* Squares a field element. */
955 ec_GFp_sqr(const mp_int
*a
, mp_int
*r
, const GFMethod
*meth
)
957 return mp_sqrmod(a
, &meth
->irr
, r
);
960 /* Divides two field elements. If a is NULL, then returns the inverse of
963 ec_GFp_div(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
964 const GFMethod
*meth
)
966 mp_err res
= MP_OKAY
;
969 /* If a is NULL, then return the inverse of b, otherwise return a/b. */
971 return mp_invmod(b
, &meth
->irr
, r
);
973 /* MPI doesn't support divmod, so we implement it using invmod and
975 MP_CHECKOK(mp_init(&t
, FLAG(b
)));
976 MP_CHECKOK(mp_invmod(b
, &meth
->irr
, &t
));
977 MP_CHECKOK(mp_mulmod(a
, &t
, &meth
->irr
, r
));
984 /* Wrapper functions for generic binary polynomial field arithmetic. */
986 /* Adds two field elements. */
988 ec_GF2m_add(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
989 const GFMethod
*meth
)
991 return mp_badd(a
, b
, r
);
994 /* Negates a field element. Note that for binary polynomial fields, the
995 * negation of a field element is the field element itself. */
997 ec_GF2m_neg(const mp_int
*a
, mp_int
*r
, const GFMethod
*meth
)
1002 return mp_copy(a
, r
);
1006 /* Reduces a binary polynomial to a field element. */
1008 ec_GF2m_mod(const mp_int
*a
, mp_int
*r
, const GFMethod
*meth
)
1010 return mp_bmod(a
, meth
->irr_arr
, r
);
1013 /* Multiplies two field elements. */
1015 ec_GF2m_mul(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
1016 const GFMethod
*meth
)
1018 return mp_bmulmod(a
, b
, meth
->irr_arr
, r
);
1021 /* Squares a field element. */
1023 ec_GF2m_sqr(const mp_int
*a
, mp_int
*r
, const GFMethod
*meth
)
1025 return mp_bsqrmod(a
, meth
->irr_arr
, r
);
1028 /* Divides two field elements. If a is NULL, then returns the inverse of
1031 ec_GF2m_div(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
1032 const GFMethod
*meth
)
1034 mp_err res
= MP_OKAY
;
1037 /* If a is NULL, then return the inverse of b, otherwise return a/b. */
1039 /* The GF(2^m) portion of MPI doesn't support invmod, so we
1041 MP_CHECKOK(mp_init(&t
, FLAG(b
)));
1042 MP_CHECKOK(mp_set_int(&t
, 1));
1043 MP_CHECKOK(mp_bdivmod(&t
, b
, &meth
->irr
, meth
->irr_arr
, r
));
1048 return mp_bdivmod(a
, b
, &meth
->irr
, meth
->irr_arr
, r
);