1*c40a6cd7SToomas Soome /*
2f9fbec18Smcpowers  * ***** BEGIN LICENSE BLOCK *****
3f9fbec18Smcpowers  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4f9fbec18Smcpowers  *
5f9fbec18Smcpowers  * The contents of this file are subject to the Mozilla Public License Version
6f9fbec18Smcpowers  * 1.1 (the "License"); you may not use this file except in compliance with
7f9fbec18Smcpowers  * the License. You may obtain a copy of the License at
8f9fbec18Smcpowers  * http://www.mozilla.org/MPL/
9f9fbec18Smcpowers  *
10f9fbec18Smcpowers  * Software distributed under the License is distributed on an "AS IS" basis,
11f9fbec18Smcpowers  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12f9fbec18Smcpowers  * for the specific language governing rights and limitations under the
13f9fbec18Smcpowers  * License.
14f9fbec18Smcpowers  *
15f9fbec18Smcpowers  * The Original Code is the elliptic curve math library.
16f9fbec18Smcpowers  *
17f9fbec18Smcpowers  * The Initial Developer of the Original Code is
18f9fbec18Smcpowers  * Sun Microsystems, Inc.
19f9fbec18Smcpowers  * Portions created by the Initial Developer are Copyright (C) 2003
20f9fbec18Smcpowers  * the Initial Developer. All Rights Reserved.
21f9fbec18Smcpowers  *
22f9fbec18Smcpowers  * Contributor(s):
23f9fbec18Smcpowers  *   Stephen Fung <fungstep@hotmail.com> and
24f9fbec18Smcpowers  *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
25f9fbec18Smcpowers  *
26f9fbec18Smcpowers  * Alternatively, the contents of this file may be used under the terms of
27f9fbec18Smcpowers  * either the GNU General Public License Version 2 or later (the "GPL"), or
28f9fbec18Smcpowers  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29f9fbec18Smcpowers  * in which case the provisions of the GPL or the LGPL are applicable instead
30f9fbec18Smcpowers  * of those above. If you wish to allow use of your version of this file only
31f9fbec18Smcpowers  * under the terms of either the GPL or the LGPL, and not to allow others to
32f9fbec18Smcpowers  * use your version of this file under the terms of the MPL, indicate your
33f9fbec18Smcpowers  * decision by deleting the provisions above and replace them with the notice
34f9fbec18Smcpowers  * and other provisions required by the GPL or the LGPL. If you do not delete
35f9fbec18Smcpowers  * the provisions above, a recipient may use your version of this file under
36f9fbec18Smcpowers  * the terms of any one of the MPL, the GPL or the LGPL.
37f9fbec18Smcpowers  *
38f9fbec18Smcpowers  * ***** END LICENSE BLOCK ***** */
39f9fbec18Smcpowers /*
40f9fbec18Smcpowers  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
41f9fbec18Smcpowers  * Use is subject to license terms.
42f9fbec18Smcpowers  *
43f9fbec18Smcpowers  * Sun elects to use this software under the MPL license.
44f9fbec18Smcpowers  */
45f9fbec18Smcpowers 
46f9fbec18Smcpowers #ifndef _ECL_PRIV_H
47f9fbec18Smcpowers #define _ECL_PRIV_H
48f9fbec18Smcpowers 
49f9fbec18Smcpowers #include "ecl.h"
50f9fbec18Smcpowers #include "mpi.h"
51f9fbec18Smcpowers #include "mplogic.h"
52f9fbec18Smcpowers 
53f9fbec18Smcpowers /* MAX_FIELD_SIZE_DIGITS is the maximum size of field element supported */
54f9fbec18Smcpowers /* the following needs to go away... */
55f9fbec18Smcpowers #if defined(MP_USE_LONG_LONG_DIGIT) || defined(MP_USE_LONG_DIGIT)
56f9fbec18Smcpowers #define ECL_SIXTY_FOUR_BIT
57f9fbec18Smcpowers #else
58f9fbec18Smcpowers #define ECL_THIRTY_TWO_BIT
59f9fbec18Smcpowers #endif
60f9fbec18Smcpowers 
61f9fbec18Smcpowers #define ECL_CURVE_DIGITS(curve_size_in_bits) \
62f9fbec18Smcpowers 	(((curve_size_in_bits)+(sizeof(mp_digit)*8-1))/(sizeof(mp_digit)*8))
63f9fbec18Smcpowers #define ECL_BITS (sizeof(mp_digit)*8)
64f9fbec18Smcpowers #define ECL_MAX_FIELD_SIZE_DIGITS (80/sizeof(mp_digit))
65f9fbec18Smcpowers 
66*c40a6cd7SToomas Soome /* Gets the i'th bit in the binary representation of a. If i >= length(a),
67f9fbec18Smcpowers  * then return 0. (The above behaviour differs from mpl_get_bit, which
68f9fbec18Smcpowers  * causes an error if i >= length(a).) */
69f9fbec18Smcpowers #define MP_GET_BIT(a, i) \
70f9fbec18Smcpowers 	((i) >= mpl_significant_bits((a))) ? 0 : mpl_get_bit((a), (i))
71f9fbec18Smcpowers 
72f9fbec18Smcpowers #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
73f9fbec18Smcpowers #define MP_ADD_CARRY(a1, a2, s, cin, cout)   \
74f9fbec18Smcpowers     { mp_word w; \
75f9fbec18Smcpowers     w = ((mp_word)(cin)) + (a1) + (a2); \
76f9fbec18Smcpowers     s = ACCUM(w); \
77f9fbec18Smcpowers     cout = CARRYOUT(w); }
78f9fbec18Smcpowers 
79f9fbec18Smcpowers #define MP_SUB_BORROW(a1, a2, s, bin, bout)   \
80f9fbec18Smcpowers     { mp_word w; \
81f9fbec18Smcpowers     w = ((mp_word)(a1)) - (a2) - (bin); \
82f9fbec18Smcpowers     s = ACCUM(w); \
83f9fbec18Smcpowers     bout = (w >> MP_DIGIT_BIT) & 1; }
84f9fbec18Smcpowers 
85f9fbec18Smcpowers #else
86*c40a6cd7SToomas Soome /* NOTE,
87f9fbec18Smcpowers  * cin and cout could be the same variable.
88f9fbec18Smcpowers  * bin and bout could be the same variable.
89f9fbec18Smcpowers  * a1 or a2 and s could be the same variable.
90f9fbec18Smcpowers  * don't trash those outputs until their respective inputs have
91f9fbec18Smcpowers  * been read. */
92f9fbec18Smcpowers #define MP_ADD_CARRY(a1, a2, s, cin, cout)   \
93f9fbec18Smcpowers     { mp_digit tmp,sum; \
94f9fbec18Smcpowers     tmp = (a1); \
95f9fbec18Smcpowers     sum = tmp + (a2); \
96f9fbec18Smcpowers     tmp = (sum < tmp);                     /* detect overflow */ \
97f9fbec18Smcpowers     s = sum += (cin); \
98f9fbec18Smcpowers     cout = tmp + (sum < (cin)); }
99f9fbec18Smcpowers 
100f9fbec18Smcpowers #define MP_SUB_BORROW(a1, a2, s, bin, bout)   \
101f9fbec18Smcpowers     { mp_digit tmp; \
102f9fbec18Smcpowers     tmp = (a1); \
103f9fbec18Smcpowers     s = tmp - (a2); \
104f9fbec18Smcpowers     tmp = (s > tmp);                    /* detect borrow */ \
105f9fbec18Smcpowers     if ((bin) && !s--) tmp++;	\
106f9fbec18Smcpowers     bout = tmp; }
107f9fbec18Smcpowers #endif
108f9fbec18Smcpowers 
109f9fbec18Smcpowers 
110f9fbec18Smcpowers struct GFMethodStr;
111f9fbec18Smcpowers typedef struct GFMethodStr GFMethod;
112f9fbec18Smcpowers struct GFMethodStr {
113*c40a6cd7SToomas Soome 	/* Indicates whether the structure was constructed from dynamic memory
114f9fbec18Smcpowers 	 * or statically created. */
115f9fbec18Smcpowers 	int constructed;
116f9fbec18Smcpowers 	/* Irreducible that defines the field. For prime fields, this is the
117f9fbec18Smcpowers 	 * prime p. For binary polynomial fields, this is the bitstring
118f9fbec18Smcpowers 	 * representation of the irreducible polynomial. */
119f9fbec18Smcpowers 	mp_int irr;
120*c40a6cd7SToomas Soome 	/* For prime fields, the value irr_arr[0] is the number of bits in the
121f9fbec18Smcpowers 	 * field. For binary polynomial fields, the irreducible polynomial
122f9fbec18Smcpowers 	 * f(t) is represented as an array of unsigned int[], where f(t) is
123f9fbec18Smcpowers 	 * of the form: f(t) = t^p[0] + t^p[1] + ... + t^p[4] where m = p[0]
124f9fbec18Smcpowers 	 * > p[1] > ... > p[4] = 0. */
125f9fbec18Smcpowers 	unsigned int irr_arr[5];
126f9fbec18Smcpowers 	/* Field arithmetic methods. All methods (except field_enc and
127f9fbec18Smcpowers 	 * field_dec) are assumed to take field-encoded parameters and return
128f9fbec18Smcpowers 	 * field-encoded values. All methods (except field_enc and field_dec)
129f9fbec18Smcpowers 	 * are required to be implemented. */
130f9fbec18Smcpowers 	mp_err (*field_add) (const mp_int *a, const mp_int *b, mp_int *r,
131f9fbec18Smcpowers 						 const GFMethod *meth);
132f9fbec18Smcpowers 	mp_err (*field_neg) (const mp_int *a, mp_int *r, const GFMethod *meth);
133f9fbec18Smcpowers 	mp_err (*field_sub) (const mp_int *a, const mp_int *b, mp_int *r,
134f9fbec18Smcpowers 						 const GFMethod *meth);
135f9fbec18Smcpowers 	mp_err (*field_mod) (const mp_int *a, mp_int *r, const GFMethod *meth);
136f9fbec18Smcpowers 	mp_err (*field_mul) (const mp_int *a, const mp_int *b, mp_int *r,
137f9fbec18Smcpowers 						 const GFMethod *meth);
138f9fbec18Smcpowers 	mp_err (*field_sqr) (const mp_int *a, mp_int *r, const GFMethod *meth);
139f9fbec18Smcpowers 	mp_err (*field_div) (const mp_int *a, const mp_int *b, mp_int *r,
140f9fbec18Smcpowers 						 const GFMethod *meth);
141f9fbec18Smcpowers 	mp_err (*field_enc) (const mp_int *a, mp_int *r, const GFMethod *meth);
142f9fbec18Smcpowers 	mp_err (*field_dec) (const mp_int *a, mp_int *r, const GFMethod *meth);
143f9fbec18Smcpowers 	/* Extra storage for implementation-specific data.  Any memory
144f9fbec18Smcpowers 	 * allocated to these extra fields will be cleared by extra_free. */
145f9fbec18Smcpowers 	void *extra1;
146f9fbec18Smcpowers 	void *extra2;
147f9fbec18Smcpowers 	void (*extra_free) (GFMethod *meth);
148f9fbec18Smcpowers };
149f9fbec18Smcpowers 
150f9fbec18Smcpowers /* Construct generic GFMethods. */
151f9fbec18Smcpowers GFMethod *GFMethod_consGFp(const mp_int *irr);
152f9fbec18Smcpowers GFMethod *GFMethod_consGFp_mont(const mp_int *irr);
153f9fbec18Smcpowers GFMethod *GFMethod_consGF2m(const mp_int *irr,
154f9fbec18Smcpowers 							const unsigned int irr_arr[5]);
155f9fbec18Smcpowers /* Free the memory allocated (if any) to a GFMethod object. */
156f9fbec18Smcpowers void GFMethod_free(GFMethod *meth);
157f9fbec18Smcpowers 
158f9fbec18Smcpowers struct ECGroupStr {
159*c40a6cd7SToomas Soome 	/* Indicates whether the structure was constructed from dynamic memory
160f9fbec18Smcpowers 	 * or statically created. */
161f9fbec18Smcpowers 	int constructed;
162f9fbec18Smcpowers 	/* Field definition and arithmetic. */
163f9fbec18Smcpowers 	GFMethod *meth;
164f9fbec18Smcpowers 	/* Textual representation of curve name, if any. */
165f9fbec18Smcpowers 	char *text;
166f9fbec18Smcpowers #ifdef _KERNEL
167f9fbec18Smcpowers 	int text_len;
168f9fbec18Smcpowers #endif
169f9fbec18Smcpowers 	/* Curve parameters, field-encoded. */
170f9fbec18Smcpowers 	mp_int curvea, curveb;
171f9fbec18Smcpowers 	/* x and y coordinates of the base point, field-encoded. */
172f9fbec18Smcpowers 	mp_int genx, geny;
173f9fbec18Smcpowers 	/* Order and cofactor of the base point. */
174f9fbec18Smcpowers 	mp_int order;
175f9fbec18Smcpowers 	int cofactor;
176f9fbec18Smcpowers 	/* Point arithmetic methods. All methods are assumed to take
177f9fbec18Smcpowers 	 * field-encoded parameters and return field-encoded values. All
178f9fbec18Smcpowers 	 * methods (except base_point_mul and points_mul) are required to be
179f9fbec18Smcpowers 	 * implemented. */
180f9fbec18Smcpowers 	mp_err (*point_add) (const mp_int *px, const mp_int *py,
181f9fbec18Smcpowers 						 const mp_int *qx, const mp_int *qy, mp_int *rx,
182f9fbec18Smcpowers 						 mp_int *ry, const ECGroup *group);
183f9fbec18Smcpowers 	mp_err (*point_sub) (const mp_int *px, const mp_int *py,
184f9fbec18Smcpowers 						 const mp_int *qx, const mp_int *qy, mp_int *rx,
185f9fbec18Smcpowers 						 mp_int *ry, const ECGroup *group);
186f9fbec18Smcpowers 	mp_err (*point_dbl) (const mp_int *px, const mp_int *py, mp_int *rx,
187f9fbec18Smcpowers 						 mp_int *ry, const ECGroup *group);
188f9fbec18Smcpowers 	mp_err (*point_mul) (const mp_int *n, const mp_int *px,
189f9fbec18Smcpowers 						 const mp_int *py, mp_int *rx, mp_int *ry,
190f9fbec18Smcpowers 						 const ECGroup *group);
191f9fbec18Smcpowers 	mp_err (*base_point_mul) (const mp_int *n, mp_int *rx, mp_int *ry,
192f9fbec18Smcpowers 							  const ECGroup *group);
193f9fbec18Smcpowers 	mp_err (*points_mul) (const mp_int *k1, const mp_int *k2,
194f9fbec18Smcpowers 						  const mp_int *px, const mp_int *py, mp_int *rx,
195f9fbec18Smcpowers 						  mp_int *ry, const ECGroup *group);
196f9fbec18Smcpowers 	mp_err (*validate_point) (const mp_int *px, const mp_int *py, const ECGroup *group);
197f9fbec18Smcpowers 	/* Extra storage for implementation-specific data.  Any memory
198f9fbec18Smcpowers 	 * allocated to these extra fields will be cleared by extra_free. */
199f9fbec18Smcpowers 	void *extra1;
200f9fbec18Smcpowers 	void *extra2;
201f9fbec18Smcpowers 	void (*extra_free) (ECGroup *group);
202f9fbec18Smcpowers };
203f9fbec18Smcpowers 
204f9fbec18Smcpowers /* Wrapper functions for generic prime field arithmetic. */
205f9fbec18Smcpowers mp_err ec_GFp_add(const mp_int *a, const mp_int *b, mp_int *r,
206f9fbec18Smcpowers 				  const GFMethod *meth);
207f9fbec18Smcpowers mp_err ec_GFp_neg(const mp_int *a, mp_int *r, const GFMethod *meth);
208f9fbec18Smcpowers mp_err ec_GFp_sub(const mp_int *a, const mp_int *b, mp_int *r,
209f9fbec18Smcpowers 				  const GFMethod *meth);
210f9fbec18Smcpowers 
211f9fbec18Smcpowers /* fixed length in-line adds. Count is in words */
212f9fbec18Smcpowers mp_err ec_GFp_add_3(const mp_int *a, const mp_int *b, mp_int *r,
213f9fbec18Smcpowers 				  const GFMethod *meth);
214f9fbec18Smcpowers mp_err ec_GFp_add_4(const mp_int *a, const mp_int *b, mp_int *r,
215f9fbec18Smcpowers 				  const GFMethod *meth);
216f9fbec18Smcpowers mp_err ec_GFp_add_5(const mp_int *a, const mp_int *b, mp_int *r,
217f9fbec18Smcpowers 				  const GFMethod *meth);
218f9fbec18Smcpowers mp_err ec_GFp_add_6(const mp_int *a, const mp_int *b, mp_int *r,
219f9fbec18Smcpowers 				  const GFMethod *meth);
220f9fbec18Smcpowers mp_err ec_GFp_sub_3(const mp_int *a, const mp_int *b, mp_int *r,
221f9fbec18Smcpowers 				  const GFMethod *meth);
222f9fbec18Smcpowers mp_err ec_GFp_sub_4(const mp_int *a, const mp_int *b, mp_int *r,
223f9fbec18Smcpowers 				  const GFMethod *meth);
224f9fbec18Smcpowers mp_err ec_GFp_sub_5(const mp_int *a, const mp_int *b, mp_int *r,
225f9fbec18Smcpowers 				  const GFMethod *meth);
226f9fbec18Smcpowers mp_err ec_GFp_sub_6(const mp_int *a, const mp_int *b, mp_int *r,
227f9fbec18Smcpowers 				  const GFMethod *meth);
228f9fbec18Smcpowers 
229f9fbec18Smcpowers mp_err ec_GFp_mod(const mp_int *a, mp_int *r, const GFMethod *meth);
230f9fbec18Smcpowers mp_err ec_GFp_mul(const mp_int *a, const mp_int *b, mp_int *r,
231f9fbec18Smcpowers 				  const GFMethod *meth);
232f9fbec18Smcpowers mp_err ec_GFp_sqr(const mp_int *a, mp_int *r, const GFMethod *meth);
233f9fbec18Smcpowers mp_err ec_GFp_div(const mp_int *a, const mp_int *b, mp_int *r,
234f9fbec18Smcpowers 				  const GFMethod *meth);
235f9fbec18Smcpowers /* Wrapper functions for generic binary polynomial field arithmetic. */
236f9fbec18Smcpowers mp_err ec_GF2m_add(const mp_int *a, const mp_int *b, mp_int *r,
237f9fbec18Smcpowers 				   const GFMethod *meth);
238f9fbec18Smcpowers mp_err ec_GF2m_neg(const mp_int *a, mp_int *r, const GFMethod *meth);
239f9fbec18Smcpowers mp_err ec_GF2m_mod(const mp_int *a, mp_int *r, const GFMethod *meth);
240f9fbec18Smcpowers mp_err ec_GF2m_mul(const mp_int *a, const mp_int *b, mp_int *r,
241f9fbec18Smcpowers 				   const GFMethod *meth);
242f9fbec18Smcpowers mp_err ec_GF2m_sqr(const mp_int *a, mp_int *r, const GFMethod *meth);
243f9fbec18Smcpowers mp_err ec_GF2m_div(const mp_int *a, const mp_int *b, mp_int *r,
244f9fbec18Smcpowers 				   const GFMethod *meth);
245f9fbec18Smcpowers 
246f9fbec18Smcpowers /* Montgomery prime field arithmetic. */
247f9fbec18Smcpowers mp_err ec_GFp_mul_mont(const mp_int *a, const mp_int *b, mp_int *r,
248f9fbec18Smcpowers 					   const GFMethod *meth);
249f9fbec18Smcpowers mp_err ec_GFp_sqr_mont(const mp_int *a, mp_int *r, const GFMethod *meth);
250f9fbec18Smcpowers mp_err ec_GFp_div_mont(const mp_int *a, const mp_int *b, mp_int *r,
251f9fbec18Smcpowers 					   const GFMethod *meth);
252f9fbec18Smcpowers mp_err ec_GFp_enc_mont(const mp_int *a, mp_int *r, const GFMethod *meth);
253f9fbec18Smcpowers mp_err ec_GFp_dec_mont(const mp_int *a, mp_int *r, const GFMethod *meth);
254f9fbec18Smcpowers void ec_GFp_extra_free_mont(GFMethod *meth);
255f9fbec18Smcpowers 
256f9fbec18Smcpowers /* point multiplication */
257f9fbec18Smcpowers mp_err ec_pts_mul_basic(const mp_int *k1, const mp_int *k2,
258f9fbec18Smcpowers 						const mp_int *px, const mp_int *py, mp_int *rx,
259f9fbec18Smcpowers 						mp_int *ry, const ECGroup *group);
260f9fbec18Smcpowers mp_err ec_pts_mul_simul_w2(const mp_int *k1, const mp_int *k2,
261f9fbec18Smcpowers 						   const mp_int *px, const mp_int *py, mp_int *rx,
262f9fbec18Smcpowers 						   mp_int *ry, const ECGroup *group);
263f9fbec18Smcpowers 
264f9fbec18Smcpowers /* Computes the windowed non-adjacent-form (NAF) of a scalar. Out should
265*c40a6cd7SToomas Soome  * be an array of signed char's to output to, bitsize should be the number
266f9fbec18Smcpowers  * of bits of out, in is the original scalar, and w is the window size.
267f9fbec18Smcpowers  * NAF is discussed in the paper: D. Hankerson, J. Hernandez and A.
268f9fbec18Smcpowers  * Menezes, "Software implementation of elliptic curve cryptography over
269f9fbec18Smcpowers  * binary fields", Proc. CHES 2000. */
270f9fbec18Smcpowers mp_err ec_compute_wNAF(signed char *out, int bitsize, const mp_int *in,
271f9fbec18Smcpowers 					   int w);
272f9fbec18Smcpowers 
273f9fbec18Smcpowers /* Optimized field arithmetic */
274f9fbec18Smcpowers mp_err ec_group_set_gfp192(ECGroup *group, ECCurveName);
275f9fbec18Smcpowers mp_err ec_group_set_gfp224(ECGroup *group, ECCurveName);
276f9fbec18Smcpowers mp_err ec_group_set_gfp256(ECGroup *group, ECCurveName);
277f9fbec18Smcpowers mp_err ec_group_set_gfp384(ECGroup *group, ECCurveName);
278f9fbec18Smcpowers mp_err ec_group_set_gfp521(ECGroup *group, ECCurveName);
279f9fbec18Smcpowers mp_err ec_group_set_gf2m163(ECGroup *group, ECCurveName name);
280f9fbec18Smcpowers mp_err ec_group_set_gf2m193(ECGroup *group, ECCurveName name);
281f9fbec18Smcpowers mp_err ec_group_set_gf2m233(ECGroup *group, ECCurveName name);
282f9fbec18Smcpowers 
283f9fbec18Smcpowers /* Optimized floating-point arithmetic */
284f9fbec18Smcpowers #ifdef ECL_USE_FP
285f9fbec18Smcpowers mp_err ec_group_set_secp160r1_fp(ECGroup *group);
286f9fbec18Smcpowers mp_err ec_group_set_nistp192_fp(ECGroup *group);
287f9fbec18Smcpowers mp_err ec_group_set_nistp224_fp(ECGroup *group);
288f9fbec18Smcpowers #endif
289f9fbec18Smcpowers 
290f9fbec18Smcpowers #endif /* _ECL_PRIV_H */
291