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 ***** */
46 /* Allocate memory for a new GFMethod object. */
52 meth
= (GFMethod
*) malloc(sizeof(GFMethod
));
55 meth
->constructed
= MP_YES
;
56 MP_DIGITS(&meth
->irr
) = 0;
57 meth
->extra_free
= NULL
;
58 MP_CHECKOK(mp_init(&meth
->irr
));
68 /* Construct a generic GFMethod for arithmetic over prime fields with
71 GFMethod_consGFp(const mp_int
*irr
)
74 GFMethod
*meth
= NULL
;
76 meth
= GFMethod_new();
80 MP_CHECKOK(mp_copy(irr
, &meth
->irr
));
81 meth
->irr_arr
[0] = mpl_significant_bits(irr
);
82 meth
->irr_arr
[1] = meth
->irr_arr
[2] = meth
->irr_arr
[3] =
84 switch(MP_USED(&meth
->irr
)) {
85 /* maybe we need 1 and 2 words here as well?*/
87 meth
->field_add
= &ec_GFp_add_3
;
88 meth
->field_sub
= &ec_GFp_sub_3
;
91 meth
->field_add
= &ec_GFp_add_4
;
92 meth
->field_sub
= &ec_GFp_sub_4
;
95 meth
->field_add
= &ec_GFp_add_5
;
96 meth
->field_sub
= &ec_GFp_sub_5
;
99 meth
->field_add
= &ec_GFp_add_6
;
100 meth
->field_sub
= &ec_GFp_sub_6
;
103 meth
->field_add
= &ec_GFp_add
;
104 meth
->field_sub
= &ec_GFp_sub
;
106 meth
->field_neg
= &ec_GFp_neg
;
107 meth
->field_mod
= &ec_GFp_mod
;
108 meth
->field_mul
= &ec_GFp_mul
;
109 meth
->field_sqr
= &ec_GFp_sqr
;
110 meth
->field_div
= &ec_GFp_div
;
111 meth
->field_enc
= NULL
;
112 meth
->field_dec
= NULL
;
115 meth
->extra_free
= NULL
;
118 if (res
!= MP_OKAY
) {
125 /* Construct a generic GFMethod for arithmetic over binary polynomial
126 * fields with irreducible irr that has array representation irr_arr (see
127 * ecl-priv.h for description of the representation). If irr_arr is NULL,
128 * then it is constructed from the bitstring representation. */
130 GFMethod_consGF2m(const mp_int
*irr
, const unsigned int irr_arr
[5])
132 mp_err res
= MP_OKAY
;
134 GFMethod
*meth
= NULL
;
136 meth
= GFMethod_new();
140 MP_CHECKOK(mp_copy(irr
, &meth
->irr
));
141 if (irr_arr
!= NULL
) {
142 /* Irreducible polynomials are either trinomials or pentanomials. */
143 meth
->irr_arr
[0] = irr_arr
[0];
144 meth
->irr_arr
[1] = irr_arr
[1];
145 meth
->irr_arr
[2] = irr_arr
[2];
146 if (irr_arr
[2] > 0) {
147 meth
->irr_arr
[3] = irr_arr
[3];
148 meth
->irr_arr
[4] = irr_arr
[4];
150 meth
->irr_arr
[3] = meth
->irr_arr
[4] = 0;
153 ret
= mp_bpoly2arr(irr
, meth
->irr_arr
, 5);
154 /* Irreducible polynomials are either trinomials or pentanomials. */
155 if ((ret
!= 5) && (ret
!= 3)) {
160 meth
->field_add
= &ec_GF2m_add
;
161 meth
->field_neg
= &ec_GF2m_neg
;
162 meth
->field_sub
= &ec_GF2m_add
;
163 meth
->field_mod
= &ec_GF2m_mod
;
164 meth
->field_mul
= &ec_GF2m_mul
;
165 meth
->field_sqr
= &ec_GF2m_sqr
;
166 meth
->field_div
= &ec_GF2m_div
;
167 meth
->field_enc
= NULL
;
168 meth
->field_dec
= NULL
;
171 meth
->extra_free
= NULL
;
174 if (res
!= MP_OKAY
) {
181 /* Free the memory allocated (if any) to a GFMethod object. */
183 GFMethod_free(GFMethod
*meth
)
187 if (meth
->constructed
== MP_NO
)
189 mp_clear(&meth
->irr
);
190 if (meth
->extra_free
!= NULL
)
191 meth
->extra_free(meth
);
195 /* Wrapper functions for generic prime field arithmetic. */
197 /* Add two field elements. Assumes that 0 <= a, b < meth->irr */
199 ec_GFp_add(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
200 const GFMethod
*meth
)
202 /* PRE: 0 <= a, b < p = meth->irr POST: 0 <= r < p, r = a + b (mod p) */
205 if ((res
= mp_add(a
, b
, r
)) != MP_OKAY
) {
208 if (mp_cmp(r
, &meth
->irr
) >= 0) {
209 return mp_sub(r
, &meth
->irr
, r
);
214 /* Negates a field element. Assumes that 0 <= a < meth->irr */
216 ec_GFp_neg(const mp_int
*a
, mp_int
*r
, const GFMethod
*meth
)
218 /* PRE: 0 <= a < p = meth->irr POST: 0 <= r < p, r = -a (mod p) */
220 if (mp_cmp_z(a
) == 0) {
224 return mp_sub(&meth
->irr
, a
, r
);
227 /* Subtracts two field elements. Assumes that 0 <= a, b < meth->irr */
229 ec_GFp_sub(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
230 const GFMethod
*meth
)
232 mp_err res
= MP_OKAY
;
234 /* PRE: 0 <= a, b < p = meth->irr POST: 0 <= r < p, r = a - b (mod p) */
235 res
= mp_sub(a
, b
, r
);
236 if (res
== MP_RANGE
) {
237 MP_CHECKOK(mp_sub(b
, a
, r
));
238 if (mp_cmp_z(r
) < 0) {
239 MP_CHECKOK(mp_add(r
, &meth
->irr
, r
));
241 MP_CHECKOK(ec_GFp_neg(r
, r
, meth
));
243 if (mp_cmp_z(r
) < 0) {
244 MP_CHECKOK(mp_add(r
, &meth
->irr
, r
));
250 * Inline adds for small curve lengths.
254 ec_GFp_add_3(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
255 const GFMethod
*meth
)
257 mp_err res
= MP_OKAY
;
258 mp_digit a0
= 0, a1
= 0, a2
= 0;
259 mp_digit r0
= 0, r1
= 0, r2
= 0;
279 #ifndef MPI_AMD64_ADD
280 MP_ADD_CARRY(a0
, r0
, r0
, 0, carry
);
281 MP_ADD_CARRY(a1
, r1
, r1
, carry
, carry
);
282 MP_ADD_CARRY(a2
, r2
, r2
, carry
, carry
);
290 : "=r"(r0
), "=r"(r1
), "=r"(r2
), "=r"(carry
)
291 : "r" (a0
), "r" (a1
), "r" (a2
),
292 "0" (r0
), "1" (r1
), "2" (r2
)
296 MP_CHECKOK(s_mp_pad(r
, 3));
300 MP_SIGN(r
) = MP_ZPOS
;
303 /* Do quick 'subract' if we've gone over
304 * (add the 2's complement of the curve field) */
305 a2
= MP_DIGIT(&meth
->irr
,2);
306 if (carry
|| r2
> a2
||
307 ((r2
== a2
) && mp_cmp(r
,&meth
->irr
) != MP_LT
)) {
308 a1
= MP_DIGIT(&meth
->irr
,1);
309 a0
= MP_DIGIT(&meth
->irr
,0);
310 #ifndef MPI_AMD64_ADD
311 MP_SUB_BORROW(r0
, a0
, r0
, 0, carry
);
312 MP_SUB_BORROW(r1
, a1
, r1
, carry
, carry
);
313 MP_SUB_BORROW(r2
, a2
, r2
, carry
, carry
);
319 : "=r"(r0
), "=r"(r1
), "=r"(r2
)
320 : "r" (a0
), "r" (a1
), "r" (a2
),
321 "0" (r0
), "1" (r1
), "2" (r2
)
337 ec_GFp_add_4(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
338 const GFMethod
*meth
)
340 mp_err res
= MP_OKAY
;
341 mp_digit a0
= 0, a1
= 0, a2
= 0, a3
= 0;
342 mp_digit r0
= 0, r1
= 0, r2
= 0, r3
= 0;
366 #ifndef MPI_AMD64_ADD
367 MP_ADD_CARRY(a0
, r0
, r0
, 0, carry
);
368 MP_ADD_CARRY(a1
, r1
, r1
, carry
, carry
);
369 MP_ADD_CARRY(a2
, r2
, r2
, carry
, carry
);
370 MP_ADD_CARRY(a3
, r3
, r3
, carry
, carry
);
379 : "=r"(r0
), "=r"(r1
), "=r"(r2
), "=r"(r3
), "=r"(carry
)
380 : "r" (a0
), "r" (a1
), "r" (a2
), "r" (a3
),
381 "0" (r0
), "1" (r1
), "2" (r2
), "3" (r3
)
385 MP_CHECKOK(s_mp_pad(r
, 4));
390 MP_SIGN(r
) = MP_ZPOS
;
393 /* Do quick 'subract' if we've gone over
394 * (add the 2's complement of the curve field) */
395 a3
= MP_DIGIT(&meth
->irr
,3);
396 if (carry
|| r3
> a3
||
397 ((r3
== a3
) && mp_cmp(r
,&meth
->irr
) != MP_LT
)) {
398 a2
= MP_DIGIT(&meth
->irr
,2);
399 a1
= MP_DIGIT(&meth
->irr
,1);
400 a0
= MP_DIGIT(&meth
->irr
,0);
401 #ifndef MPI_AMD64_ADD
402 MP_SUB_BORROW(r0
, a0
, r0
, 0, carry
);
403 MP_SUB_BORROW(r1
, a1
, r1
, carry
, carry
);
404 MP_SUB_BORROW(r2
, a2
, r2
, carry
, carry
);
405 MP_SUB_BORROW(r3
, a3
, r3
, carry
, carry
);
412 : "=r"(r0
), "=r"(r1
), "=r"(r2
), "=r"(r3
)
413 : "r" (a0
), "r" (a1
), "r" (a2
), "r" (a3
),
414 "0" (r0
), "1" (r1
), "2" (r2
), "3" (r3
)
431 ec_GFp_add_5(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
432 const GFMethod
*meth
)
434 mp_err res
= MP_OKAY
;
435 mp_digit a0
= 0, a1
= 0, a2
= 0, a3
= 0, a4
= 0;
436 mp_digit r0
= 0, r1
= 0, r2
= 0, r3
= 0, r4
= 0;
464 MP_ADD_CARRY(a0
, r0
, r0
, 0, carry
);
465 MP_ADD_CARRY(a1
, r1
, r1
, carry
, carry
);
466 MP_ADD_CARRY(a2
, r2
, r2
, carry
, carry
);
467 MP_ADD_CARRY(a3
, r3
, r3
, carry
, carry
);
468 MP_ADD_CARRY(a4
, r4
, r4
, carry
, carry
);
470 MP_CHECKOK(s_mp_pad(r
, 5));
476 MP_SIGN(r
) = MP_ZPOS
;
479 /* Do quick 'subract' if we've gone over
480 * (add the 2's complement of the curve field) */
481 a4
= MP_DIGIT(&meth
->irr
,4);
482 if (carry
|| r4
> a4
||
483 ((r4
== a4
) && mp_cmp(r
,&meth
->irr
) != MP_LT
)) {
484 a3
= MP_DIGIT(&meth
->irr
,3);
485 a2
= MP_DIGIT(&meth
->irr
,2);
486 a1
= MP_DIGIT(&meth
->irr
,1);
487 a0
= MP_DIGIT(&meth
->irr
,0);
488 MP_SUB_BORROW(r0
, a0
, r0
, 0, carry
);
489 MP_SUB_BORROW(r1
, a1
, r1
, carry
, carry
);
490 MP_SUB_BORROW(r2
, a2
, r2
, carry
, carry
);
491 MP_SUB_BORROW(r3
, a3
, r3
, carry
, carry
);
492 MP_SUB_BORROW(r4
, a4
, r4
, carry
, carry
);
508 ec_GFp_add_6(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
509 const GFMethod
*meth
)
511 mp_err res
= MP_OKAY
;
512 mp_digit a0
= 0, a1
= 0, a2
= 0, a3
= 0, a4
= 0, a5
= 0;
513 mp_digit r0
= 0, r1
= 0, r2
= 0, r3
= 0, r4
= 0, r5
= 0;
545 MP_ADD_CARRY(a0
, r0
, r0
, 0, carry
);
546 MP_ADD_CARRY(a1
, r1
, r1
, carry
, carry
);
547 MP_ADD_CARRY(a2
, r2
, r2
, carry
, carry
);
548 MP_ADD_CARRY(a3
, r3
, r3
, carry
, carry
);
549 MP_ADD_CARRY(a4
, r4
, r4
, carry
, carry
);
550 MP_ADD_CARRY(a5
, r5
, r5
, carry
, carry
);
552 MP_CHECKOK(s_mp_pad(r
, 6));
559 MP_SIGN(r
) = MP_ZPOS
;
562 /* Do quick 'subract' if we've gone over
563 * (add the 2's complement of the curve field) */
564 a5
= MP_DIGIT(&meth
->irr
,5);
565 if (carry
|| r5
> a5
||
566 ((r5
== a5
) && mp_cmp(r
,&meth
->irr
) != MP_LT
)) {
567 a4
= MP_DIGIT(&meth
->irr
,4);
568 a3
= MP_DIGIT(&meth
->irr
,3);
569 a2
= MP_DIGIT(&meth
->irr
,2);
570 a1
= MP_DIGIT(&meth
->irr
,1);
571 a0
= MP_DIGIT(&meth
->irr
,0);
572 MP_SUB_BORROW(r0
, a0
, r0
, 0, carry
);
573 MP_SUB_BORROW(r1
, a1
, r1
, carry
, carry
);
574 MP_SUB_BORROW(r2
, a2
, r2
, carry
, carry
);
575 MP_SUB_BORROW(r3
, a3
, r3
, carry
, carry
);
576 MP_SUB_BORROW(r4
, a4
, r4
, carry
, carry
);
577 MP_SUB_BORROW(r5
, a5
, r5
, carry
, carry
);
593 * The following subraction functions do in-line subractions based
599 ec_GFp_sub_3(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
600 const GFMethod
*meth
)
602 mp_err res
= MP_OKAY
;
603 mp_digit b0
= 0, b1
= 0, b2
= 0;
604 mp_digit r0
= 0, r1
= 0, r2
= 0;
624 #ifndef MPI_AMD64_ADD
625 MP_SUB_BORROW(r0
, b0
, r0
, 0, borrow
);
626 MP_SUB_BORROW(r1
, b1
, r1
, borrow
, borrow
);
627 MP_SUB_BORROW(r2
, b2
, r2
, borrow
, borrow
);
635 : "=r"(r0
), "=r"(r1
), "=r"(r2
), "=r" (borrow
)
636 : "r" (b0
), "r" (b1
), "r" (b2
),
637 "0" (r0
), "1" (r1
), "2" (r2
)
641 /* Do quick 'add' if we've gone under 0
642 * (subtract the 2's complement of the curve field) */
644 b2
= MP_DIGIT(&meth
->irr
,2);
645 b1
= MP_DIGIT(&meth
->irr
,1);
646 b0
= MP_DIGIT(&meth
->irr
,0);
647 #ifndef MPI_AMD64_ADD
648 MP_ADD_CARRY(b0
, r0
, r0
, 0, borrow
);
649 MP_ADD_CARRY(b1
, r1
, r1
, borrow
, borrow
);
650 MP_ADD_CARRY(b2
, r2
, r2
, borrow
, borrow
);
656 : "=r"(r0
), "=r"(r1
), "=r"(r2
)
657 : "r" (b0
), "r" (b1
), "r" (b2
),
658 "0" (r0
), "1" (r1
), "2" (r2
)
664 /* compiler fakeout? */
665 if ((r2
== b0
) && (r1
== b0
) && (r0
== b0
)) {
666 MP_CHECKOK(s_mp_pad(r
, 4));
669 MP_CHECKOK(s_mp_pad(r
, 3));
673 MP_SIGN(r
) = MP_ZPOS
;
683 ec_GFp_sub_4(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
684 const GFMethod
*meth
)
686 mp_err res
= MP_OKAY
;
687 mp_digit b0
= 0, b1
= 0, b2
= 0, b3
= 0;
688 mp_digit r0
= 0, r1
= 0, r2
= 0, r3
= 0;
712 #ifndef MPI_AMD64_ADD
713 MP_SUB_BORROW(r0
, b0
, r0
, 0, borrow
);
714 MP_SUB_BORROW(r1
, b1
, r1
, borrow
, borrow
);
715 MP_SUB_BORROW(r2
, b2
, r2
, borrow
, borrow
);
716 MP_SUB_BORROW(r3
, b3
, r3
, borrow
, borrow
);
725 : "=r"(r0
), "=r"(r1
), "=r"(r2
), "=r"(r3
), "=r" (borrow
)
726 : "r" (b0
), "r" (b1
), "r" (b2
), "r" (b3
),
727 "0" (r0
), "1" (r1
), "2" (r2
), "3" (r3
)
731 /* Do quick 'add' if we've gone under 0
732 * (subtract the 2's complement of the curve field) */
734 b3
= MP_DIGIT(&meth
->irr
,3);
735 b2
= MP_DIGIT(&meth
->irr
,2);
736 b1
= MP_DIGIT(&meth
->irr
,1);
737 b0
= MP_DIGIT(&meth
->irr
,0);
738 #ifndef MPI_AMD64_ADD
739 MP_ADD_CARRY(b0
, r0
, r0
, 0, borrow
);
740 MP_ADD_CARRY(b1
, r1
, r1
, borrow
, borrow
);
741 MP_ADD_CARRY(b2
, r2
, r2
, borrow
, borrow
);
742 MP_ADD_CARRY(b3
, r3
, r3
, borrow
, borrow
);
749 : "=r"(r0
), "=r"(r1
), "=r"(r2
), "=r"(r3
)
750 : "r" (b0
), "r" (b1
), "r" (b2
), "r" (b3
),
751 "0" (r0
), "1" (r1
), "2" (r2
), "3" (r3
)
756 /* compiler fakeout? */
757 if ((r3
== b0
) && (r1
== b0
) && (r0
== b0
)) {
758 MP_CHECKOK(s_mp_pad(r
, 4));
761 MP_CHECKOK(s_mp_pad(r
, 4));
766 MP_SIGN(r
) = MP_ZPOS
;
776 ec_GFp_sub_5(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
777 const GFMethod
*meth
)
779 mp_err res
= MP_OKAY
;
780 mp_digit b0
= 0, b1
= 0, b2
= 0, b3
= 0, b4
= 0;
781 mp_digit r0
= 0, r1
= 0, r2
= 0, r3
= 0, r4
= 0;
809 MP_SUB_BORROW(r0
, b0
, r0
, 0, borrow
);
810 MP_SUB_BORROW(r1
, b1
, r1
, borrow
, borrow
);
811 MP_SUB_BORROW(r2
, b2
, r2
, borrow
, borrow
);
812 MP_SUB_BORROW(r3
, b3
, r3
, borrow
, borrow
);
813 MP_SUB_BORROW(r4
, b4
, r4
, borrow
, borrow
);
815 /* Do quick 'add' if we've gone under 0
816 * (subtract the 2's complement of the curve field) */
818 b4
= MP_DIGIT(&meth
->irr
,4);
819 b3
= MP_DIGIT(&meth
->irr
,3);
820 b2
= MP_DIGIT(&meth
->irr
,2);
821 b1
= MP_DIGIT(&meth
->irr
,1);
822 b0
= MP_DIGIT(&meth
->irr
,0);
823 MP_ADD_CARRY(b0
, r0
, r0
, 0, borrow
);
824 MP_ADD_CARRY(b1
, r1
, r1
, borrow
, borrow
);
825 MP_ADD_CARRY(b2
, r2
, r2
, borrow
, borrow
);
826 MP_ADD_CARRY(b3
, r3
, r3
, borrow
, borrow
);
828 MP_CHECKOK(s_mp_pad(r
, 5));
834 MP_SIGN(r
) = MP_ZPOS
;
844 ec_GFp_sub_6(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
845 const GFMethod
*meth
)
847 mp_err res
= MP_OKAY
;
848 mp_digit b0
= 0, b1
= 0, b2
= 0, b3
= 0, b4
= 0, b5
= 0;
849 mp_digit r0
= 0, r1
= 0, r2
= 0, r3
= 0, r4
= 0, r5
= 0;
881 MP_SUB_BORROW(r0
, b0
, r0
, 0, borrow
);
882 MP_SUB_BORROW(r1
, b1
, r1
, borrow
, borrow
);
883 MP_SUB_BORROW(r2
, b2
, r2
, borrow
, borrow
);
884 MP_SUB_BORROW(r3
, b3
, r3
, borrow
, borrow
);
885 MP_SUB_BORROW(r4
, b4
, r4
, borrow
, borrow
);
886 MP_SUB_BORROW(r5
, b5
, r5
, borrow
, borrow
);
888 /* Do quick 'add' if we've gone under 0
889 * (subtract the 2's complement of the curve field) */
891 b5
= MP_DIGIT(&meth
->irr
,5);
892 b4
= MP_DIGIT(&meth
->irr
,4);
893 b3
= MP_DIGIT(&meth
->irr
,3);
894 b2
= MP_DIGIT(&meth
->irr
,2);
895 b1
= MP_DIGIT(&meth
->irr
,1);
896 b0
= MP_DIGIT(&meth
->irr
,0);
897 MP_ADD_CARRY(b0
, r0
, r0
, 0, borrow
);
898 MP_ADD_CARRY(b1
, r1
, r1
, borrow
, borrow
);
899 MP_ADD_CARRY(b2
, r2
, r2
, borrow
, borrow
);
900 MP_ADD_CARRY(b3
, r3
, r3
, borrow
, borrow
);
901 MP_ADD_CARRY(b4
, r4
, r4
, borrow
, borrow
);
904 MP_CHECKOK(s_mp_pad(r
, 6));
911 MP_SIGN(r
) = MP_ZPOS
;
920 /* Reduces an integer to a field element. */
922 ec_GFp_mod(const mp_int
*a
, mp_int
*r
, const GFMethod
*meth
)
924 return mp_mod(a
, &meth
->irr
, r
);
927 /* Multiplies two field elements. */
929 ec_GFp_mul(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
930 const GFMethod
*meth
)
932 return mp_mulmod(a
, b
, &meth
->irr
, r
);
935 /* Squares a field element. */
937 ec_GFp_sqr(const mp_int
*a
, mp_int
*r
, const GFMethod
*meth
)
939 return mp_sqrmod(a
, &meth
->irr
, r
);
942 /* Divides two field elements. If a is NULL, then returns the inverse of
945 ec_GFp_div(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
946 const GFMethod
*meth
)
948 mp_err res
= MP_OKAY
;
951 /* If a is NULL, then return the inverse of b, otherwise return a/b. */
953 return mp_invmod(b
, &meth
->irr
, r
);
955 /* MPI doesn't support divmod, so we implement it using invmod and
957 MP_CHECKOK(mp_init(&t
));
958 MP_CHECKOK(mp_invmod(b
, &meth
->irr
, &t
));
959 MP_CHECKOK(mp_mulmod(a
, &t
, &meth
->irr
, r
));
966 /* Wrapper functions for generic binary polynomial field arithmetic. */
968 /* Adds two field elements. */
970 ec_GF2m_add(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
971 const GFMethod
*meth
)
973 return mp_badd(a
, b
, r
);
976 /* Negates a field element. Note that for binary polynomial fields, the
977 * negation of a field element is the field element itself. */
979 ec_GF2m_neg(const mp_int
*a
, mp_int
*r
, const GFMethod
*meth
)
984 return mp_copy(a
, r
);
988 /* Reduces a binary polynomial to a field element. */
990 ec_GF2m_mod(const mp_int
*a
, mp_int
*r
, const GFMethod
*meth
)
992 return mp_bmod(a
, meth
->irr_arr
, r
);
995 /* Multiplies two field elements. */
997 ec_GF2m_mul(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
998 const GFMethod
*meth
)
1000 return mp_bmulmod(a
, b
, meth
->irr_arr
, r
);
1003 /* Squares a field element. */
1005 ec_GF2m_sqr(const mp_int
*a
, mp_int
*r
, const GFMethod
*meth
)
1007 return mp_bsqrmod(a
, meth
->irr_arr
, r
);
1010 /* Divides two field elements. If a is NULL, then returns the inverse of
1013 ec_GF2m_div(const mp_int
*a
, const mp_int
*b
, mp_int
*r
,
1014 const GFMethod
*meth
)
1016 mp_err res
= MP_OKAY
;
1019 /* If a is NULL, then return the inverse of b, otherwise return a/b. */
1021 /* The GF(2^m) portion of MPI doesn't support invmod, so we
1023 MP_CHECKOK(mp_init(&t
));
1024 MP_CHECKOK(mp_set_int(&t
, 1));
1025 MP_CHECKOK(mp_bdivmod(&t
, b
, &meth
->irr
, meth
->irr_arr
, r
));
1030 return mp_bdivmod(a
, b
, &meth
->irr
, meth
->irr_arr
, r
);