1656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* crypto/ec/ecp_smpl.c */
2656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de>
3656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * for the OpenSSL project.
4656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Includes code written by Bodo Moeller for the OpenSSL project.
5656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project*/
6656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* ====================================================================
7656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
8656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
9656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Redistribution and use in source and binary forms, with or without
10656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * modification, are permitted provided that the following conditions
11656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * are met:
12656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
13656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 1. Redistributions of source code must retain the above copyright
14656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    notice, this list of conditions and the following disclaimer.
15656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
16656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
17656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    notice, this list of conditions and the following disclaimer in
18656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    the documentation and/or other materials provided with the
19656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    distribution.
20656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
21656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 3. All advertising materials mentioning features or use of this
22656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    software must display the following acknowledgment:
23656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    "This product includes software developed by the OpenSSL Project
24656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
25656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
26656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    endorse or promote products derived from this software without
28656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    prior written permission. For written permission, please contact
29656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    openssl-core@openssl.org.
30656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
31656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 5. Products derived from this software may not be called "OpenSSL"
32656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    nor may "OpenSSL" appear in their names without prior written
33656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    permission of the OpenSSL Project.
34656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
35656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * 6. Redistributions of any form whatsoever must retain the following
36656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    acknowledgment:
37656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    "This product includes software developed by the OpenSSL Project
38656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
39656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
40656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * OF THE POSSIBILITY OF SUCH DAMAGE.
52656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * ====================================================================
53656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
54656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * This product includes cryptographic software written by Eric Young
55656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * (eay@cryptsoft.com).  This product includes software written by Tim
56656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Hudson (tjh@cryptsoft.com).
57656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project *
58656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
59656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* ====================================================================
60656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
61656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Portions of this software developed by SUN MICROSYSTEMS, INC.,
62656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * and contributed to the OpenSSL project.
63656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
64656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
65656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include <openssl/err.h>
66656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include <openssl/symhacks.h>
67656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
68392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef OPENSSL_FIPS
69392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#include <openssl/fips.h>
70392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
71392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
72656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project#include "ec_lcl.h"
73656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
74656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectconst EC_METHOD *EC_GFp_simple_method(void)
75656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
76656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	static const EC_METHOD ret = {
77392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		EC_FLAGS_DEFAULT_OCT,
78656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		NID_X9_62_prime_field,
79656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_group_init,
80656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_group_finish,
81656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_group_clear_finish,
82656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_group_copy,
83656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_group_set_curve,
84656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_group_get_curve,
85656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_group_get_degree,
86656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_group_check_discriminant,
87656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_point_init,
88656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_point_finish,
89656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_point_clear_finish,
90656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_point_copy,
91656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_point_set_to_infinity,
92656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_set_Jprojective_coordinates_GFp,
93656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_get_Jprojective_coordinates_GFp,
94656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_point_set_affine_coordinates,
95656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_point_get_affine_coordinates,
96392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		0,0,0,
97656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_add,
98656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_dbl,
99656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_invert,
100656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_is_at_infinity,
101656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_is_on_curve,
102656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_cmp,
103656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_make_affine,
104656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_points_make_affine,
105656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		0 /* mul */,
106656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		0 /* precompute_mult */,
107656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		0 /* have_precompute_mult */,
108656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_field_mul,
109656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ec_GFp_simple_field_sqr,
110656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		0 /* field_div */,
111656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		0 /* field_encode */,
112656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		0 /* field_decode */,
113656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		0 /* field_set_to_one */ };
114656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
115c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root#ifdef OPENSSL_FIPS
116c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root	if (FIPS_mode())
117c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		return fips_ec_gfp_simple_method();
118392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
119c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root
120c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root	return &ret;
121656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
122656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
123656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
124656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project/* Most method functions in this file are designed to work with
125656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * non-trivial representations of field elements if necessary
126656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * (see ecp_mont.c): while standard modular addition and subtraction
127656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * are used, the field_mul and field_sqr methods will be used for
128656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * multiplication, and field_encode and field_decode (if defined)
129656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * will be used for converting between representations.
130656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
131656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * Functions ec_GFp_simple_points_make_affine() and
132656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * ec_GFp_simple_point_get_affine_coordinates() specifically assume
133656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * that if a non-trivial representation is used, it is a Montgomery
134656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project * representation (i.e. 'encoding' means multiplying by some factor R).
135656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project */
136656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
137656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
138656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint ec_GFp_simple_group_init(EC_GROUP *group)
139656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
140656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_init(&group->field);
141656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_init(&group->a);
142656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_init(&group->b);
143656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	group->a_is_minus3 = 0;
144656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return 1;
145656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
146656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
147656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
148656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectvoid ec_GFp_simple_group_finish(EC_GROUP *group)
149656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
150656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_free(&group->field);
151656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_free(&group->a);
152656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_free(&group->b);
153656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
154656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
155656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
156656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectvoid ec_GFp_simple_group_clear_finish(EC_GROUP *group)
157656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
158656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_clear_free(&group->field);
159656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_clear_free(&group->a);
160656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_clear_free(&group->b);
161656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
162656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
163656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
164656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
165656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
166656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_copy(&dest->field, &src->field)) return 0;
167656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_copy(&dest->a, &src->a)) return 0;
168656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_copy(&dest->b, &src->b)) return 0;
169656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
170656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	dest->a_is_minus3 = src->a_is_minus3;
171656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
172656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return 1;
173656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
174656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
175656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
176656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint ec_GFp_simple_group_set_curve(EC_GROUP *group,
177656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
178656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
179656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int ret = 0;
180656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX *new_ctx = NULL;
181656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIGNUM *tmp_a;
182656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
183656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* p must be a prime > 3 */
184656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (BN_num_bits(p) <= 2 || !BN_is_odd(p))
185656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
186656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, EC_R_INVALID_FIELD);
187656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		return 0;
188656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
189656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
190656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (ctx == NULL)
191656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
192656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ctx = new_ctx = BN_CTX_new();
193656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (ctx == NULL)
194656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			return 0;
195656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
196656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
197656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX_start(ctx);
198656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	tmp_a = BN_CTX_get(ctx);
199656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (tmp_a == NULL) goto err;
200656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
201656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* group->field */
202656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_copy(&group->field, p)) goto err;
203656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_set_negative(&group->field, 0);
204656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
205656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* group->a */
206656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_nnmod(tmp_a, a, p, ctx)) goto err;
207656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (group->meth->field_encode)
208656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{ if (!group->meth->field_encode(group, &group->a, tmp_a, ctx)) goto err; }
209656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	else
210656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_copy(&group->a, tmp_a)) goto err;
211656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
212656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* group->b */
213656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_nnmod(&group->b, b, p, ctx)) goto err;
214656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (group->meth->field_encode)
215656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!group->meth->field_encode(group, &group->b, &group->b, ctx)) goto err;
216656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
217656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* group->a_is_minus3 */
218656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_add_word(tmp_a, 3)) goto err;
219656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field));
220656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
221656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	ret = 1;
222656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
223656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project err:
224656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX_end(ctx);
225656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (new_ctx != NULL)
226656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		BN_CTX_free(new_ctx);
227656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return ret;
228656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
229656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
230656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
231656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
232656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
233656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int ret = 0;
234656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX *new_ctx = NULL;
235656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
236656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (p != NULL)
237656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
238656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_copy(p, &group->field)) return 0;
239656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
240656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
241656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (a != NULL || b != NULL)
242656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
243656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (group->meth->field_decode)
244656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
245656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (ctx == NULL)
246656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				{
247656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				ctx = new_ctx = BN_CTX_new();
248656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				if (ctx == NULL)
249656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project					return 0;
250656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				}
251656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (a != NULL)
252656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				{
253656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				if (!group->meth->field_decode(group, a, &group->a, ctx)) goto err;
254656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				}
255656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (b != NULL)
256656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				{
257656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				if (!group->meth->field_decode(group, b, &group->b, ctx)) goto err;
258656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				}
259656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
260656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		else
261656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
262656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (a != NULL)
263656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				{
264656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				if (!BN_copy(a, &group->a)) goto err;
265656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				}
266656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (b != NULL)
267656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				{
268656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				if (!BN_copy(b, &group->b)) goto err;
269656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				}
270656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
271656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
272656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
273656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	ret = 1;
274656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
275656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project err:
276656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (new_ctx)
277656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		BN_CTX_free(new_ctx);
278656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return ret;
279656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
280656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
281656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
282656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint ec_GFp_simple_group_get_degree(const EC_GROUP *group)
283656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
284656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return BN_num_bits(&group->field);
285656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
286656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
287656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
288656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
289656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
290656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int ret = 0;
291656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIGNUM *a,*b,*order,*tmp_1,*tmp_2;
292656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	const BIGNUM *p = &group->field;
293656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX *new_ctx = NULL;
294656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
295656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (ctx == NULL)
296656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
297656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ctx = new_ctx = BN_CTX_new();
298656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (ctx == NULL)
299656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
300656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT, ERR_R_MALLOC_FAILURE);
301656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			goto err;
302656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
303656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
304656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX_start(ctx);
305656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	a = BN_CTX_get(ctx);
306656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	b = BN_CTX_get(ctx);
307656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	tmp_1 = BN_CTX_get(ctx);
308656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	tmp_2 = BN_CTX_get(ctx);
309656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	order = BN_CTX_get(ctx);
310656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (order == NULL) goto err;
311656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
312656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (group->meth->field_decode)
313656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
314656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!group->meth->field_decode(group, a, &group->a, ctx)) goto err;
315656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!group->meth->field_decode(group, b, &group->b, ctx)) goto err;
316656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
317656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	else
318656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
319656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_copy(a, &group->a)) goto err;
320656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_copy(b, &group->b)) goto err;
321656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
322656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
323656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* check the discriminant:
324656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 * y^2 = x^3 + a*x + b is an elliptic curve <=> 4*a^3 + 27*b^2 != 0 (mod p)
325656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project         * 0 =< a, b < p */
326656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (BN_is_zero(a))
327656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
328656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (BN_is_zero(b)) goto err;
329656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
330656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	else if (!BN_is_zero(b))
331656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
332656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_mod_sqr(tmp_1, a, p, ctx)) goto err;
333656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_mod_mul(tmp_2, tmp_1, a, p, ctx)) goto err;
334656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_lshift(tmp_1, tmp_2, 2)) goto err;
335656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* tmp_1 = 4*a^3 */
336656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
337656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_mod_sqr(tmp_2, b, p, ctx)) goto err;
338656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_mul_word(tmp_2, 27)) goto err;
339656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* tmp_2 = 27*b^2 */
340656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
341656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx)) goto err;
342656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (BN_is_zero(a)) goto err;
343656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
344656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	ret = 1;
345656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
346656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projecterr:
347656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (ctx != NULL)
348656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		BN_CTX_end(ctx);
349656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (new_ctx != NULL)
350656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		BN_CTX_free(new_ctx);
351656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return ret;
352656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
353656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
354656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
355656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint ec_GFp_simple_point_init(EC_POINT *point)
356656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
357656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_init(&point->X);
358656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_init(&point->Y);
359656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_init(&point->Z);
360656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	point->Z_is_one = 0;
361656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
362656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return 1;
363656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
364656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
365656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
366656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectvoid ec_GFp_simple_point_finish(EC_POINT *point)
367656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
368656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_free(&point->X);
369656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_free(&point->Y);
370656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_free(&point->Z);
371656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
372656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
373656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
374656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectvoid ec_GFp_simple_point_clear_finish(EC_POINT *point)
375656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
376656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_clear_free(&point->X);
377656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_clear_free(&point->Y);
378656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_clear_free(&point->Z);
379656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	point->Z_is_one = 0;
380656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
381656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
382656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
383656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
384656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
385656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_copy(&dest->X, &src->X)) return 0;
386656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_copy(&dest->Y, &src->Y)) return 0;
387656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_copy(&dest->Z, &src->Z)) return 0;
388656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	dest->Z_is_one = src->Z_is_one;
389656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
390656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return 1;
391656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
392656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
393656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
394656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
395656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
396656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	point->Z_is_one = 0;
397656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_zero(&point->Z);
398656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return 1;
399656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
400656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
401656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
402656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
403656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx)
404656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
405656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX *new_ctx = NULL;
406656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int ret = 0;
407656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
408656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (ctx == NULL)
409656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
410656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ctx = new_ctx = BN_CTX_new();
411656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (ctx == NULL)
412656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			return 0;
413656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
414656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
415656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (x != NULL)
416656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
417656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_nnmod(&point->X, x, &group->field, ctx)) goto err;
418656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (group->meth->field_encode)
419656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
420656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (!group->meth->field_encode(group, &point->X, &point->X, ctx)) goto err;
421656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
422656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
423656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
424656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (y != NULL)
425656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
426656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_nnmod(&point->Y, y, &group->field, ctx)) goto err;
427656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (group->meth->field_encode)
428656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
429656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (!group->meth->field_encode(group, &point->Y, &point->Y, ctx)) goto err;
430656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
431656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
432656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
433656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (z != NULL)
434656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
435656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		int Z_is_one;
436656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
437656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_nnmod(&point->Z, z, &group->field, ctx)) goto err;
438656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		Z_is_one = BN_is_one(&point->Z);
439656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (group->meth->field_encode)
440656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
441656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (Z_is_one && (group->meth->field_set_to_one != 0))
442656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				{
443656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				if (!group->meth->field_set_to_one(group, &point->Z, ctx)) goto err;
444656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				}
445656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			else
446656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				{
447656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				if (!group->meth->field_encode(group, &point->Z, &point->Z, ctx)) goto err;
448656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				}
449656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
450656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		point->Z_is_one = Z_is_one;
451656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
452656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
453656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	ret = 1;
454656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
455656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project err:
456656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (new_ctx != NULL)
457656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		BN_CTX_free(new_ctx);
458656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return ret;
459656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
460656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
461656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
462656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
463656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx)
464656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
465656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX *new_ctx = NULL;
466656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int ret = 0;
467656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
468656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (group->meth->field_decode != 0)
469656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
470656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (ctx == NULL)
471656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
472656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			ctx = new_ctx = BN_CTX_new();
473656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (ctx == NULL)
474656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				return 0;
475656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
476656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
477656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (x != NULL)
478656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
479656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (!group->meth->field_decode(group, x, &point->X, ctx)) goto err;
480656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
481656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (y != NULL)
482656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
483656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (!group->meth->field_decode(group, y, &point->Y, ctx)) goto err;
484656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
485656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (z != NULL)
486656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
487656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (!group->meth->field_decode(group, z, &point->Z, ctx)) goto err;
488656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
489656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
490656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	else
491656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
492656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (x != NULL)
493656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
494656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (!BN_copy(x, &point->X)) goto err;
495656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
496656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (y != NULL)
497656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
498656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (!BN_copy(y, &point->Y)) goto err;
499656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
500656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (z != NULL)
501656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
502656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (!BN_copy(z, &point->Z)) goto err;
503656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
504656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
505656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
506656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	ret = 1;
507656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
508656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project err:
509656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (new_ctx != NULL)
510656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		BN_CTX_free(new_ctx);
511656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return ret;
512656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
513656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
514656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
515656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
516656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
517656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
518656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (x == NULL || y == NULL)
519656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
520656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* unlike for projective coordinates, we do not tolerate this */
521656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ECerr(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER);
522656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		return 0;
523656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
524656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
525656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return EC_POINT_set_Jprojective_coordinates_GFp(group, point, x, y, BN_value_one(), ctx);
526656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
527656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
528656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
529656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point,
530656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
531656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
532656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX *new_ctx = NULL;
533656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIGNUM *Z, *Z_1, *Z_2, *Z_3;
534656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	const BIGNUM *Z_;
535656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int ret = 0;
536656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
537656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (EC_POINT_is_at_infinity(group, point))
538656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
539656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY);
540656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		return 0;
541656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
542656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
543656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (ctx == NULL)
544656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
545656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ctx = new_ctx = BN_CTX_new();
546656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (ctx == NULL)
547656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			return 0;
548656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
549656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
550656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX_start(ctx);
551656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	Z = BN_CTX_get(ctx);
552656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	Z_1 = BN_CTX_get(ctx);
553656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	Z_2 = BN_CTX_get(ctx);
554656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	Z_3 = BN_CTX_get(ctx);
555656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (Z_3 == NULL) goto err;
556656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
557656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* transform  (X, Y, Z)  into  (x, y) := (X/Z^2, Y/Z^3) */
558656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
559656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (group->meth->field_decode)
560656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
561656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!group->meth->field_decode(group, Z, &point->Z, ctx)) goto err;
562656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		Z_ = Z;
563656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
564656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	else
565656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
566656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		Z_ = &point->Z;
567656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
568656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
569656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (BN_is_one(Z_))
570656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
571656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (group->meth->field_decode)
572656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
573656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (x != NULL)
574656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				{
575656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				if (!group->meth->field_decode(group, x, &point->X, ctx)) goto err;
576656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				}
577656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (y != NULL)
578656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				{
579656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				if (!group->meth->field_decode(group, y, &point->Y, ctx)) goto err;
580656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				}
581656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
582656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		else
583656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
584656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (x != NULL)
585656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				{
586656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				if (!BN_copy(x, &point->X)) goto err;
587656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				}
588656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (y != NULL)
589656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				{
590656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				if (!BN_copy(y, &point->Y)) goto err;
591656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				}
592656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
593656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
594656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	else
595656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
596656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx))
597656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
598656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_BN_LIB);
599656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			goto err;
600656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
601656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
602656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (group->meth->field_encode == 0)
603656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
604656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			/* field_sqr works on standard representation */
605656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (!group->meth->field_sqr(group, Z_2, Z_1, ctx)) goto err;
606656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
607656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		else
608656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
609656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) goto err;
610656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
611656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
612656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (x != NULL)
613656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
614656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			/* in the Montgomery case, field_mul will cancel out Montgomery factor in X: */
615656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (!group->meth->field_mul(group, x, &point->X, Z_2, ctx)) goto err;
616656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
617656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
618656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (y != NULL)
619656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
620656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (group->meth->field_encode == 0)
621656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				{
622656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				/* field_mul works on standard representation */
623656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) goto err;
624656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				}
625656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			else
626656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				{
627656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) goto err;
628656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				}
629656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
630656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			/* in the Montgomery case, field_mul will cancel out Montgomery factor in Y: */
631656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (!group->meth->field_mul(group, y, &point->Y, Z_3, ctx)) goto err;
632656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
633656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
634656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
635656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	ret = 1;
636656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
637656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project err:
638656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX_end(ctx);
639656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (new_ctx != NULL)
640656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		BN_CTX_free(new_ctx);
641656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return ret;
642656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
643656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
644656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
645656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
646656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
647656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
648656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	const BIGNUM *p;
649656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX *new_ctx = NULL;
650656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6;
651656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int ret = 0;
652656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
653656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (a == b)
654656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		return EC_POINT_dbl(group, r, a, ctx);
655656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (EC_POINT_is_at_infinity(group, a))
656656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		return EC_POINT_copy(r, b);
657656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (EC_POINT_is_at_infinity(group, b))
658656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		return EC_POINT_copy(r, a);
659656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
660656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	field_mul = group->meth->field_mul;
661656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	field_sqr = group->meth->field_sqr;
662656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	p = &group->field;
663656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
664656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (ctx == NULL)
665656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
666656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ctx = new_ctx = BN_CTX_new();
667656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (ctx == NULL)
668656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			return 0;
669656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
670656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
671656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX_start(ctx);
672656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	n0 = BN_CTX_get(ctx);
673656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	n1 = BN_CTX_get(ctx);
674656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	n2 = BN_CTX_get(ctx);
675656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	n3 = BN_CTX_get(ctx);
676656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	n4 = BN_CTX_get(ctx);
677656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	n5 = BN_CTX_get(ctx);
678656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	n6 = BN_CTX_get(ctx);
679656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (n6 == NULL) goto end;
680656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
681656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* Note that in this function we must not read components of 'a' or 'b'
682656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 * once we have written the corresponding components of 'r'.
683656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 * ('r' might be one of 'a' or 'b'.)
684656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 */
685656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
686656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* n1, n2 */
687656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (b->Z_is_one)
688656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
689656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_copy(n1, &a->X)) goto end;
690656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_copy(n2, &a->Y)) goto end;
691656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* n1 = X_a */
692656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* n2 = Y_a */
693656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
694656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	else
695656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
696656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_sqr(group, n0, &b->Z, ctx)) goto end;
697656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_mul(group, n1, &a->X, n0, ctx)) goto end;
698656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* n1 = X_a * Z_b^2 */
699656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
700656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_mul(group, n0, n0, &b->Z, ctx)) goto end;
701656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_mul(group, n2, &a->Y, n0, ctx)) goto end;
702656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* n2 = Y_a * Z_b^3 */
703656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
704656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
705656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* n3, n4 */
706656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (a->Z_is_one)
707656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
708656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_copy(n3, &b->X)) goto end;
709656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_copy(n4, &b->Y)) goto end;
710656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* n3 = X_b */
711656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* n4 = Y_b */
712656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
713656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	else
714656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
715656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_sqr(group, n0, &a->Z, ctx)) goto end;
716656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_mul(group, n3, &b->X, n0, ctx)) goto end;
717656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* n3 = X_b * Z_a^2 */
718656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
719656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_mul(group, n0, n0, &a->Z, ctx)) goto end;
720656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_mul(group, n4, &b->Y, n0, ctx)) goto end;
721656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* n4 = Y_b * Z_a^3 */
722656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
723656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
724656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* n5, n6 */
725656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_mod_sub_quick(n5, n1, n3, p)) goto end;
726656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_mod_sub_quick(n6, n2, n4, p)) goto end;
727656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* n5 = n1 - n3 */
728656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* n6 = n2 - n4 */
729656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
730656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (BN_is_zero(n5))
731656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
732656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (BN_is_zero(n6))
733656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
734656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			/* a is the same point as b */
735656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			BN_CTX_end(ctx);
736656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			ret = EC_POINT_dbl(group, r, a, ctx);
737656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			ctx = NULL;
738656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			goto end;
739656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
740656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		else
741656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
742656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			/* a is the inverse of b */
743656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			BN_zero(&r->Z);
744656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			r->Z_is_one = 0;
745656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			ret = 1;
746656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			goto end;
747656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
748656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
749656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
750656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* 'n7', 'n8' */
751656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_mod_add_quick(n1, n1, n3, p)) goto end;
752656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_mod_add_quick(n2, n2, n4, p)) goto end;
753656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* 'n7' = n1 + n3 */
754656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* 'n8' = n2 + n4 */
755656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
756656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* Z_r */
757656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (a->Z_is_one && b->Z_is_one)
758656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
759656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_copy(&r->Z, n5)) goto end;
760656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
761656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	else
762656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
763656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (a->Z_is_one)
764656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{ if (!BN_copy(n0, &b->Z)) goto end; }
765656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		else if (b->Z_is_one)
766656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{ if (!BN_copy(n0, &a->Z)) goto end; }
767656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		else
768656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{ if (!field_mul(group, n0, &a->Z, &b->Z, ctx)) goto end; }
769656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_mul(group, &r->Z, n0, n5, ctx)) goto end;
770656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
771656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	r->Z_is_one = 0;
772656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* Z_r = Z_a * Z_b * n5 */
773656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
774656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* X_r */
775656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!field_sqr(group, n0, n6, ctx)) goto end;
776656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!field_sqr(group, n4, n5, ctx)) goto end;
777656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!field_mul(group, n3, n1, n4, ctx)) goto end;
778656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_mod_sub_quick(&r->X, n0, n3, p)) goto end;
779656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* X_r = n6^2 - n5^2 * 'n7' */
780656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
781656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* 'n9' */
782656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_mod_lshift1_quick(n0, &r->X, p)) goto end;
783656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_mod_sub_quick(n0, n3, n0, p)) goto end;
784656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* n9 = n5^2 * 'n7' - 2 * X_r */
785656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
786656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* Y_r */
787656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!field_mul(group, n0, n0, n6, ctx)) goto end;
788656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!field_mul(group, n5, n4, n5, ctx)) goto end; /* now n5 is n5^3 */
789656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!field_mul(group, n1, n2, n5, ctx)) goto end;
790656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_mod_sub_quick(n0, n0, n1, p)) goto end;
791656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (BN_is_odd(n0))
792656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_add(n0, n0, p)) goto end;
793656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* now  0 <= n0 < 2*p,  and n0 is even */
794656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_rshift1(&r->Y, n0)) goto end;
795656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */
796656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
797656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	ret = 1;
798656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
799656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project end:
800656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (ctx) /* otherwise we already called BN_CTX_end */
801656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		BN_CTX_end(ctx);
802656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (new_ctx != NULL)
803656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		BN_CTX_free(new_ctx);
804656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return ret;
805656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
806656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
807656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
808656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
809656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
810656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
811656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
812656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	const BIGNUM *p;
813656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX *new_ctx = NULL;
814656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIGNUM *n0, *n1, *n2, *n3;
815656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int ret = 0;
816656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
817656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (EC_POINT_is_at_infinity(group, a))
818656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
819656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		BN_zero(&r->Z);
820656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		r->Z_is_one = 0;
821656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		return 1;
822656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
823656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
824656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	field_mul = group->meth->field_mul;
825656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	field_sqr = group->meth->field_sqr;
826656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	p = &group->field;
827656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
828656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (ctx == NULL)
829656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
830656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ctx = new_ctx = BN_CTX_new();
831656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (ctx == NULL)
832656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			return 0;
833656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
834656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
835656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX_start(ctx);
836656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	n0 = BN_CTX_get(ctx);
837656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	n1 = BN_CTX_get(ctx);
838656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	n2 = BN_CTX_get(ctx);
839656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	n3 = BN_CTX_get(ctx);
840656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (n3 == NULL) goto err;
841656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
842656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* Note that in this function we must not read components of 'a'
843656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 * once we have written the corresponding components of 'r'.
844656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 * ('r' might the same as 'a'.)
845656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 */
846656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
847656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* n1 */
848656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (a->Z_is_one)
849656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
850656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_sqr(group, n0, &a->X, ctx)) goto err;
851656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_mod_lshift1_quick(n1, n0, p)) goto err;
852656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_mod_add_quick(n0, n0, n1, p)) goto err;
853656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_mod_add_quick(n1, n0, &group->a, p)) goto err;
854656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* n1 = 3 * X_a^2 + a_curve */
855656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
856656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	else if (group->a_is_minus3)
857656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
858656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_sqr(group, n1, &a->Z, ctx)) goto err;
859656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_mod_add_quick(n0, &a->X, n1, p)) goto err;
860656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_mod_sub_quick(n2, &a->X, n1, p)) goto err;
861656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_mul(group, n1, n0, n2, ctx)) goto err;
862656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_mod_lshift1_quick(n0, n1, p)) goto err;
863656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_mod_add_quick(n1, n0, n1, p)) goto err;
864656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2)
865656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 *    = 3 * X_a^2 - 3 * Z_a^4 */
866656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
867656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	else
868656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
869656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_sqr(group, n0, &a->X, ctx)) goto err;
870656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_mod_lshift1_quick(n1, n0, p)) goto err;
871656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_mod_add_quick(n0, n0, n1, p)) goto err;
872656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_sqr(group, n1, &a->Z, ctx)) goto err;
873656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_sqr(group, n1, n1, ctx)) goto err;
874656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_mul(group, n1, n1, &group->a, ctx)) goto err;
875656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_mod_add_quick(n1, n1, n0, p)) goto err;
876656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* n1 = 3 * X_a^2 + a_curve * Z_a^4 */
877656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
878656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
879656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* Z_r */
880656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (a->Z_is_one)
881656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
882656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_copy(n0, &a->Y)) goto err;
883656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
884656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	else
885656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
886656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_mul(group, n0, &a->Y, &a->Z, ctx)) goto err;
887656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
888656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_mod_lshift1_quick(&r->Z, n0, p)) goto err;
889656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	r->Z_is_one = 0;
890656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* Z_r = 2 * Y_a * Z_a */
891656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
892656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* n2 */
893656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!field_sqr(group, n3, &a->Y, ctx)) goto err;
894656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!field_mul(group, n2, &a->X, n3, ctx)) goto err;
895656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_mod_lshift_quick(n2, n2, 2, p)) goto err;
896656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* n2 = 4 * X_a * Y_a^2 */
897656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
898656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* X_r */
899656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_mod_lshift1_quick(n0, n2, p)) goto err;
900656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!field_sqr(group, &r->X, n1, ctx)) goto err;
901656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_mod_sub_quick(&r->X, &r->X, n0, p)) goto err;
902656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* X_r = n1^2 - 2 * n2 */
903656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
904656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* n3 */
905656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!field_sqr(group, n0, n3, ctx)) goto err;
906656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_mod_lshift_quick(n3, n0, 3, p)) goto err;
907656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* n3 = 8 * Y_a^4 */
908656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
909656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* Y_r */
910656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_mod_sub_quick(n0, n2, &r->X, p)) goto err;
911656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!field_mul(group, n0, n1, n0, ctx)) goto err;
912656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!BN_mod_sub_quick(&r->Y, n0, n3, p)) goto err;
913656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* Y_r = n1 * (n2 - X_r) - n3 */
914656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
915656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	ret = 1;
916656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
917656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project err:
918656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX_end(ctx);
919656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (new_ctx != NULL)
920656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		BN_CTX_free(new_ctx);
921656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return ret;
922656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
923656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
924656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
925656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
926656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
927656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y))
928656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* point is its own inverse */
929656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		return 1;
930656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
931656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return BN_usub(&point->Y, &group->field, &point->Y);
932656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
933656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
934656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
935656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
936656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
937656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return BN_is_zero(&point->Z);
938656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
939656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
940656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
941656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
942656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
943656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
944656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
945656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	const BIGNUM *p;
946656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX *new_ctx = NULL;
947656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIGNUM *rh, *tmp, *Z4, *Z6;
948656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int ret = -1;
949656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
950656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (EC_POINT_is_at_infinity(group, point))
951656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		return 1;
952656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
953656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	field_mul = group->meth->field_mul;
954656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	field_sqr = group->meth->field_sqr;
955656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	p = &group->field;
956656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
957656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (ctx == NULL)
958656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
959656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ctx = new_ctx = BN_CTX_new();
960656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (ctx == NULL)
961656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			return -1;
962656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
963656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
964656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX_start(ctx);
965656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	rh = BN_CTX_get(ctx);
966656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	tmp = BN_CTX_get(ctx);
967656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	Z4 = BN_CTX_get(ctx);
968656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	Z6 = BN_CTX_get(ctx);
969656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (Z6 == NULL) goto err;
970656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
971656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* We have a curve defined by a Weierstrass equation
972656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 *      y^2 = x^3 + a*x + b.
973656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 * The point to consider is given in Jacobian projective coordinates
974656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 * where  (X, Y, Z)  represents  (x, y) = (X/Z^2, Y/Z^3).
975656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 * Substituting this and multiplying by  Z^6  transforms the above equation into
976656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 *      Y^2 = X^3 + a*X*Z^4 + b*Z^6.
977656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 * To test this, we add up the right-hand side in 'rh'.
978656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 */
979656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
980656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* rh := X^2 */
981656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!field_sqr(group, rh, &point->X, ctx)) goto err;
982656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
983656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!point->Z_is_one)
984656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
985656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_sqr(group, tmp, &point->Z, ctx)) goto err;
986656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_sqr(group, Z4, tmp, ctx)) goto err;
987656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_mul(group, Z6, Z4, tmp, ctx)) goto err;
988656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
989656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* rh := (rh + a*Z^4)*X */
990656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (group->a_is_minus3)
991656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
992656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (!BN_mod_lshift1_quick(tmp, Z4, p)) goto err;
993656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (!BN_mod_add_quick(tmp, tmp, Z4, p)) goto err;
994656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (!BN_mod_sub_quick(rh, rh, tmp, p)) goto err;
995656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
996656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
997656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		else
998656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
999656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (!field_mul(group, tmp, Z4, &group->a, ctx)) goto err;
1000656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (!BN_mod_add_quick(rh, rh, tmp, p)) goto err;
1001656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
1002656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
1003656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1004656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* rh := rh + b*Z^6 */
1005656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_mul(group, tmp, &group->b, Z6, ctx)) goto err;
1006656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_mod_add_quick(rh, rh, tmp, p)) goto err;
1007656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
1008656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	else
1009656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
1010656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* point->Z_is_one */
1011656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1012656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* rh := (rh + a)*X */
1013656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_mod_add_quick(rh, rh, &group->a, p)) goto err;
1014656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
1015656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* rh := rh + b */
1016656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_mod_add_quick(rh, rh, &group->b, p)) goto err;
1017656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
1018656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1019656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* 'lh' := Y^2 */
1020656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!field_sqr(group, tmp, &point->Y, ctx)) goto err;
1021656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1022656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	ret = (0 == BN_ucmp(tmp, rh));
1023656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1024656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project err:
1025656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX_end(ctx);
1026656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (new_ctx != NULL)
1027656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		BN_CTX_free(new_ctx);
1028656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return ret;
1029656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
1030656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1031656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1032656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
1033656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
1034656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* return values:
1035656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 *  -1   error
1036656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 *   0   equal (in affine coordinates)
1037656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 *   1   not equal
1038656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 */
1039656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1040656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
1041656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
1042656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX *new_ctx = NULL;
1043656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIGNUM *tmp1, *tmp2, *Za23, *Zb23;
1044656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	const BIGNUM *tmp1_, *tmp2_;
1045656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int ret = -1;
1046656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1047656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (EC_POINT_is_at_infinity(group, a))
1048656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
1049656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
1050656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
105181c4de7869b646592127e952cda763abf8305069Brian Carlstrom
105281c4de7869b646592127e952cda763abf8305069Brian Carlstrom	if (EC_POINT_is_at_infinity(group, b))
105381c4de7869b646592127e952cda763abf8305069Brian Carlstrom		return 1;
1054656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1055656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (a->Z_is_one && b->Z_is_one)
1056656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
1057656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
1058656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
1059656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1060656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	field_mul = group->meth->field_mul;
1061656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	field_sqr = group->meth->field_sqr;
1062656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1063656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (ctx == NULL)
1064656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
1065656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ctx = new_ctx = BN_CTX_new();
1066656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (ctx == NULL)
1067656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			return -1;
1068656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
1069656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1070656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX_start(ctx);
1071656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	tmp1 = BN_CTX_get(ctx);
1072656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	tmp2 = BN_CTX_get(ctx);
1073656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	Za23 = BN_CTX_get(ctx);
1074656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	Zb23 = BN_CTX_get(ctx);
1075656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (Zb23 == NULL) goto end;
1076656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1077656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* We have to decide whether
1078656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 *     (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2, Y_b/Z_b^3),
1079656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 * or equivalently, whether
1080656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 *     (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3).
1081656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	 */
1082656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1083656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!b->Z_is_one)
1084656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
1085656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_sqr(group, Zb23, &b->Z, ctx)) goto end;
1086656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_mul(group, tmp1, &a->X, Zb23, ctx)) goto end;
1087656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		tmp1_ = tmp1;
1088656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
1089656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	else
1090656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		tmp1_ = &a->X;
1091656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!a->Z_is_one)
1092656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
1093656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_sqr(group, Za23, &a->Z, ctx)) goto end;
1094656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_mul(group, tmp2, &b->X, Za23, ctx)) goto end;
1095656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		tmp2_ = tmp2;
1096656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
1097656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	else
1098656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		tmp2_ = &b->X;
1099656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1100656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* compare  X_a*Z_b^2  with  X_b*Z_a^2 */
1101656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (BN_cmp(tmp1_, tmp2_) != 0)
1102656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
1103656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ret = 1; /* points differ */
1104656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		goto end;
1105656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
1106656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1107656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1108656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!b->Z_is_one)
1109656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
1110656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_mul(group, Zb23, Zb23, &b->Z, ctx)) goto end;
1111656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_mul(group, tmp1, &a->Y, Zb23, ctx)) goto end;
1112656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* tmp1_ = tmp1 */
1113656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
1114656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	else
1115656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		tmp1_ = &a->Y;
1116656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!a->Z_is_one)
1117656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
1118656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_mul(group, Za23, Za23, &a->Z, ctx)) goto end;
1119656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!field_mul(group, tmp2, &b->Y, Za23, ctx)) goto end;
1120656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		/* tmp2_ = tmp2 */
1121656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
1122656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	else
1123656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		tmp2_ = &b->Y;
1124656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1125656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* compare  Y_a*Z_b^3  with  Y_b*Z_a^3 */
1126656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (BN_cmp(tmp1_, tmp2_) != 0)
1127656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
1128656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ret = 1; /* points differ */
1129656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		goto end;
1130656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
1131656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1132656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	/* points are equal */
1133656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	ret = 0;
1134656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1135656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project end:
1136656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX_end(ctx);
1137656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (new_ctx != NULL)
1138656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		BN_CTX_free(new_ctx);
1139656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return ret;
1140656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
1141656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1142656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1143656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
1144656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
1145656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX *new_ctx = NULL;
1146656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BIGNUM *x, *y;
1147656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int ret = 0;
1148656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1149656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
1150656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		return 1;
1151656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1152656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (ctx == NULL)
1153656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
1154656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ctx = new_ctx = BN_CTX_new();
1155656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (ctx == NULL)
1156656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			return 0;
1157656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
1158656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1159656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX_start(ctx);
1160656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	x = BN_CTX_get(ctx);
1161656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	y = BN_CTX_get(ctx);
1162656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (y == NULL) goto err;
1163656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1164656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
1165656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
1166656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (!point->Z_is_one)
1167656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
1168656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ECerr(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE, ERR_R_INTERNAL_ERROR);
1169656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		goto err;
1170656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
1171656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1172656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	ret = 1;
1173656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1174656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project err:
1175656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX_end(ctx);
1176656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (new_ctx != NULL)
1177656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		BN_CTX_free(new_ctx);
1178656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return ret;
1179656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
1180656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1181656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1182656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
1183656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
1184656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX *new_ctx = NULL;
1185c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root	BIGNUM *tmp, *tmp_Z;
1186c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root	BIGNUM **prod_Z = NULL;
1187656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	size_t i;
1188656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	int ret = 0;
1189656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1190656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (num == 0)
1191656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		return 1;
1192656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1193656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (ctx == NULL)
1194656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
1195656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		ctx = new_ctx = BN_CTX_new();
1196656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (ctx == NULL)
1197656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			return 0;
1198656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
1199656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1200656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX_start(ctx);
1201c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root	tmp = BN_CTX_get(ctx);
1202c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root	tmp_Z = BN_CTX_get(ctx);
1203c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root	if (tmp == NULL || tmp_Z == NULL) goto err;
1204656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1205c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root	prod_Z = OPENSSL_malloc(num * sizeof prod_Z[0]);
1206c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root	if (prod_Z == NULL) goto err;
1207c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root	for (i = 0; i < num; i++)
1208c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		{
1209c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		prod_Z[i] = BN_new();
1210c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		if (prod_Z[i] == NULL) goto err;
1211c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		}
1212656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1213c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root	/* Set each prod_Z[i] to the product of points[0]->Z .. points[i]->Z,
1214c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root	 * skipping any zero-valued inputs (pretend that they're 1). */
1215656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1216c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root	if (!BN_is_zero(&points[0]->Z))
1217656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
1218c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		if (!BN_copy(prod_Z[0], &points[0]->Z)) goto err;
1219c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		}
1220c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root	else
1221c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		{
1222c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		if (group->meth->field_set_to_one != 0)
1223656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
1224c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root			if (!group->meth->field_set_to_one(group, prod_Z[0], ctx)) goto err;
1225c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root			}
1226c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		else
1227c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root			{
1228c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root			if (!BN_one(prod_Z[0])) goto err;
1229656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
1230656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
1231656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1232c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root	for (i = 1; i < num; i++)
1233656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
1234c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		if (!BN_is_zero(&points[i]->Z))
1235656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
1236c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root			if (!group->meth->field_mul(group, prod_Z[i], prod_Z[i - 1], &points[i]->Z, ctx)) goto err;
1237c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root			}
1238c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		else
1239c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root			{
1240c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root			if (!BN_copy(prod_Z[i], prod_Z[i - 1])) goto err;
1241656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
1242656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
1243c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root
1244c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root	/* Now use a single explicit inversion to replace every
1245c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root	 * non-zero points[i]->Z by its inverse. */
1246c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root
1247c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root	if (!BN_mod_inverse(tmp, prod_Z[num - 1], &group->field, ctx))
1248c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		{
1249c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		ECerr(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, ERR_R_BN_LIB);
1250c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		goto err;
1251c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		}
1252656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (group->meth->field_encode != 0)
1253656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
1254c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		/* In the Montgomery case, we just turned  R*H  (representing H)
1255656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		 * into  1/(R*H),  but we need  R*(1/H)  (representing 1/H);
1256c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		 * i.e. we need to multiply by the Montgomery factor twice. */
1257c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		if (!group->meth->field_encode(group, tmp, tmp, ctx)) goto err;
1258c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		if (!group->meth->field_encode(group, tmp, tmp, ctx)) goto err;
1259656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
1260656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1261c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root	for (i = num - 1; i > 0; --i)
1262656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
1263c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		/* Loop invariant: tmp is the product of the inverses of
1264c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		 * points[0]->Z .. points[i]->Z (zero-valued inputs skipped). */
1265c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		if (!BN_is_zero(&points[i]->Z))
1266656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
1267c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root			/* Set tmp_Z to the inverse of points[i]->Z (as product
1268c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root			 * of Z inverses 0 .. i, Z values 0 .. i - 1). */
1269c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root			if (!group->meth->field_mul(group, tmp_Z, prod_Z[i - 1], tmp, ctx)) goto err;
1270c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root			/* Update tmp to satisfy the loop invariant for i - 1. */
1271c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root			if (!group->meth->field_mul(group, tmp, tmp, &points[i]->Z, ctx)) goto err;
1272c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root			/* Replace points[i]->Z by its inverse. */
1273c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root			if (!BN_copy(&points[i]->Z, tmp_Z)) goto err;
1274656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
1275656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
1276656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1277c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root	if (!BN_is_zero(&points[0]->Z))
1278c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		{
1279c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		/* Replace points[0]->Z by its inverse. */
1280c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		if (!BN_copy(&points[0]->Z, tmp)) goto err;
1281c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		}
1282c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root
1283c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root	/* Finally, fix up the X and Y coordinates for all points. */
1284c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root
1285656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	for (i = 0; i < num; i++)
1286656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
1287656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		EC_POINT *p = points[i];
1288c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root
1289656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		if (!BN_is_zero(&p->Z))
1290656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
1291656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			/* turn  (X, Y, 1/Z)  into  (X/Z^2, Y/Z^3, 1) */
1292656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1293c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root			if (!group->meth->field_sqr(group, tmp, &p->Z, ctx)) goto err;
1294c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root			if (!group->meth->field_mul(group, &p->X, &p->X, tmp, ctx)) goto err;
1295c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root
1296c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root			if (!group->meth->field_mul(group, tmp, tmp, &p->Z, ctx)) goto err;
1297c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root			if (!group->meth->field_mul(group, &p->Y, &p->Y, tmp, ctx)) goto err;
1298656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1299656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			if (group->meth->field_set_to_one != 0)
1300656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				{
1301656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				if (!group->meth->field_set_to_one(group, &p->Z, ctx)) goto err;
1302656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				}
1303656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			else
1304656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				{
1305656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				if (!BN_one(&p->Z)) goto err;
1306656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project				}
1307656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			p->Z_is_one = 1;
1308656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
1309656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
1310656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1311656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	ret = 1;
1312c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root
1313656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project err:
1314656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	BN_CTX_end(ctx);
1315656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	if (new_ctx != NULL)
1316656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		BN_CTX_free(new_ctx);
1317c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root	if (prod_Z != NULL)
1318656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		{
1319c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		for (i = 0; i < num; i++)
1320656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			{
1321c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root			if (prod_Z[i] == NULL) break;
1322c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root			BN_clear_free(prod_Z[i]);
1323656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project			}
1324c64f6fe2be99cb3fa8e491b5bede9a217de87a4cKenny Root		OPENSSL_free(prod_Z);
1325656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project		}
1326656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return ret;
1327656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
1328656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1329656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1330656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
1331656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
1332656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return BN_mod_mul(r, a, b, &group->field, ctx);
1333656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
1334656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1335656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
1336656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectint ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
1337656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	{
1338656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	return BN_mod_sqr(r, a, &group->field, ctx);
1339656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project	}
1340