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