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