1/* 2 * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved. 3 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved 4 * 5 * Licensed under the Apache License 2.0 (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/* 12 * ECDSA low level APIs are deprecated for public use, but still ok for 13 * internal use. 14 */ 15#include "internal/deprecated.h" 16 17#include <openssl/err.h> 18 19#include "ec_local.h" 20 21const EC_METHOD *EC_GFp_mont_method(void) 22{ 23 static const EC_METHOD ret = { 24 EC_FLAGS_DEFAULT_OCT, 25 NID_X9_62_prime_field, 26 ossl_ec_GFp_mont_group_init, 27 ossl_ec_GFp_mont_group_finish, 28 ossl_ec_GFp_mont_group_clear_finish, 29 ossl_ec_GFp_mont_group_copy, 30 ossl_ec_GFp_mont_group_set_curve, 31 ossl_ec_GFp_simple_group_get_curve, 32 ossl_ec_GFp_simple_group_get_degree, 33 ossl_ec_group_simple_order_bits, 34 ossl_ec_GFp_simple_group_check_discriminant, 35 ossl_ec_GFp_simple_point_init, 36 ossl_ec_GFp_simple_point_finish, 37 ossl_ec_GFp_simple_point_clear_finish, 38 ossl_ec_GFp_simple_point_copy, 39 ossl_ec_GFp_simple_point_set_to_infinity, 40 ossl_ec_GFp_simple_point_set_affine_coordinates, 41 ossl_ec_GFp_simple_point_get_affine_coordinates, 42 0, 0, 0, 43 ossl_ec_GFp_simple_add, 44 ossl_ec_GFp_simple_dbl, 45 ossl_ec_GFp_simple_invert, 46 ossl_ec_GFp_simple_is_at_infinity, 47 ossl_ec_GFp_simple_is_on_curve, 48 ossl_ec_GFp_simple_cmp, 49 ossl_ec_GFp_simple_make_affine, 50 ossl_ec_GFp_simple_points_make_affine, 51 0 /* mul */ , 52 0 /* precompute_mult */ , 53 0 /* have_precompute_mult */ , 54 ossl_ec_GFp_mont_field_mul, 55 ossl_ec_GFp_mont_field_sqr, 56 0 /* field_div */ , 57 ossl_ec_GFp_mont_field_inv, 58 ossl_ec_GFp_mont_field_encode, 59 ossl_ec_GFp_mont_field_decode, 60 ossl_ec_GFp_mont_field_set_to_one, 61 ossl_ec_key_simple_priv2oct, 62 ossl_ec_key_simple_oct2priv, 63 0, /* set private */ 64 ossl_ec_key_simple_generate_key, 65 ossl_ec_key_simple_check_key, 66 ossl_ec_key_simple_generate_public_key, 67 0, /* keycopy */ 68 0, /* keyfinish */ 69 ossl_ecdh_simple_compute_key, 70 ossl_ecdsa_simple_sign_setup, 71 ossl_ecdsa_simple_sign_sig, 72 ossl_ecdsa_simple_verify_sig, 73 0, /* field_inverse_mod_ord */ 74 ossl_ec_GFp_simple_blind_coordinates, 75 ossl_ec_GFp_simple_ladder_pre, 76 ossl_ec_GFp_simple_ladder_step, 77 ossl_ec_GFp_simple_ladder_post 78 }; 79 80 return &ret; 81} 82 83int ossl_ec_GFp_mont_group_init(EC_GROUP *group) 84{ 85 int ok; 86 87 ok = ossl_ec_GFp_simple_group_init(group); 88 group->field_data1 = NULL; 89 group->field_data2 = NULL; 90 return ok; 91} 92 93void ossl_ec_GFp_mont_group_finish(EC_GROUP *group) 94{ 95 BN_MONT_CTX_free(group->field_data1); 96 group->field_data1 = NULL; 97 BN_free(group->field_data2); 98 group->field_data2 = NULL; 99 ossl_ec_GFp_simple_group_finish(group); 100} 101 102void ossl_ec_GFp_mont_group_clear_finish(EC_GROUP *group) 103{ 104 BN_MONT_CTX_free(group->field_data1); 105 group->field_data1 = NULL; 106 BN_clear_free(group->field_data2); 107 group->field_data2 = NULL; 108 ossl_ec_GFp_simple_group_clear_finish(group); 109} 110 111int ossl_ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src) 112{ 113 BN_MONT_CTX_free(dest->field_data1); 114 dest->field_data1 = NULL; 115 BN_clear_free(dest->field_data2); 116 dest->field_data2 = NULL; 117 118 if (!ossl_ec_GFp_simple_group_copy(dest, src)) 119 return 0; 120 121 if (src->field_data1 != NULL) { 122 dest->field_data1 = BN_MONT_CTX_new(); 123 if (dest->field_data1 == NULL) 124 return 0; 125 if (!BN_MONT_CTX_copy(dest->field_data1, src->field_data1)) 126 goto err; 127 } 128 if (src->field_data2 != NULL) { 129 dest->field_data2 = BN_dup(src->field_data2); 130 if (dest->field_data2 == NULL) 131 goto err; 132 } 133 134 return 1; 135 136 err: 137 BN_MONT_CTX_free(dest->field_data1); 138 dest->field_data1 = NULL; 139 return 0; 140} 141 142int ossl_ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, 143 const BIGNUM *a, const BIGNUM *b, 144 BN_CTX *ctx) 145{ 146 BN_CTX *new_ctx = NULL; 147 BN_MONT_CTX *mont = NULL; 148 BIGNUM *one = NULL; 149 int ret = 0; 150 151 BN_MONT_CTX_free(group->field_data1); 152 group->field_data1 = NULL; 153 BN_free(group->field_data2); 154 group->field_data2 = NULL; 155 156 if (ctx == NULL) { 157 ctx = new_ctx = BN_CTX_new_ex(group->libctx); 158 if (ctx == NULL) 159 return 0; 160 } 161 162 mont = BN_MONT_CTX_new(); 163 if (mont == NULL) 164 goto err; 165 if (!BN_MONT_CTX_set(mont, p, ctx)) { 166 ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); 167 goto err; 168 } 169 one = BN_new(); 170 if (one == NULL) 171 goto err; 172 if (!BN_to_montgomery(one, BN_value_one(), mont, ctx)) 173 goto err; 174 175 group->field_data1 = mont; 176 mont = NULL; 177 group->field_data2 = one; 178 one = NULL; 179 180 ret = ossl_ec_GFp_simple_group_set_curve(group, p, a, b, ctx); 181 182 if (!ret) { 183 BN_MONT_CTX_free(group->field_data1); 184 group->field_data1 = NULL; 185 BN_free(group->field_data2); 186 group->field_data2 = NULL; 187 } 188 189 err: 190 BN_free(one); 191 BN_CTX_free(new_ctx); 192 BN_MONT_CTX_free(mont); 193 return ret; 194} 195 196int ossl_ec_GFp_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, 197 const BIGNUM *b, BN_CTX *ctx) 198{ 199 if (group->field_data1 == NULL) { 200 ERR_raise(ERR_LIB_EC, EC_R_NOT_INITIALIZED); 201 return 0; 202 } 203 204 return BN_mod_mul_montgomery(r, a, b, group->field_data1, ctx); 205} 206 207int ossl_ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, 208 BN_CTX *ctx) 209{ 210 if (group->field_data1 == NULL) { 211 ERR_raise(ERR_LIB_EC, EC_R_NOT_INITIALIZED); 212 return 0; 213 } 214 215 return BN_mod_mul_montgomery(r, a, a, group->field_data1, ctx); 216} 217 218/*- 219 * Computes the multiplicative inverse of a in GF(p), storing the result in r. 220 * If a is zero (or equivalent), you'll get a EC_R_CANNOT_INVERT error. 221 * We have a Mont structure, so SCA hardening is FLT inversion. 222 */ 223int ossl_ec_GFp_mont_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, 224 BN_CTX *ctx) 225{ 226 BIGNUM *e = NULL; 227 BN_CTX *new_ctx = NULL; 228 int ret = 0; 229 230 if (group->field_data1 == NULL) 231 return 0; 232 233 if (ctx == NULL 234 && (ctx = new_ctx = BN_CTX_secure_new_ex(group->libctx)) == NULL) 235 return 0; 236 237 BN_CTX_start(ctx); 238 if ((e = BN_CTX_get(ctx)) == NULL) 239 goto err; 240 241 /* Inverse in constant time with Fermats Little Theorem */ 242 if (!BN_set_word(e, 2)) 243 goto err; 244 if (!BN_sub(e, group->field, e)) 245 goto err; 246 /*- 247 * Exponent e is public. 248 * No need for scatter-gather or BN_FLG_CONSTTIME. 249 */ 250 if (!BN_mod_exp_mont(r, a, e, group->field, ctx, group->field_data1)) 251 goto err; 252 253 /* throw an error on zero */ 254 if (BN_is_zero(r)) { 255 ERR_raise(ERR_LIB_EC, EC_R_CANNOT_INVERT); 256 goto err; 257 } 258 259 ret = 1; 260 261 err: 262 BN_CTX_end(ctx); 263 BN_CTX_free(new_ctx); 264 return ret; 265} 266 267int ossl_ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r, 268 const BIGNUM *a, BN_CTX *ctx) 269{ 270 if (group->field_data1 == NULL) { 271 ERR_raise(ERR_LIB_EC, EC_R_NOT_INITIALIZED); 272 return 0; 273 } 274 275 return BN_to_montgomery(r, a, (BN_MONT_CTX *)group->field_data1, ctx); 276} 277 278int ossl_ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, 279 const BIGNUM *a, BN_CTX *ctx) 280{ 281 if (group->field_data1 == NULL) { 282 ERR_raise(ERR_LIB_EC, EC_R_NOT_INITIALIZED); 283 return 0; 284 } 285 286 return BN_from_montgomery(r, a, group->field_data1, ctx); 287} 288 289int ossl_ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r, 290 BN_CTX *ctx) 291{ 292 if (group->field_data2 == NULL) { 293 ERR_raise(ERR_LIB_EC, EC_R_NOT_INITIALIZED); 294 return 0; 295 } 296 297 if (!BN_copy(r, group->field_data2)) 298 return 0; 299 return 1; 300} 301