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