1 /* 2 * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. 3 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved 4 * 5 * Licensed under the OpenSSL license (the "License"). You may not use 6 * this file except in compliance with the License. You can obtain a copy 7 * in the file LICENSE in the source distribution or at 8 * https://www.openssl.org/source/license.html 9 */ 10 11 #include <openssl/err.h> 12 13 #include "ec_lcl.h" 14 15 const EC_METHOD *EC_GFp_mont_method(void) 16 { 17 static const EC_METHOD ret = { 18 EC_FLAGS_DEFAULT_OCT, 19 NID_X9_62_prime_field, 20 ec_GFp_mont_group_init, 21 ec_GFp_mont_group_finish, 22 ec_GFp_mont_group_clear_finish, 23 ec_GFp_mont_group_copy, 24 ec_GFp_mont_group_set_curve, 25 ec_GFp_simple_group_get_curve, 26 ec_GFp_simple_group_get_degree, 27 ec_group_simple_order_bits, 28 ec_GFp_simple_group_check_discriminant, 29 ec_GFp_simple_point_init, 30 ec_GFp_simple_point_finish, 31 ec_GFp_simple_point_clear_finish, 32 ec_GFp_simple_point_copy, 33 ec_GFp_simple_point_set_to_infinity, 34 ec_GFp_simple_set_Jprojective_coordinates_GFp, 35 ec_GFp_simple_get_Jprojective_coordinates_GFp, 36 ec_GFp_simple_point_set_affine_coordinates, 37 ec_GFp_simple_point_get_affine_coordinates, 38 0, 0, 0, 39 ec_GFp_simple_add, 40 ec_GFp_simple_dbl, 41 ec_GFp_simple_invert, 42 ec_GFp_simple_is_at_infinity, 43 ec_GFp_simple_is_on_curve, 44 ec_GFp_simple_cmp, 45 ec_GFp_simple_make_affine, 46 ec_GFp_simple_points_make_affine, 47 0 /* mul */ , 48 0 /* precompute_mult */ , 49 0 /* have_precompute_mult */ , 50 ec_GFp_mont_field_mul, 51 ec_GFp_mont_field_sqr, 52 0 /* field_div */ , 53 ec_GFp_mont_field_encode, 54 ec_GFp_mont_field_decode, 55 ec_GFp_mont_field_set_to_one, 56 ec_key_simple_priv2oct, 57 ec_key_simple_oct2priv, 58 0, /* set private */ 59 ec_key_simple_generate_key, 60 ec_key_simple_check_key, 61 ec_key_simple_generate_public_key, 62 0, /* keycopy */ 63 0, /* keyfinish */ 64 ecdh_simple_compute_key, 65 0, /* field_inverse_mod_ord */ 66 ec_GFp_simple_blind_coordinates, 67 ec_GFp_simple_ladder_pre, 68 ec_GFp_simple_ladder_step, 69 ec_GFp_simple_ladder_post 70 }; 71 72 return &ret; 73 } 74 75 int ec_GFp_mont_group_init(EC_GROUP *group) 76 { 77 int ok; 78 79 ok = ec_GFp_simple_group_init(group); 80 group->field_data1 = NULL; 81 group->field_data2 = NULL; 82 return ok; 83 } 84 85 void ec_GFp_mont_group_finish(EC_GROUP *group) 86 { 87 BN_MONT_CTX_free(group->field_data1); 88 group->field_data1 = NULL; 89 BN_free(group->field_data2); 90 group->field_data2 = NULL; 91 ec_GFp_simple_group_finish(group); 92 } 93 94 void ec_GFp_mont_group_clear_finish(EC_GROUP *group) 95 { 96 BN_MONT_CTX_free(group->field_data1); 97 group->field_data1 = NULL; 98 BN_clear_free(group->field_data2); 99 group->field_data2 = NULL; 100 ec_GFp_simple_group_clear_finish(group); 101 } 102 103 int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src) 104 { 105 BN_MONT_CTX_free(dest->field_data1); 106 dest->field_data1 = NULL; 107 BN_clear_free(dest->field_data2); 108 dest->field_data2 = NULL; 109 110 if (!ec_GFp_simple_group_copy(dest, src)) 111 return 0; 112 113 if (src->field_data1 != NULL) { 114 dest->field_data1 = BN_MONT_CTX_new(); 115 if (dest->field_data1 == NULL) 116 return 0; 117 if (!BN_MONT_CTX_copy(dest->field_data1, src->field_data1)) 118 goto err; 119 } 120 if (src->field_data2 != NULL) { 121 dest->field_data2 = BN_dup(src->field_data2); 122 if (dest->field_data2 == NULL) 123 goto err; 124 } 125 126 return 1; 127 128 err: 129 BN_MONT_CTX_free(dest->field_data1); 130 dest->field_data1 = NULL; 131 return 0; 132 } 133 134 int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, 135 const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) 136 { 137 BN_CTX *new_ctx = NULL; 138 BN_MONT_CTX *mont = NULL; 139 BIGNUM *one = NULL; 140 int ret = 0; 141 142 BN_MONT_CTX_free(group->field_data1); 143 group->field_data1 = NULL; 144 BN_free(group->field_data2); 145 group->field_data2 = NULL; 146 147 if (ctx == NULL) { 148 ctx = new_ctx = BN_CTX_new(); 149 if (ctx == NULL) 150 return 0; 151 } 152 153 mont = BN_MONT_CTX_new(); 154 if (mont == NULL) 155 goto err; 156 if (!BN_MONT_CTX_set(mont, p, ctx)) { 157 ECerr(EC_F_EC_GFP_MONT_GROUP_SET_CURVE, ERR_R_BN_LIB); 158 goto err; 159 } 160 one = BN_new(); 161 if (one == NULL) 162 goto err; 163 if (!BN_to_montgomery(one, BN_value_one(), mont, ctx)) 164 goto err; 165 166 group->field_data1 = mont; 167 mont = NULL; 168 group->field_data2 = one; 169 one = NULL; 170 171 ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); 172 173 if (!ret) { 174 BN_MONT_CTX_free(group->field_data1); 175 group->field_data1 = NULL; 176 BN_free(group->field_data2); 177 group->field_data2 = NULL; 178 } 179 180 err: 181 BN_free(one); 182 BN_CTX_free(new_ctx); 183 BN_MONT_CTX_free(mont); 184 return ret; 185 } 186 187 int ec_GFp_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, 188 const BIGNUM *b, BN_CTX *ctx) 189 { 190 if (group->field_data1 == NULL) { 191 ECerr(EC_F_EC_GFP_MONT_FIELD_MUL, EC_R_NOT_INITIALIZED); 192 return 0; 193 } 194 195 return BN_mod_mul_montgomery(r, a, b, group->field_data1, ctx); 196 } 197 198 int ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, 199 BN_CTX *ctx) 200 { 201 if (group->field_data1 == NULL) { 202 ECerr(EC_F_EC_GFP_MONT_FIELD_SQR, EC_R_NOT_INITIALIZED); 203 return 0; 204 } 205 206 return BN_mod_mul_montgomery(r, a, a, group->field_data1, ctx); 207 } 208 209 int ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r, 210 const BIGNUM *a, BN_CTX *ctx) 211 { 212 if (group->field_data1 == NULL) { 213 ECerr(EC_F_EC_GFP_MONT_FIELD_ENCODE, EC_R_NOT_INITIALIZED); 214 return 0; 215 } 216 217 return BN_to_montgomery(r, a, (BN_MONT_CTX *)group->field_data1, ctx); 218 } 219 220 int ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, 221 const BIGNUM *a, BN_CTX *ctx) 222 { 223 if (group->field_data1 == NULL) { 224 ECerr(EC_F_EC_GFP_MONT_FIELD_DECODE, EC_R_NOT_INITIALIZED); 225 return 0; 226 } 227 228 return BN_from_montgomery(r, a, group->field_data1, ctx); 229 } 230 231 int ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r, 232 BN_CTX *ctx) 233 { 234 if (group->field_data2 == NULL) { 235 ECerr(EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE, EC_R_NOT_INITIALIZED); 236 return 0; 237 } 238 239 if (!BN_copy(r, group->field_data2)) 240 return 0; 241 return 1; 242 } 243