ecp_mont.c revision 160815
1239268Sgonzo/* crypto/ec/ecp_mont.c */ 2289865Sian/* 3239268Sgonzo * Originally written by Bodo Moeller for the OpenSSL project. 4239268Sgonzo */ 5239268Sgonzo/* ==================================================================== 6239268Sgonzo * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. 7239268Sgonzo * 8239268Sgonzo * Redistribution and use in source and binary forms, with or without 9239268Sgonzo * modification, are permitted provided that the following conditions 10239268Sgonzo * are met: 11239268Sgonzo * 12239268Sgonzo * 1. Redistributions of source code must retain the above copyright 13239268Sgonzo * notice, this list of conditions and the following disclaimer. 14239268Sgonzo * 15239268Sgonzo * 2. Redistributions in binary form must reproduce the above copyright 16239268Sgonzo * notice, this list of conditions and the following disclaimer in 17239268Sgonzo * the documentation and/or other materials provided with the 18239268Sgonzo * distribution. 19239268Sgonzo * 20239268Sgonzo * 3. All advertising materials mentioning features or use of this 21239268Sgonzo * software must display the following acknowledgment: 22239268Sgonzo * "This product includes software developed by the OpenSSL Project 23239268Sgonzo * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 24239268Sgonzo * 25239268Sgonzo * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26239268Sgonzo * endorse or promote products derived from this software without 27239268Sgonzo * prior written permission. For written permission, please contact 28239268Sgonzo * openssl-core@openssl.org. 29239268Sgonzo * 30239268Sgonzo * 5. Products derived from this software may not be called "OpenSSL" 31239268Sgonzo * nor may "OpenSSL" appear in their names without prior written 32239268Sgonzo * permission of the OpenSSL Project. 33239268Sgonzo * 34239268Sgonzo * 6. Redistributions of any form whatsoever must retain the following 35239268Sgonzo * acknowledgment: 36239268Sgonzo * "This product includes software developed by the OpenSSL Project 37239268Sgonzo * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 38239268Sgonzo * 39239268Sgonzo * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40239268Sgonzo * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41244469Scognet * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42269321Sian * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43239268Sgonzo * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44239268Sgonzo * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45239268Sgonzo * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46239268Sgonzo * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47246713Skib * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48239268Sgonzo * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49239268Sgonzo * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50246713Skib * OF THE POSSIBILITY OF SUCH DAMAGE. 51239268Sgonzo * ==================================================================== 52239268Sgonzo * 53239268Sgonzo * This product includes cryptographic software written by Eric Young 54239268Sgonzo * (eay@cryptsoft.com). This product includes software written by Tim 55239268Sgonzo * Hudson (tjh@cryptsoft.com). 56244469Scognet * 57244469Scognet */ 58239268Sgonzo/* ==================================================================== 59239268Sgonzo * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. 60239268Sgonzo * Portions of this software developed by SUN MICROSYSTEMS, INC., 61289759Sjah * and contributed to the OpenSSL project. 62239268Sgonzo */ 63239268Sgonzo 64289851Sian#include <openssl/err.h> 65289851Sian 66289851Sian#include "ec_lcl.h" 67289851Sian 68289851Sian 69289851Sianconst EC_METHOD *EC_GFp_mont_method(void) 70239268Sgonzo { 71239268Sgonzo static const EC_METHOD ret = { 72239268Sgonzo NID_X9_62_prime_field, 73239268Sgonzo ec_GFp_mont_group_init, 74289851Sian ec_GFp_mont_group_finish, 75289851Sian ec_GFp_mont_group_clear_finish, 76289854Sian ec_GFp_mont_group_copy, 77289851Sian ec_GFp_mont_group_set_curve, 78289851Sian ec_GFp_simple_group_get_curve, 79289851Sian ec_GFp_simple_group_get_degree, 80289851Sian ec_GFp_simple_group_check_discriminant, 81289851Sian ec_GFp_simple_point_init, 82289851Sian ec_GFp_simple_point_finish, 83289851Sian ec_GFp_simple_point_clear_finish, 84289851Sian ec_GFp_simple_point_copy, 85289851Sian ec_GFp_simple_point_set_to_infinity, 86289851Sian ec_GFp_simple_set_Jprojective_coordinates_GFp, 87289851Sian ec_GFp_simple_get_Jprojective_coordinates_GFp, 88289851Sian ec_GFp_simple_point_set_affine_coordinates, 89289851Sian ec_GFp_simple_point_get_affine_coordinates, 90239268Sgonzo ec_GFp_simple_set_compressed_coordinates, 91239268Sgonzo ec_GFp_simple_point2oct, 92239268Sgonzo ec_GFp_simple_oct2point, 93239268Sgonzo ec_GFp_simple_add, 94239268Sgonzo ec_GFp_simple_dbl, 95239268Sgonzo ec_GFp_simple_invert, 96239268Sgonzo ec_GFp_simple_is_at_infinity, 97239268Sgonzo ec_GFp_simple_is_on_curve, 98239268Sgonzo ec_GFp_simple_cmp, 99239268Sgonzo ec_GFp_simple_make_affine, 100239268Sgonzo ec_GFp_simple_points_make_affine, 101239268Sgonzo 0 /* mul */, 102239268Sgonzo 0 /* precompute_mult */, 103239268Sgonzo 0 /* have_precompute_mult */, 104289759Sjah ec_GFp_mont_field_mul, 105289759Sjah ec_GFp_mont_field_sqr, 106239268Sgonzo 0 /* field_div */, 107239268Sgonzo ec_GFp_mont_field_encode, 108239268Sgonzo ec_GFp_mont_field_decode, 109239268Sgonzo ec_GFp_mont_field_set_to_one }; 110239268Sgonzo 111286968Sian return &ret; 112289759Sjah } 113289759Sjah 114239268Sgonzo 115239268Sgonzoint ec_GFp_mont_group_init(EC_GROUP *group) 116239268Sgonzo { 117239268Sgonzo int ok; 118239268Sgonzo 119239268Sgonzo ok = ec_GFp_simple_group_init(group); 120239268Sgonzo group->field_data1 = NULL; 121239268Sgonzo group->field_data2 = NULL; 122239268Sgonzo return ok; 123239268Sgonzo } 124239268Sgonzo 125239268Sgonzo 126239268Sgonzovoid ec_GFp_mont_group_finish(EC_GROUP *group) 127239268Sgonzo { 128239268Sgonzo if (group->field_data1 != NULL) 129239268Sgonzo { 130239268Sgonzo BN_MONT_CTX_free(group->field_data1); 131239268Sgonzo group->field_data1 = NULL; 132239268Sgonzo } 133239268Sgonzo if (group->field_data2 != NULL) 134239268Sgonzo { 135239268Sgonzo BN_free(group->field_data2); 136239268Sgonzo group->field_data2 = NULL; 137239268Sgonzo } 138239268Sgonzo ec_GFp_simple_group_finish(group); 139239268Sgonzo } 140269217Sian 141269217Sian 142269217Sianvoid ec_GFp_mont_group_clear_finish(EC_GROUP *group) 143269217Sian { 144269321Sian if (group->field_data1 != NULL) 145269321Sian { 146269321Sian BN_MONT_CTX_free(group->field_data1); 147269321Sian group->field_data1 = NULL; 148269321Sian } 149269321Sian if (group->field_data2 != NULL) 150269217Sian { 151239268Sgonzo BN_clear_free(group->field_data2); 152239268Sgonzo group->field_data2 = NULL; 153239268Sgonzo } 154269217Sian ec_GFp_simple_group_clear_finish(group); 155269321Sian } 156269217Sian 157269321Sian 158269217Sianint ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src) 159269321Sian { 160269217Sian if (dest->field_data1 != NULL) 161269321Sian { 162283366Sandrew BN_MONT_CTX_free(dest->field_data1); 163269321Sian dest->field_data1 = NULL; 164269321Sian } 165269321Sian if (dest->field_data2 != NULL) 166269321Sian { 167269321Sian BN_clear_free(dest->field_data2); 168269321Sian dest->field_data2 = NULL; 169269321Sian } 170269321Sian 171269321Sian if (!ec_GFp_simple_group_copy(dest, src)) return 0; 172269321Sian 173269321Sian if (src->field_data1 != NULL) 174239268Sgonzo { 175269321Sian dest->field_data1 = BN_MONT_CTX_new(); 176239268Sgonzo if (dest->field_data1 == NULL) return 0; 177239268Sgonzo if (!BN_MONT_CTX_copy(dest->field_data1, src->field_data1)) goto err; 178289851Sian } 179289851Sian if (src->field_data2 != NULL) 180289851Sian { 181289851Sian dest->field_data2 = BN_dup(src->field_data2); 182289851Sian if (dest->field_data2 == NULL) goto err; 183289851Sian } 184289851Sian 185289851Sian return 1; 186289851Sian 187289851Sian err: 188289851Sian if (dest->field_data1 != NULL) 189239268Sgonzo { 190269216Sian BN_MONT_CTX_free(dest->field_data1); 191289851Sian dest->field_data1 = NULL; 192289851Sian } 193239268Sgonzo return 0; 194239268Sgonzo } 195239268Sgonzo 196239268Sgonzo 197239268Sgonzoint ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) 198239268Sgonzo { 199239268Sgonzo BN_CTX *new_ctx = NULL; 200239268Sgonzo BN_MONT_CTX *mont = NULL; 201239268Sgonzo BIGNUM *one = NULL; 202289851Sian int ret = 0; 203239268Sgonzo 204289851Sian if (group->field_data1 != NULL) 205239268Sgonzo { 206289759Sjah BN_MONT_CTX_free(group->field_data1); 207289759Sjah group->field_data1 = NULL; 208246713Skib } 209246713Skib if (group->field_data2 != NULL) 210246713Skib { 211246713Skib BN_free(group->field_data2); 212289759Sjah group->field_data2 = NULL; 213289759Sjah } 214239268Sgonzo 215244469Scognet if (ctx == NULL) 216244469Scognet { 217289858Sian ctx = new_ctx = BN_CTX_new(); 218289858Sian if (ctx == NULL) 219289858Sian return 0; 220289858Sian } 221244469Scognet 222244469Scognet mont = BN_MONT_CTX_new(); 223244469Scognet if (mont == NULL) goto err; 224252652Sgonzo if (!BN_MONT_CTX_set(mont, p, ctx)) 225244469Scognet { 226269321Sian ECerr(EC_F_EC_GFP_MONT_GROUP_SET_CURVE, ERR_R_BN_LIB); 227269321Sian goto err; 228269321Sian } 229269321Sian one = BN_new(); 230269321Sian if (one == NULL) goto err; 231269321Sian if (!BN_to_montgomery(one, BN_value_one(), mont, ctx)) goto err; 232269321Sian 233252652Sgonzo group->field_data1 = mont; 234252652Sgonzo mont = NULL; 235244469Scognet group->field_data2 = one; 236283366Sandrew one = NULL; 237244469Scognet 238283366Sandrew ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); 239244469Scognet 240252652Sgonzo if (!ret) 241244469Scognet { 242252652Sgonzo BN_MONT_CTX_free(group->field_data1); 243283366Sandrew group->field_data1 = NULL; 244252652Sgonzo BN_free(group->field_data2); 245252652Sgonzo group->field_data2 = NULL; 246252652Sgonzo } 247252652Sgonzo 248252652Sgonzo err: 249252652Sgonzo if (new_ctx != NULL) 250252652Sgonzo BN_CTX_free(new_ctx); 251244469Scognet if (mont != NULL) 252244469Scognet BN_MONT_CTX_free(mont); 253244469Scognet return ret; 254244469Scognet } 255244469Scognet 256244469Scognet 257283366Sandrewint ec_GFp_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) 258283366Sandrew { 259252652Sgonzo if (group->field_data1 == NULL) 260244469Scognet { 261244469Scognet ECerr(EC_F_EC_GFP_MONT_FIELD_MUL, EC_R_NOT_INITIALIZED); 262244469Scognet return 0; 263244469Scognet } 264289858Sian 265269321Sian return BN_mod_mul_montgomery(r, a, b, group->field_data1, ctx); 266269321Sian } 267244469Scognet 268269321Sian 269244469Scognetint ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) 270269136Sian { 271269136Sian if (group->field_data1 == NULL) 272269136Sian { 273269136Sian ECerr(EC_F_EC_GFP_MONT_FIELD_SQR, EC_R_NOT_INITIALIZED); 274269136Sian return 0; 275269136Sian } 276269136Sian 277269136Sian return BN_mod_mul_montgomery(r, a, a, group->field_data1, ctx); 278269136Sian } 279269136Sian 280269136Sian 281269136Sianint ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) 282269206Sian { 283269207Sian if (group->field_data1 == NULL) 284239268Sgonzo { 285239268Sgonzo ECerr(EC_F_EC_GFP_MONT_FIELD_ENCODE, EC_R_NOT_INITIALIZED); 286269136Sian return 0; 287269136Sian } 288269136Sian 289269136Sian return BN_to_montgomery(r, a, (BN_MONT_CTX *)group->field_data1, ctx); 290239268Sgonzo } 291269209Sian 292269209Sian 293239268Sgonzoint ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) 294239268Sgonzo { 295239268Sgonzo if (group->field_data1 == NULL) 296239268Sgonzo { 297239268Sgonzo ECerr(EC_F_EC_GFP_MONT_FIELD_DECODE, EC_R_NOT_INITIALIZED); 298269206Sian return 0; 299269207Sian } 300269207Sian 301269207Sian return BN_from_montgomery(r, a, group->field_data1, ctx); 302269207Sian } 303269207Sian 304269207Sian 305269207Sianint ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r, BN_CTX *ctx) 306269207Sian { 307269207Sian if (group->field_data2 == NULL) 308269207Sian { 309269206Sian ECerr(EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE, EC_R_NOT_INITIALIZED); 310269206Sian return 0; 311269206Sian } 312269206Sian 313269206Sian if (!BN_copy(r, group->field_data2)) return 0; 314269206Sian return 1; 315269206Sian } 316269206Sian