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