xref: /onnv-gate/usr/src/common/openssl/crypto/ec/ecp_mont.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /* crypto/ec/ecp_mont.c */
2*0Sstevel@tonic-gate /* ====================================================================
3*0Sstevel@tonic-gate  * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
4*0Sstevel@tonic-gate  *
5*0Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
6*0Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
7*0Sstevel@tonic-gate  * are met:
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
10*0Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
11*0Sstevel@tonic-gate  *
12*0Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
13*0Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
14*0Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
15*0Sstevel@tonic-gate  *    distribution.
16*0Sstevel@tonic-gate  *
17*0Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this
18*0Sstevel@tonic-gate  *    software must display the following acknowledgment:
19*0Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
20*0Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
21*0Sstevel@tonic-gate  *
22*0Sstevel@tonic-gate  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23*0Sstevel@tonic-gate  *    endorse or promote products derived from this software without
24*0Sstevel@tonic-gate  *    prior written permission. For written permission, please contact
25*0Sstevel@tonic-gate  *    openssl-core@openssl.org.
26*0Sstevel@tonic-gate  *
27*0Sstevel@tonic-gate  * 5. Products derived from this software may not be called "OpenSSL"
28*0Sstevel@tonic-gate  *    nor may "OpenSSL" appear in their names without prior written
29*0Sstevel@tonic-gate  *    permission of the OpenSSL Project.
30*0Sstevel@tonic-gate  *
31*0Sstevel@tonic-gate  * 6. Redistributions of any form whatsoever must retain the following
32*0Sstevel@tonic-gate  *    acknowledgment:
33*0Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
34*0Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
35*0Sstevel@tonic-gate  *
36*0Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37*0Sstevel@tonic-gate  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38*0Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39*0Sstevel@tonic-gate  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40*0Sstevel@tonic-gate  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41*0Sstevel@tonic-gate  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42*0Sstevel@tonic-gate  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43*0Sstevel@tonic-gate  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44*0Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45*0Sstevel@tonic-gate  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46*0Sstevel@tonic-gate  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47*0Sstevel@tonic-gate  * OF THE POSSIBILITY OF SUCH DAMAGE.
48*0Sstevel@tonic-gate  * ====================================================================
49*0Sstevel@tonic-gate  *
50*0Sstevel@tonic-gate  * This product includes cryptographic software written by Eric Young
51*0Sstevel@tonic-gate  * (eay@cryptsoft.com).  This product includes software written by Tim
52*0Sstevel@tonic-gate  * Hudson (tjh@cryptsoft.com).
53*0Sstevel@tonic-gate  *
54*0Sstevel@tonic-gate  */
55*0Sstevel@tonic-gate 
56*0Sstevel@tonic-gate #include <openssl/err.h>
57*0Sstevel@tonic-gate 
58*0Sstevel@tonic-gate #include "ec_lcl.h"
59*0Sstevel@tonic-gate 
60*0Sstevel@tonic-gate 
61*0Sstevel@tonic-gate const EC_METHOD *EC_GFp_mont_method(void)
62*0Sstevel@tonic-gate 	{
63*0Sstevel@tonic-gate 	static const EC_METHOD ret = {
64*0Sstevel@tonic-gate 		ec_GFp_mont_group_init,
65*0Sstevel@tonic-gate 		ec_GFp_mont_group_finish,
66*0Sstevel@tonic-gate 		ec_GFp_mont_group_clear_finish,
67*0Sstevel@tonic-gate 		ec_GFp_mont_group_copy,
68*0Sstevel@tonic-gate 		ec_GFp_mont_group_set_curve_GFp,
69*0Sstevel@tonic-gate 		ec_GFp_simple_group_get_curve_GFp,
70*0Sstevel@tonic-gate 		ec_GFp_simple_group_set_generator,
71*0Sstevel@tonic-gate 		ec_GFp_simple_group_get0_generator,
72*0Sstevel@tonic-gate 		ec_GFp_simple_group_get_order,
73*0Sstevel@tonic-gate 		ec_GFp_simple_group_get_cofactor,
74*0Sstevel@tonic-gate 		ec_GFp_simple_point_init,
75*0Sstevel@tonic-gate 		ec_GFp_simple_point_finish,
76*0Sstevel@tonic-gate 		ec_GFp_simple_point_clear_finish,
77*0Sstevel@tonic-gate 		ec_GFp_simple_point_copy,
78*0Sstevel@tonic-gate 		ec_GFp_simple_point_set_to_infinity,
79*0Sstevel@tonic-gate 		ec_GFp_simple_set_Jprojective_coordinates_GFp,
80*0Sstevel@tonic-gate 		ec_GFp_simple_get_Jprojective_coordinates_GFp,
81*0Sstevel@tonic-gate 		ec_GFp_simple_point_set_affine_coordinates_GFp,
82*0Sstevel@tonic-gate 		ec_GFp_simple_point_get_affine_coordinates_GFp,
83*0Sstevel@tonic-gate 		ec_GFp_simple_set_compressed_coordinates_GFp,
84*0Sstevel@tonic-gate 		ec_GFp_simple_point2oct,
85*0Sstevel@tonic-gate 		ec_GFp_simple_oct2point,
86*0Sstevel@tonic-gate 		ec_GFp_simple_add,
87*0Sstevel@tonic-gate 		ec_GFp_simple_dbl,
88*0Sstevel@tonic-gate 		ec_GFp_simple_invert,
89*0Sstevel@tonic-gate 		ec_GFp_simple_is_at_infinity,
90*0Sstevel@tonic-gate 		ec_GFp_simple_is_on_curve,
91*0Sstevel@tonic-gate 		ec_GFp_simple_cmp,
92*0Sstevel@tonic-gate 		ec_GFp_simple_make_affine,
93*0Sstevel@tonic-gate 		ec_GFp_simple_points_make_affine,
94*0Sstevel@tonic-gate 		ec_GFp_mont_field_mul,
95*0Sstevel@tonic-gate 		ec_GFp_mont_field_sqr,
96*0Sstevel@tonic-gate 		ec_GFp_mont_field_encode,
97*0Sstevel@tonic-gate 		ec_GFp_mont_field_decode,
98*0Sstevel@tonic-gate 		ec_GFp_mont_field_set_to_one };
99*0Sstevel@tonic-gate 
100*0Sstevel@tonic-gate 	return &ret;
101*0Sstevel@tonic-gate 	}
102*0Sstevel@tonic-gate 
103*0Sstevel@tonic-gate 
104*0Sstevel@tonic-gate int ec_GFp_mont_group_init(EC_GROUP *group)
105*0Sstevel@tonic-gate 	{
106*0Sstevel@tonic-gate 	int ok;
107*0Sstevel@tonic-gate 
108*0Sstevel@tonic-gate 	ok = ec_GFp_simple_group_init(group);
109*0Sstevel@tonic-gate 	group->field_data1 = NULL;
110*0Sstevel@tonic-gate 	group->field_data2 = NULL;
111*0Sstevel@tonic-gate 	return ok;
112*0Sstevel@tonic-gate 	}
113*0Sstevel@tonic-gate 
114*0Sstevel@tonic-gate 
115*0Sstevel@tonic-gate int ec_GFp_mont_group_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
116*0Sstevel@tonic-gate 	{
117*0Sstevel@tonic-gate 	BN_CTX *new_ctx = NULL;
118*0Sstevel@tonic-gate 	BN_MONT_CTX *mont = NULL;
119*0Sstevel@tonic-gate 	BIGNUM *one = NULL;
120*0Sstevel@tonic-gate 	int ret = 0;
121*0Sstevel@tonic-gate 
122*0Sstevel@tonic-gate 	if (group->field_data1 != NULL)
123*0Sstevel@tonic-gate 		{
124*0Sstevel@tonic-gate 		BN_MONT_CTX_free(group->field_data1);
125*0Sstevel@tonic-gate 		group->field_data1 = NULL;
126*0Sstevel@tonic-gate 		}
127*0Sstevel@tonic-gate 	if (group->field_data2 != NULL)
128*0Sstevel@tonic-gate 		{
129*0Sstevel@tonic-gate 		BN_free(group->field_data2);
130*0Sstevel@tonic-gate 		group->field_data2 = NULL;
131*0Sstevel@tonic-gate 		}
132*0Sstevel@tonic-gate 
133*0Sstevel@tonic-gate 	if (ctx == NULL)
134*0Sstevel@tonic-gate 		{
135*0Sstevel@tonic-gate 		ctx = new_ctx = BN_CTX_new();
136*0Sstevel@tonic-gate 		if (ctx == NULL)
137*0Sstevel@tonic-gate 			return 0;
138*0Sstevel@tonic-gate 		}
139*0Sstevel@tonic-gate 
140*0Sstevel@tonic-gate 	mont = BN_MONT_CTX_new();
141*0Sstevel@tonic-gate 	if (mont == NULL) goto err;
142*0Sstevel@tonic-gate 	if (!BN_MONT_CTX_set(mont, p, ctx))
143*0Sstevel@tonic-gate 		{
144*0Sstevel@tonic-gate 		ECerr(EC_F_GFP_MONT_GROUP_SET_CURVE_GFP, ERR_R_BN_LIB);
145*0Sstevel@tonic-gate 		goto err;
146*0Sstevel@tonic-gate 		}
147*0Sstevel@tonic-gate 	one = BN_new();
148*0Sstevel@tonic-gate 	if (one == NULL) goto err;
149*0Sstevel@tonic-gate 	if (!BN_to_montgomery(one, BN_value_one(), mont, ctx)) goto err;
150*0Sstevel@tonic-gate 
151*0Sstevel@tonic-gate 	group->field_data1 = mont;
152*0Sstevel@tonic-gate 	mont = NULL;
153*0Sstevel@tonic-gate 	group->field_data2 = one;
154*0Sstevel@tonic-gate 	one = NULL;
155*0Sstevel@tonic-gate 
156*0Sstevel@tonic-gate 	ret = ec_GFp_simple_group_set_curve_GFp(group, p, a, b, ctx);
157*0Sstevel@tonic-gate 
158*0Sstevel@tonic-gate 	if (!ret)
159*0Sstevel@tonic-gate 		{
160*0Sstevel@tonic-gate 		BN_MONT_CTX_free(group->field_data1);
161*0Sstevel@tonic-gate 		group->field_data1 = NULL;
162*0Sstevel@tonic-gate 		BN_free(group->field_data2);
163*0Sstevel@tonic-gate 		group->field_data2 = NULL;
164*0Sstevel@tonic-gate 		}
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate  err:
167*0Sstevel@tonic-gate 	if (new_ctx != NULL)
168*0Sstevel@tonic-gate 		BN_CTX_free(new_ctx);
169*0Sstevel@tonic-gate 	if (mont != NULL)
170*0Sstevel@tonic-gate 		BN_MONT_CTX_free(mont);
171*0Sstevel@tonic-gate 	return ret;
172*0Sstevel@tonic-gate 	}
173*0Sstevel@tonic-gate 
174*0Sstevel@tonic-gate 
175*0Sstevel@tonic-gate void ec_GFp_mont_group_finish(EC_GROUP *group)
176*0Sstevel@tonic-gate 	{
177*0Sstevel@tonic-gate 	if (group->field_data1 != NULL)
178*0Sstevel@tonic-gate 		{
179*0Sstevel@tonic-gate 		BN_MONT_CTX_free(group->field_data1);
180*0Sstevel@tonic-gate 		group->field_data1 = NULL;
181*0Sstevel@tonic-gate 		}
182*0Sstevel@tonic-gate 	if (group->field_data2 != NULL)
183*0Sstevel@tonic-gate 		{
184*0Sstevel@tonic-gate 		BN_free(group->field_data2);
185*0Sstevel@tonic-gate 		group->field_data2 = NULL;
186*0Sstevel@tonic-gate 		}
187*0Sstevel@tonic-gate 	ec_GFp_simple_group_finish(group);
188*0Sstevel@tonic-gate 	}
189*0Sstevel@tonic-gate 
190*0Sstevel@tonic-gate 
191*0Sstevel@tonic-gate void ec_GFp_mont_group_clear_finish(EC_GROUP *group)
192*0Sstevel@tonic-gate 	{
193*0Sstevel@tonic-gate 	if (group->field_data1 != NULL)
194*0Sstevel@tonic-gate 		{
195*0Sstevel@tonic-gate 		BN_MONT_CTX_free(group->field_data1);
196*0Sstevel@tonic-gate 		group->field_data1 = NULL;
197*0Sstevel@tonic-gate 		}
198*0Sstevel@tonic-gate 	if (group->field_data2 != NULL)
199*0Sstevel@tonic-gate 		{
200*0Sstevel@tonic-gate 		BN_clear_free(group->field_data2);
201*0Sstevel@tonic-gate 		group->field_data2 = NULL;
202*0Sstevel@tonic-gate 		}
203*0Sstevel@tonic-gate 	ec_GFp_simple_group_clear_finish(group);
204*0Sstevel@tonic-gate 	}
205*0Sstevel@tonic-gate 
206*0Sstevel@tonic-gate 
207*0Sstevel@tonic-gate int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src)
208*0Sstevel@tonic-gate 	{
209*0Sstevel@tonic-gate 	if (dest->field_data1 != NULL)
210*0Sstevel@tonic-gate 		{
211*0Sstevel@tonic-gate 		BN_MONT_CTX_free(dest->field_data1);
212*0Sstevel@tonic-gate 		dest->field_data1 = NULL;
213*0Sstevel@tonic-gate 		}
214*0Sstevel@tonic-gate 	if (dest->field_data2 != NULL)
215*0Sstevel@tonic-gate 		{
216*0Sstevel@tonic-gate 		BN_clear_free(dest->field_data2);
217*0Sstevel@tonic-gate 		dest->field_data2 = NULL;
218*0Sstevel@tonic-gate 		}
219*0Sstevel@tonic-gate 
220*0Sstevel@tonic-gate 	if (!ec_GFp_simple_group_copy(dest, src)) return 0;
221*0Sstevel@tonic-gate 
222*0Sstevel@tonic-gate 	if (src->field_data1 != NULL)
223*0Sstevel@tonic-gate 		{
224*0Sstevel@tonic-gate 		dest->field_data1 = BN_MONT_CTX_new();
225*0Sstevel@tonic-gate 		if (dest->field_data1 == NULL) return 0;
226*0Sstevel@tonic-gate 		if (!BN_MONT_CTX_copy(dest->field_data1, src->field_data1)) goto err;
227*0Sstevel@tonic-gate 		}
228*0Sstevel@tonic-gate 	if (src->field_data2 != NULL)
229*0Sstevel@tonic-gate 		{
230*0Sstevel@tonic-gate 		dest->field_data2 = BN_dup(src->field_data2);
231*0Sstevel@tonic-gate 		if (dest->field_data2 == NULL) goto err;
232*0Sstevel@tonic-gate 		}
233*0Sstevel@tonic-gate 
234*0Sstevel@tonic-gate 	return 1;
235*0Sstevel@tonic-gate 
236*0Sstevel@tonic-gate  err:
237*0Sstevel@tonic-gate 	if (dest->field_data1 != NULL)
238*0Sstevel@tonic-gate 		{
239*0Sstevel@tonic-gate 		BN_MONT_CTX_free(dest->field_data1);
240*0Sstevel@tonic-gate 		dest->field_data1 = NULL;
241*0Sstevel@tonic-gate 		}
242*0Sstevel@tonic-gate 	return 0;
243*0Sstevel@tonic-gate 	}
244*0Sstevel@tonic-gate 
245*0Sstevel@tonic-gate 
246*0Sstevel@tonic-gate int ec_GFp_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
247*0Sstevel@tonic-gate 	{
248*0Sstevel@tonic-gate 	if (group->field_data1 == NULL)
249*0Sstevel@tonic-gate 		{
250*0Sstevel@tonic-gate 		ECerr(EC_F_EC_GFP_MONT_FIELD_MUL, EC_R_NOT_INITIALIZED);
251*0Sstevel@tonic-gate 		return 0;
252*0Sstevel@tonic-gate 		}
253*0Sstevel@tonic-gate 
254*0Sstevel@tonic-gate 	return BN_mod_mul_montgomery(r, a, b, group->field_data1, ctx);
255*0Sstevel@tonic-gate 	}
256*0Sstevel@tonic-gate 
257*0Sstevel@tonic-gate 
258*0Sstevel@tonic-gate int ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
259*0Sstevel@tonic-gate 	{
260*0Sstevel@tonic-gate 	if (group->field_data1 == NULL)
261*0Sstevel@tonic-gate 		{
262*0Sstevel@tonic-gate 		ECerr(EC_F_EC_GFP_MONT_FIELD_SQR, EC_R_NOT_INITIALIZED);
263*0Sstevel@tonic-gate 		return 0;
264*0Sstevel@tonic-gate 		}
265*0Sstevel@tonic-gate 
266*0Sstevel@tonic-gate 	return BN_mod_mul_montgomery(r, a, a, group->field_data1, ctx);
267*0Sstevel@tonic-gate 	}
268*0Sstevel@tonic-gate 
269*0Sstevel@tonic-gate 
270*0Sstevel@tonic-gate int ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
271*0Sstevel@tonic-gate 	{
272*0Sstevel@tonic-gate 	if (group->field_data1 == NULL)
273*0Sstevel@tonic-gate 		{
274*0Sstevel@tonic-gate 		ECerr(EC_F_EC_GFP_MONT_FIELD_ENCODE, EC_R_NOT_INITIALIZED);
275*0Sstevel@tonic-gate 		return 0;
276*0Sstevel@tonic-gate 		}
277*0Sstevel@tonic-gate 
278*0Sstevel@tonic-gate 	return BN_to_montgomery(r, a, (BN_MONT_CTX *)group->field_data1, ctx);
279*0Sstevel@tonic-gate 	}
280*0Sstevel@tonic-gate 
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate int ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
283*0Sstevel@tonic-gate 	{
284*0Sstevel@tonic-gate 	if (group->field_data1 == NULL)
285*0Sstevel@tonic-gate 		{
286*0Sstevel@tonic-gate 		ECerr(EC_F_EC_GFP_MONT_FIELD_DECODE, EC_R_NOT_INITIALIZED);
287*0Sstevel@tonic-gate 		return 0;
288*0Sstevel@tonic-gate 		}
289*0Sstevel@tonic-gate 
290*0Sstevel@tonic-gate 	return BN_from_montgomery(r, a, group->field_data1, ctx);
291*0Sstevel@tonic-gate 	}
292*0Sstevel@tonic-gate 
293*0Sstevel@tonic-gate 
294*0Sstevel@tonic-gate int ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r, BN_CTX *ctx)
295*0Sstevel@tonic-gate 	{
296*0Sstevel@tonic-gate 	if (group->field_data2 == NULL)
297*0Sstevel@tonic-gate 		{
298*0Sstevel@tonic-gate 		ECerr(EC_F_EC_GFP_MONT_FIELD_DECODE, EC_R_NOT_INITIALIZED);
299*0Sstevel@tonic-gate 		return 0;
300*0Sstevel@tonic-gate 		}
301*0Sstevel@tonic-gate 
302*0Sstevel@tonic-gate 	if (!BN_copy(r, group->field_data2)) return 0;
303*0Sstevel@tonic-gate 	return 1;
304*0Sstevel@tonic-gate 	}
305